home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-i386 / desc.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  4.2 KB  |  168 lines

  1. #ifndef __ARCH_DESC_H
  2. #define __ARCH_DESC_H
  3.  
  4. #include <asm/ldt.h>
  5. #include <asm/segment.h>
  6.  
  7. #define CPU_16BIT_STACK_SIZE 1024
  8.  
  9. #ifndef __ASSEMBLY__
  10.  
  11. #include <linux/preempt.h>
  12. #include <linux/smp.h>
  13. #include <linux/percpu.h>
  14.  
  15. #include <asm/mmu.h>
  16.  
  17. extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
  18.  
  19. DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
  20.  
  21. struct Xgt_desc_struct {
  22.     unsigned short size;
  23.     unsigned long address __attribute__((packed));
  24.     unsigned short pad;
  25. } __attribute__ ((packed));
  26.  
  27. extern struct Xgt_desc_struct idt_descr;
  28. DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
  29.  
  30.  
  31. static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
  32. {
  33.     return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
  34. }
  35.  
  36. #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
  37. #define load_LDT_desc() __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8))
  38.  
  39. #define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
  40. #define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
  41. #define load_tr(tr) __asm__ __volatile("ltr %0"::"mr" (tr))
  42. #define load_ldt(ldt) __asm__ __volatile("lldt %0"::"mr" (ldt))
  43.  
  44. #define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr))
  45. #define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr))
  46. #define store_tr(tr) __asm__ ("str %0":"=mr" (tr))
  47. #define store_ldt(ldt) __asm__ ("sldt %0":"=mr" (ldt))
  48.  
  49. /*
  50.  * This is the ldt that every process will get unless we need
  51.  * something other than this.
  52.  */
  53. extern struct desc_struct default_ldt[];
  54. extern void set_intr_gate(unsigned int irq, void * addr);
  55.  
  56. #define _set_tssldt_desc(n,addr,limit,type) \
  57. __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
  58.     "movw %w1,2(%2)\n\t" \
  59.     "rorl $16,%1\n\t" \
  60.     "movb %b1,4(%2)\n\t" \
  61.     "movb %4,5(%2)\n\t" \
  62.     "movb $0,6(%2)\n\t" \
  63.     "movb %h1,7(%2)\n\t" \
  64.     "rorl $16,%1" \
  65.     : "=m"(*(n)) : "q" (addr), "r"(n), "ir"(limit), "i"(type))
  66.  
  67. static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
  68. {
  69.     _set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr,
  70.         offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
  71. }
  72.  
  73. #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
  74.  
  75. static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
  76. {
  77.     _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
  78. }
  79.  
  80. #define LDT_entry_a(info) \
  81.     ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
  82.  
  83. #define LDT_entry_b(info) \
  84.     (((info)->base_addr & 0xff000000) | \
  85.     (((info)->base_addr & 0x00ff0000) >> 16) | \
  86.     ((info)->limit & 0xf0000) | \
  87.     (((info)->read_exec_only ^ 1) << 9) | \
  88.     ((info)->contents << 10) | \
  89.     (((info)->seg_not_present ^ 1) << 15) | \
  90.     ((info)->seg_32bit << 22) | \
  91.     ((info)->limit_in_pages << 23) | \
  92.     ((info)->useable << 20) | \
  93.     0x7000)
  94.  
  95. #define LDT_empty(info) (\
  96.     (info)->base_addr    == 0    && \
  97.     (info)->limit        == 0    && \
  98.     (info)->contents    == 0    && \
  99.     (info)->read_exec_only    == 1    && \
  100.     (info)->seg_32bit    == 0    && \
  101.     (info)->limit_in_pages    == 0    && \
  102.     (info)->seg_not_present    == 1    && \
  103.     (info)->useable        == 0    )
  104.  
  105. static inline void write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b)
  106. {
  107.     __u32 *lp = (__u32 *)((char *)ldt + entry*8);
  108.     *lp = entry_a;
  109.     *(lp+1) = entry_b;
  110. }
  111.  
  112. #if TLS_SIZE != 24
  113. # error update this code.
  114. #endif
  115.  
  116. static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
  117. {
  118. #define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
  119.     C(0); C(1); C(2);
  120. #undef C
  121. }
  122.  
  123. static inline void clear_LDT(void)
  124. {
  125.     int cpu = get_cpu();
  126.  
  127.     set_ldt_desc(cpu, &default_ldt[0], 5);
  128.     load_LDT_desc();
  129.     put_cpu();
  130. }
  131.  
  132. /*
  133.  * load one particular LDT into the current CPU
  134.  */
  135. static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
  136. {
  137.     void *segments = pc->ldt;
  138.     int count = pc->size;
  139.  
  140.     if (likely(!count)) {
  141.         segments = &default_ldt[0];
  142.         count = 5;
  143.     }
  144.         
  145.     set_ldt_desc(cpu, segments, count);
  146.     load_LDT_desc();
  147. }
  148.  
  149. static inline void load_LDT(mm_context_t *pc)
  150. {
  151.     int cpu = get_cpu();
  152.     load_LDT_nolock(pc, cpu);
  153.     put_cpu();
  154. }
  155.  
  156. static inline unsigned long get_desc_base(unsigned long *desc)
  157. {
  158.     unsigned long base;
  159.     base = ((desc[0] >> 16)  & 0x0000ffff) |
  160.         ((desc[1] << 16) & 0x00ff0000) |
  161.         (desc[1] & 0xff000000);
  162.     return base;
  163. }
  164.  
  165. #endif /* !__ASSEMBLY__ */
  166.  
  167. #endif
  168.