diff options
author | Glauber de Oliveira Costa <gcosta@redhat.com> | 2008-01-30 07:31:14 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:31:14 -0500 |
commit | 507f90c9f92592e7630b1c1e87bf92d2c9858cc6 (patch) | |
tree | 23e011c11bc221e1c51702ca7dc748d2b241005d /include | |
parent | 54cd0eac7286b83ef1a657d2dddd74e0556209e7 (diff) |
x86: move _set_gate and its users to a common location
This patch moves _set_gate and its users to desc.h. We can now
use common code for x86_64 and i386.
[ mingo@elte.hu: set_system_gate() fixes for nasty crashes. ]
Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-x86/desc.h | 92 | ||||
-rw-r--r-- | include/asm-x86/desc_32.h | 16 | ||||
-rw-r--r-- | include/asm-x86/desc_64.h | 45 | ||||
-rw-r--r-- | include/asm-x86/desc_defs.h | 5 |
4 files changed, 93 insertions, 65 deletions
diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h index e61a5a38caba..d75bc0634313 100644 --- a/include/asm-x86/desc.h +++ b/include/asm-x86/desc.h | |||
@@ -33,6 +33,22 @@ extern struct desc_struct cpu_gdt_table[GDT_ENTRIES]; | |||
33 | extern struct desc_ptr cpu_gdt_descr[]; | 33 | extern struct desc_ptr cpu_gdt_descr[]; |
34 | /* the cpu gdt accessor */ | 34 | /* the cpu gdt accessor */ |
35 | #define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address) | 35 | #define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address) |
36 | |||
37 | static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func, | ||
38 | unsigned dpl, unsigned ist, unsigned seg) | ||
39 | { | ||
40 | gate->offset_low = PTR_LOW(func); | ||
41 | gate->segment = __KERNEL_CS; | ||
42 | gate->ist = ist; | ||
43 | gate->p = 1; | ||
44 | gate->dpl = dpl; | ||
45 | gate->zero0 = 0; | ||
46 | gate->zero1 = 0; | ||
47 | gate->type = type; | ||
48 | gate->offset_middle = PTR_MIDDLE(func); | ||
49 | gate->offset_high = PTR_HIGH(func); | ||
50 | } | ||
51 | |||
36 | #else | 52 | #else |
37 | struct gdt_page { | 53 | struct gdt_page { |
38 | struct desc_struct gdt[GDT_ENTRIES]; | 54 | struct desc_struct gdt[GDT_ENTRIES]; |
@@ -43,6 +59,16 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu) | |||
43 | { | 59 | { |
44 | return per_cpu(gdt_page, cpu).gdt; | 60 | return per_cpu(gdt_page, cpu).gdt; |
45 | } | 61 | } |
62 | |||
63 | static inline void pack_gate(gate_desc *gate, unsigned char type, | ||
64 | unsigned long base, unsigned dpl, unsigned flags, unsigned short seg) | ||
65 | |||
66 | { | ||
67 | gate->a = (seg << 16) | (base & 0xffff); | ||
68 | gate->b = (base & 0xffff0000) | | ||
69 | (((0x80 | type | (dpl << 5)) & 0xff) << 8); | ||
70 | } | ||
71 | |||
46 | #endif | 72 | #endif |
47 | 73 | ||
48 | #ifdef CONFIG_PARAVIRT | 74 | #ifdef CONFIG_PARAVIRT |
@@ -242,6 +268,72 @@ static inline unsigned long get_desc_base(struct desc_struct *desc) | |||
242 | { | 268 | { |
243 | return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24); | 269 | return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24); |
244 | } | 270 | } |
271 | static inline void _set_gate(int gate, unsigned type, void *addr, | ||
272 | unsigned dpl, unsigned ist, unsigned seg) | ||
273 | { | ||
274 | gate_desc s; | ||
275 | pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg); | ||
276 | /* | ||
277 | * does not need to be atomic because it is only done once at | ||
278 | * setup time | ||
279 | */ | ||
280 | write_idt_entry(idt_table, gate, &s); | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * This needs to use 'idt_table' rather than 'idt', and | ||
285 | * thus use the _nonmapped_ version of the IDT, as the | ||
286 | * Pentium F0 0F bugfix can have resulted in the mapped | ||
287 | * IDT being write-protected. | ||
288 | */ | ||
289 | static inline void set_intr_gate(unsigned int n, void *addr) | ||
290 | { | ||
291 | BUG_ON((unsigned)n > 0xFF); | ||
292 | _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS); | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * This routine sets up an interrupt gate at directory privilege level 3. | ||
297 | */ | ||
298 | static inline void set_system_intr_gate(unsigned int n, void *addr) | ||
299 | { | ||
300 | BUG_ON((unsigned)n > 0xFF); | ||
301 | _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS); | ||
302 | } | ||
303 | |||
304 | static inline void set_trap_gate(unsigned int n, void *addr) | ||
305 | { | ||
306 | BUG_ON((unsigned)n > 0xFF); | ||
307 | _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS); | ||
308 | } | ||
309 | |||
310 | static inline void set_system_gate(unsigned int n, void *addr) | ||
311 | { | ||
312 | BUG_ON((unsigned)n > 0xFF); | ||
313 | #ifdef CONFIG_X86_32 | ||
314 | _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS); | ||
315 | #else | ||
316 | _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS); | ||
317 | #endif | ||
318 | } | ||
319 | |||
320 | static inline void set_task_gate(unsigned int n, unsigned int gdt_entry) | ||
321 | { | ||
322 | BUG_ON((unsigned)n > 0xFF); | ||
323 | _set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3)); | ||
324 | } | ||
325 | |||
326 | static inline void set_intr_gate_ist(int n, void *addr, unsigned ist) | ||
327 | { | ||
328 | BUG_ON((unsigned)n > 0xFF); | ||
329 | _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS); | ||
330 | } | ||
331 | |||
332 | static inline void set_system_gate_ist(int n, void *addr, unsigned ist) | ||
333 | { | ||
334 | BUG_ON((unsigned)n > 0xFF); | ||
335 | _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS); | ||
336 | } | ||
245 | 337 | ||
246 | #else | 338 | #else |
247 | /* | 339 | /* |
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h index 4bf20b7dd741..3b112ec186a0 100644 --- a/include/asm-x86/desc_32.h +++ b/include/asm-x86/desc_32.h | |||
@@ -10,22 +10,6 @@ | |||
10 | #include <linux/preempt.h> | 10 | #include <linux/preempt.h> |
11 | #include <linux/percpu.h> | 11 | #include <linux/percpu.h> |
12 | 12 | ||
13 | extern void set_intr_gate(unsigned int irq, void * addr); | ||
14 | |||
15 | static inline void pack_gate(gate_desc *gate, | ||
16 | unsigned long base, unsigned short seg, unsigned char type, unsigned char flags) | ||
17 | { | ||
18 | gate->a = (seg << 16) | (base & 0xffff); | ||
19 | gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff); | ||
20 | } | ||
21 | |||
22 | static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg) | ||
23 | { | ||
24 | gate_desc g; | ||
25 | pack_gate(&g, (unsigned long)addr, seg, type, 0); | ||
26 | write_idt_entry(idt_table, gate, &g); | ||
27 | } | ||
28 | |||
29 | static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr) | 13 | static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr) |
30 | { | 14 | { |
31 | tss_desc tss; | 15 | tss_desc tss; |
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h index b0290c45319c..6bc92e6e5cc3 100644 --- a/include/asm-x86/desc_64.h +++ b/include/asm-x86/desc_64.h | |||
@@ -11,51 +11,6 @@ | |||
11 | 11 | ||
12 | #include <asm/segment.h> | 12 | #include <asm/segment.h> |
13 | 13 | ||
14 | static inline void _set_gate(int gate, unsigned type, unsigned long func, | ||
15 | unsigned dpl, unsigned ist) | ||
16 | { | ||
17 | gate_desc s; | ||
18 | |||
19 | s.offset_low = PTR_LOW(func); | ||
20 | s.segment = __KERNEL_CS; | ||
21 | s.ist = ist; | ||
22 | s.p = 1; | ||
23 | s.dpl = dpl; | ||
24 | s.zero0 = 0; | ||
25 | s.zero1 = 0; | ||
26 | s.type = type; | ||
27 | s.offset_middle = PTR_MIDDLE(func); | ||
28 | s.offset_high = PTR_HIGH(func); | ||
29 | /* | ||
30 | * does not need to be atomic because it is only done once at | ||
31 | * setup time | ||
32 | */ | ||
33 | write_idt_entry(idt_table, gate, &s); | ||
34 | } | ||
35 | |||
36 | static inline void set_intr_gate(int nr, void *func) | ||
37 | { | ||
38 | BUG_ON((unsigned)nr > 0xFF); | ||
39 | _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, 0); | ||
40 | } | ||
41 | |||
42 | static inline void set_intr_gate_ist(int nr, void *func, unsigned ist) | ||
43 | { | ||
44 | BUG_ON((unsigned)nr > 0xFF); | ||
45 | _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, ist); | ||
46 | } | ||
47 | |||
48 | static inline void set_system_gate(int nr, void *func) | ||
49 | { | ||
50 | BUG_ON((unsigned)nr > 0xFF); | ||
51 | _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, 0); | ||
52 | } | ||
53 | |||
54 | static inline void set_system_gate_ist(int nr, void *func, unsigned ist) | ||
55 | { | ||
56 | _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, ist); | ||
57 | } | ||
58 | |||
59 | static inline void set_tss_desc(unsigned cpu, void *addr) | 14 | static inline void set_tss_desc(unsigned cpu, void *addr) |
60 | { | 15 | { |
61 | struct desc_struct *d = get_cpu_gdt_table(cpu); | 16 | struct desc_struct *d = get_cpu_gdt_table(cpu); |
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h index ebb64fe3a450..e33f078b3e54 100644 --- a/include/asm-x86/desc_defs.h +++ b/include/asm-x86/desc_defs.h | |||
@@ -36,6 +36,7 @@ enum { | |||
36 | GATE_INTERRUPT = 0xE, | 36 | GATE_INTERRUPT = 0xE, |
37 | GATE_TRAP = 0xF, | 37 | GATE_TRAP = 0xF, |
38 | GATE_CALL = 0xC, | 38 | GATE_CALL = 0xC, |
39 | GATE_TASK = 0x5, | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | // 16byte gate | 42 | // 16byte gate |
@@ -55,10 +56,6 @@ struct gate_struct64 { | |||
55 | enum { | 56 | enum { |
56 | DESC_TSS = 0x9, | 57 | DESC_TSS = 0x9, |
57 | DESC_LDT = 0x2, | 58 | DESC_LDT = 0x2, |
58 | DESCTYPE_TASK = 0x85, /* present, system, DPL-0, task gate */ | ||
59 | DESCTYPE_INT = 0x8e, /* present, system, DPL-0, interrupt gate */ | ||
60 | DESCTYPE_TRAP = 0x8f, /* present, system, DPL-0, trap gate */ | ||
61 | DESCTYPE_DPL3 = 0x60, /* DPL-3 */ | ||
62 | DESCTYPE_S = 0x10, /* !system */ | 59 | DESCTYPE_S = 0x10, /* !system */ |
63 | }; | 60 | }; |
64 | 61 | ||