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 
clear_LDT(void)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  */
load_LDT(mm_context_t * pc)82 static inline void load_LDT (mm_context_t *pc)
83 {
84 	int cpu = smp_processor_id();
85 	void *segments = pc->ldt;
86 	int count = pc->size;
87 
88 	if (!count) {
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