File: /usr/src/linux/include/asm-i386/desc.h

1     #ifndef __ARCH_DESC_H
2     #define __ARCH_DESC_H
3     
4     #include <asm/ldt.h>
5     
6     /*
7      * The layout of the GDT under Linux:
8      *
9      *   0 - null
10      *   1 - not used
11      *   2 - kernel code segment
12      *   3 - kernel data segment
13      *   4 - user code segment                  <-- new cacheline 
14      *   5 - user data segment
15      *   6 - not used
16      *   7 - not used
17      *   8 - APM BIOS support                   <-- new cacheline 
18      *   9 - APM BIOS support
19      *  10 - APM BIOS support
20      *  11 - APM BIOS support
21      *
22      * The TSS+LDT descriptors are spread out a bit so that every CPU
23      * has an exclusive cacheline for the per-CPU TSS and LDT:
24      *
25      *  12 - CPU#0 TSS                          <-- new cacheline 
26      *  13 - CPU#0 LDT
27      *  14 - not used 
28      *  15 - not used 
29      *  16 - CPU#1 TSS                          <-- new cacheline 
30      *  17 - CPU#1 LDT
31      *  18 - not used 
32      *  19 - not used 
33      *  ... NR_CPUS per-CPU TSS+LDT's if on SMP
34      *
35      * Entry into gdt where to find first TSS.
36      */
37     #define __FIRST_TSS_ENTRY 12
38     #define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY+1)
39     
40     #define __TSS(n) (((n)<<2) + __FIRST_TSS_ENTRY)
41     #define __LDT(n) (((n)<<2) + __FIRST_LDT_ENTRY)
42     
43     #ifndef __ASSEMBLY__
44     struct desc_struct {
45     	unsigned long a,b;
46     };
47     
48     extern struct desc_struct gdt_table[];
49     extern struct desc_struct *idt, *gdt;
50     
51     struct Xgt_desc_struct {
52     	unsigned short size;
53     	unsigned long address __attribute__((packed));
54     };
55     
56     #define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2))
57     #define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2))
58     
59     #define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3))
60     
61     #define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3))
62     
63     /*
64      * This is the ldt that every process will get unless we need
65      * something other than this.
66      */
67     extern struct desc_struct default_ldt[];
68     extern void set_intr_gate(unsigned int irq, void * addr);
69     extern void set_ldt_desc(unsigned int n, void *addr, unsigned int size);
70     extern void set_tss_desc(unsigned int n, void *addr);
71     
72     static inline void clear_LDT(void)
73     {
74     	int cpu = smp_processor_id();
75     	set_ldt_desc(cpu, &default_ldt[0], 5);
76     	__load_LDT(cpu);
77     }
78     
79     /*
80      * load one particular LDT into the current CPU
81      */
82     static inline void load_LDT (struct mm_struct *mm)
83     {
84     	int cpu = smp_processor_id();
85     	void *segments = mm->context.segments;
86     	int count = LDT_ENTRIES;
87     
88     	if (!segments) {
89     		segments = &default_ldt[0];
90     		count = 5;
91     	}
92     		
93     	set_ldt_desc(cpu, segments, count);
94     	__load_LDT(cpu);
95     }
96     
97     #endif /* !__ASSEMBLY__ */
98     
99     #endif
100