aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/traps_32.c34
-rw-r--r--include/asm-x86/desc.h92
-rw-r--r--include/asm-x86/desc_32.h16
-rw-r--r--include/asm-x86/desc_64.h45
-rw-r--r--include/asm-x86/desc_defs.h5
5 files changed, 93 insertions, 99 deletions
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index c70c41fd710b..3065b3f41928 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -1102,40 +1102,6 @@ asmlinkage void math_emulate(long arg)
1102 1102
1103#endif /* CONFIG_MATH_EMULATION */ 1103#endif /* CONFIG_MATH_EMULATION */
1104 1104
1105/*
1106 * This needs to use 'idt_table' rather than 'idt', and
1107 * thus use the _nonmapped_ version of the IDT, as the
1108 * Pentium F0 0F bugfix can have resulted in the mapped
1109 * IDT being write-protected.
1110 */
1111void set_intr_gate(unsigned int n, void *addr)
1112{
1113 _set_gate(n, DESCTYPE_INT, addr, __KERNEL_CS);
1114}
1115
1116/*
1117 * This routine sets up an interrupt gate at directory privilege level 3.
1118 */
1119static inline void set_system_intr_gate(unsigned int n, void *addr)
1120{
1121 _set_gate(n, DESCTYPE_INT | DESCTYPE_DPL3, addr, __KERNEL_CS);
1122}
1123
1124static void __init set_trap_gate(unsigned int n, void *addr)
1125{
1126 _set_gate(n, DESCTYPE_TRAP, addr, __KERNEL_CS);
1127}
1128
1129static void __init set_system_gate(unsigned int n, void *addr)
1130{
1131 _set_gate(n, DESCTYPE_TRAP | DESCTYPE_DPL3, addr, __KERNEL_CS);
1132}
1133
1134static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
1135{
1136 _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3));
1137}
1138
1139 1105
1140void __init trap_init(void) 1106void __init trap_init(void)
1141{ 1107{
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];
33extern struct desc_ptr cpu_gdt_descr[]; 33extern 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
37static 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
37struct gdt_page { 53struct 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
63static 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}
271static 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 */
289static 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 */
298static 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
304static 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
310static 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
320static 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
326static 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
332static 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
13extern void set_intr_gate(unsigned int irq, void * addr);
14
15static 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
22static 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
29static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr) 13static 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
14static 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
36static 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
42static 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
48static 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
54static 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
59static inline void set_tss_desc(unsigned cpu, void *addr) 14static 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 {
55enum { 56enum {
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