diff options
-rw-r--r-- | arch/i386/kernel/traps.c | 24 | ||||
-rw-r--r-- | include/asm-i386/desc.h | 121 |
2 files changed, 81 insertions, 64 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index bdf949c30c7c..00d643f3de41 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -1165,20 +1165,6 @@ void __init trap_init_f00f_bug(void) | |||
1165 | } | 1165 | } |
1166 | #endif | 1166 | #endif |
1167 | 1167 | ||
1168 | #define _set_gate(gate_addr,type,dpl,addr,seg) \ | ||
1169 | do { \ | ||
1170 | int __d0, __d1; \ | ||
1171 | __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \ | ||
1172 | "movw %4,%%dx\n\t" \ | ||
1173 | "movl %%eax,%0\n\t" \ | ||
1174 | "movl %%edx,%1" \ | ||
1175 | :"=m" (*((long *) (gate_addr))), \ | ||
1176 | "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \ | ||
1177 | :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \ | ||
1178 | "3" ((char *) (addr)),"2" ((seg) << 16)); \ | ||
1179 | } while (0) | ||
1180 | |||
1181 | |||
1182 | /* | 1168 | /* |
1183 | * This needs to use 'idt_table' rather than 'idt', and | 1169 | * This needs to use 'idt_table' rather than 'idt', and |
1184 | * thus use the _nonmapped_ version of the IDT, as the | 1170 | * thus use the _nonmapped_ version of the IDT, as the |
@@ -1187,7 +1173,7 @@ do { \ | |||
1187 | */ | 1173 | */ |
1188 | void set_intr_gate(unsigned int n, void *addr) | 1174 | void set_intr_gate(unsigned int n, void *addr) |
1189 | { | 1175 | { |
1190 | _set_gate(idt_table+n,14,0,addr,__KERNEL_CS); | 1176 | _set_gate(n, DESCTYPE_INT, addr, __KERNEL_CS); |
1191 | } | 1177 | } |
1192 | 1178 | ||
1193 | /* | 1179 | /* |
@@ -1195,22 +1181,22 @@ void set_intr_gate(unsigned int n, void *addr) | |||
1195 | */ | 1181 | */ |
1196 | static inline void set_system_intr_gate(unsigned int n, void *addr) | 1182 | static inline void set_system_intr_gate(unsigned int n, void *addr) |
1197 | { | 1183 | { |
1198 | _set_gate(idt_table+n, 14, 3, addr, __KERNEL_CS); | 1184 | _set_gate(n, DESCTYPE_INT | DESCTYPE_DPL3, addr, __KERNEL_CS); |
1199 | } | 1185 | } |
1200 | 1186 | ||
1201 | static void __init set_trap_gate(unsigned int n, void *addr) | 1187 | static void __init set_trap_gate(unsigned int n, void *addr) |
1202 | { | 1188 | { |
1203 | _set_gate(idt_table+n,15,0,addr,__KERNEL_CS); | 1189 | _set_gate(n, DESCTYPE_TRAP, addr, __KERNEL_CS); |
1204 | } | 1190 | } |
1205 | 1191 | ||
1206 | static void __init set_system_gate(unsigned int n, void *addr) | 1192 | static void __init set_system_gate(unsigned int n, void *addr) |
1207 | { | 1193 | { |
1208 | _set_gate(idt_table+n,15,3,addr,__KERNEL_CS); | 1194 | _set_gate(n, DESCTYPE_TRAP | DESCTYPE_DPL3, addr, __KERNEL_CS); |
1209 | } | 1195 | } |
1210 | 1196 | ||
1211 | static void __init set_task_gate(unsigned int n, unsigned int gdt_entry) | 1197 | static void __init set_task_gate(unsigned int n, unsigned int gdt_entry) |
1212 | { | 1198 | { |
1213 | _set_gate(idt_table+n,5,0,0,(gdt_entry<<3)); | 1199 | _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3)); |
1214 | } | 1200 | } |
1215 | 1201 | ||
1216 | 1202 | ||
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h index 89b8b82c82b3..5db9e96e8dc1 100644 --- a/include/asm-i386/desc.h +++ b/include/asm-i386/desc.h | |||
@@ -33,50 +33,99 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu) | |||
33 | return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address; | 33 | return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address; |
34 | } | 34 | } |
35 | 35 | ||
36 | /* | ||
37 | * This is the ldt that every process will get unless we need | ||
38 | * something other than this. | ||
39 | */ | ||
40 | extern struct desc_struct default_ldt[]; | ||
41 | extern struct desc_struct idt_table[]; | ||
42 | extern void set_intr_gate(unsigned int irq, void * addr); | ||
43 | |||
44 | static inline void pack_descriptor(__u32 *a, __u32 *b, | ||
45 | unsigned long base, unsigned long limit, unsigned char type, unsigned char flags) | ||
46 | { | ||
47 | *a = ((base & 0xffff) << 16) | (limit & 0xffff); | ||
48 | *b = (base & 0xff000000) | ((base & 0xff0000) >> 16) | | ||
49 | ((type & 0xff) << 8) | ((flags & 0xf) << 12); | ||
50 | } | ||
51 | |||
52 | static inline void pack_gate(__u32 *a, __u32 *b, | ||
53 | unsigned long base, unsigned short seg, unsigned char type, unsigned char flags) | ||
54 | { | ||
55 | *a = (seg << 16) | (base & 0xffff); | ||
56 | *b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff); | ||
57 | } | ||
58 | |||
59 | #define DESCTYPE_LDT 0x82 /* present, system, DPL-0, LDT */ | ||
60 | #define DESCTYPE_TSS 0x89 /* present, system, DPL-0, 32-bit TSS */ | ||
61 | #define DESCTYPE_TASK 0x85 /* present, system, DPL-0, task gate */ | ||
62 | #define DESCTYPE_INT 0x8e /* present, system, DPL-0, interrupt gate */ | ||
63 | #define DESCTYPE_TRAP 0x8f /* present, system, DPL-0, trap gate */ | ||
64 | #define DESCTYPE_DPL3 0x60 /* DPL-3 */ | ||
65 | #define DESCTYPE_S 0x10 /* !system */ | ||
66 | |||
36 | #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8)) | 67 | #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)) | 68 | #define load_LDT_desc() __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8)) |
38 | 69 | ||
39 | #define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr)) | 70 | #define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr)) |
40 | #define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr)) | 71 | #define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr)) |
41 | #define load_tr(tr) __asm__ __volatile("ltr %0"::"mr" (tr)) | 72 | #define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr)) |
42 | #define load_ldt(ldt) __asm__ __volatile("lldt %0"::"mr" (ldt)) | 73 | #define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt)) |
43 | 74 | ||
44 | #define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr)) | 75 | #define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr)) |
45 | #define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr)) | 76 | #define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr)) |
46 | #define store_tr(tr) __asm__ ("str %0":"=mr" (tr)) | 77 | #define store_tr(tr) __asm__ ("str %0":"=m" (tr)) |
47 | #define store_ldt(ldt) __asm__ ("sldt %0":"=mr" (ldt)) | 78 | #define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt)) |
48 | 79 | ||
49 | /* | 80 | #if TLS_SIZE != 24 |
50 | * This is the ldt that every process will get unless we need | 81 | # error update this code. |
51 | * something other than this. | 82 | #endif |
52 | */ | ||
53 | extern struct desc_struct default_ldt[]; | ||
54 | extern void set_intr_gate(unsigned int irq, void * addr); | ||
55 | 83 | ||
56 | #define _set_tssldt_desc(n,addr,limit,type) \ | 84 | static inline void load_TLS(struct thread_struct *t, unsigned int cpu) |
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 | { | 85 | { |
69 | _set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr, | 86 | #define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i] |
70 | offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89); | 87 | C(0); C(1); C(2); |
88 | #undef C | ||
71 | } | 89 | } |
72 | 90 | ||
73 | #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr) | 91 | static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b) |
92 | { | ||
93 | __u32 *lp = (__u32 *)((char *)dt + entry*8); | ||
94 | *lp = entry_a; | ||
95 | *(lp+1) = entry_b; | ||
96 | } | ||
97 | |||
98 | #define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b) | ||
99 | #define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b) | ||
100 | #define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b) | ||
101 | |||
102 | static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg) | ||
103 | { | ||
104 | __u32 a, b; | ||
105 | pack_gate(&a, &b, (unsigned long)addr, seg, type, 0); | ||
106 | write_idt_entry(idt_table, gate, a, b); | ||
107 | } | ||
74 | 108 | ||
75 | static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size) | 109 | static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr) |
76 | { | 110 | { |
77 | _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82); | 111 | __u32 a, b; |
112 | pack_descriptor(&a, &b, (unsigned long)addr, | ||
113 | offsetof(struct tss_struct, __cacheline_filler) - 1, | ||
114 | DESCTYPE_TSS, 0); | ||
115 | write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b); | ||
78 | } | 116 | } |
79 | 117 | ||
118 | static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int entries) | ||
119 | { | ||
120 | __u32 a, b; | ||
121 | pack_descriptor(&a, &b, (unsigned long)addr, | ||
122 | entries * sizeof(struct desc_struct) - 1, | ||
123 | DESCTYPE_LDT, 0); | ||
124 | write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b); | ||
125 | } | ||
126 | |||
127 | #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr) | ||
128 | |||
80 | #define LDT_entry_a(info) \ | 129 | #define LDT_entry_a(info) \ |
81 | ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) | 130 | ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) |
82 | 131 | ||
@@ -102,24 +151,6 @@ static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size) | |||
102 | (info)->seg_not_present == 1 && \ | 151 | (info)->seg_not_present == 1 && \ |
103 | (info)->useable == 0 ) | 152 | (info)->useable == 0 ) |
104 | 153 | ||
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) | 154 | static inline void clear_LDT(void) |
124 | { | 155 | { |
125 | int cpu = get_cpu(); | 156 | int cpu = get_cpu(); |