diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2017-08-28 02:47:49 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-08-29 06:07:27 -0400 |
commit | 3318e9744244a415ee9481ca7e54234caf5e12c5 (patch) | |
tree | 9f970eca410c835424b9dcf37b05ff650b0ea79e | |
parent | 87e81786b13b267c4355e0d23e33c7e4c08fa63f (diff) |
x86/idt: Prepare for table based init
The IDT setup code is handled in several places. All of them use variants
of set_intr_gate() inlines. This can be done with a table based
initialization, which allows to reduce the inline zoo and puts all IDT
related code and information into a single place.
Add the infrastructure.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/20170828064958.849877032@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/kernel/idt.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c index 70ca24853ef0..ae6fc12fd64f 100644 --- a/arch/x86/kernel/idt.c +++ b/arch/x86/kernel/idt.c | |||
@@ -5,8 +5,49 @@ | |||
5 | */ | 5 | */ |
6 | #include <linux/interrupt.h> | 6 | #include <linux/interrupt.h> |
7 | 7 | ||
8 | #include <asm/traps.h> | ||
9 | #include <asm/proto.h> | ||
8 | #include <asm/desc.h> | 10 | #include <asm/desc.h> |
9 | 11 | ||
12 | struct idt_data { | ||
13 | unsigned int vector; | ||
14 | unsigned int segment; | ||
15 | struct idt_bits bits; | ||
16 | const void *addr; | ||
17 | }; | ||
18 | |||
19 | #define DPL0 0x0 | ||
20 | #define DPL3 0x3 | ||
21 | |||
22 | #define DEFAULT_STACK 0 | ||
23 | |||
24 | #define G(_vector, _addr, _ist, _type, _dpl, _segment) \ | ||
25 | { \ | ||
26 | .vector = _vector, \ | ||
27 | .bits.ist = _ist, \ | ||
28 | .bits.type = _type, \ | ||
29 | .bits.dpl = _dpl, \ | ||
30 | .bits.p = 1, \ | ||
31 | .addr = _addr, \ | ||
32 | .segment = _segment, \ | ||
33 | } | ||
34 | |||
35 | /* Interrupt gate */ | ||
36 | #define INTG(_vector, _addr) \ | ||
37 | G(_vector, _addr, DEFAULT_STACK, GATE_INTERRUPT, DPL0, __KERNEL_CS) | ||
38 | |||
39 | /* System interrupt gate */ | ||
40 | #define SYSG(_vector, _addr) \ | ||
41 | G(_vector, _addr, DEFAULT_STACK, GATE_INTERRUPT, DPL3, __KERNEL_CS) | ||
42 | |||
43 | /* Interrupt gate with interrupt stack */ | ||
44 | #define ISTG(_vector, _addr, _ist) \ | ||
45 | G(_vector, _addr, _ist, GATE_INTERRUPT, DPL0, __KERNEL_CS) | ||
46 | |||
47 | /* Task gate */ | ||
48 | #define TSKG(_vector, _gdt) \ | ||
49 | G(_vector, NULL, DEFAULT_STACK, GATE_TASK, DPL0, _gdt << 3) | ||
50 | |||
10 | /* Must be page-aligned because the real IDT is used in a fixmap. */ | 51 | /* Must be page-aligned because the real IDT is used in a fixmap. */ |
11 | gate_desc idt_table[IDT_ENTRIES] __page_aligned_bss; | 52 | gate_desc idt_table[IDT_ENTRIES] __page_aligned_bss; |
12 | 53 | ||
@@ -25,6 +66,32 @@ const struct desc_ptr debug_idt_descr = { | |||
25 | }; | 66 | }; |
26 | #endif | 67 | #endif |
27 | 68 | ||
69 | static inline void idt_init_desc(gate_desc *gate, const struct idt_data *d) | ||
70 | { | ||
71 | unsigned long addr = (unsigned long) d->addr; | ||
72 | |||
73 | gate->offset_low = (u16) addr; | ||
74 | gate->segment = (u16) d->segment; | ||
75 | gate->bits = d->bits; | ||
76 | gate->offset_middle = (u16) (addr >> 16); | ||
77 | #ifdef CONFIG_X86_64 | ||
78 | gate->offset_high = (u32) (addr >> 32); | ||
79 | gate->reserved = 0; | ||
80 | #endif | ||
81 | } | ||
82 | |||
83 | static __init void | ||
84 | idt_setup_from_table(gate_desc *idt, const struct idt_data *t, int size) | ||
85 | { | ||
86 | gate_desc desc; | ||
87 | |||
88 | for (; size > 0; t++, size--) { | ||
89 | idt_init_desc(&desc, t); | ||
90 | set_bit(t->vector, used_vectors); | ||
91 | write_idt_entry(idt, t->vector, &desc); | ||
92 | } | ||
93 | } | ||
94 | |||
28 | /** | 95 | /** |
29 | * idt_setup_early_handler - Initializes the idt table with early handlers | 96 | * idt_setup_early_handler - Initializes the idt table with early handlers |
30 | */ | 97 | */ |