diff options
-rw-r--r-- | arch/x86/include/asm/desc.h | 37 | ||||
-rw-r--r-- | arch/x86/kernel/idt.c | 43 |
2 files changed, 36 insertions, 44 deletions
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h index cbd36dd7993e..33f84f29a724 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h @@ -390,44 +390,11 @@ static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit) desc->limit1 = (limit >> 16) & 0xf; } -static inline void _set_gate(int gate, unsigned type, const void *addr, - unsigned dpl, unsigned ist, unsigned seg) -{ - gate_desc s; - - pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg); - /* - * does not need to be atomic because it is only done once at - * setup time - */ - write_idt_entry(idt_table, gate, &s); -} - -static inline void set_intr_gate(unsigned int n, const void *addr) -{ - BUG_ON(n > 0xFF); - _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS); -} +void set_intr_gate(unsigned int n, const void *addr); +void alloc_intr_gate(unsigned int n, const void *addr); extern unsigned long used_vectors[]; -static inline void alloc_system_vector(int vector) -{ - BUG_ON(vector < FIRST_SYSTEM_VECTOR); - if (!test_bit(vector, used_vectors)) { - set_bit(vector, used_vectors); - } else { - BUG(); - } -} - -#define alloc_intr_gate(n, addr) \ - do { \ - alloc_system_vector(n); \ - set_intr_gate(n, addr); \ - } while (0) - - #ifdef CONFIG_X86_64 DECLARE_PER_CPU(u32, debug_idt_ctr); static inline bool is_debug_idt_enabled(void) diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c index 99f93a6fb92a..8e9318d2b56d 100644 --- a/arch/x86/kernel/idt.c +++ b/arch/x86/kernel/idt.c @@ -212,15 +212,16 @@ static inline void idt_init_desc(gate_desc *gate, const struct idt_data *d) #endif } -static __init void -idt_setup_from_table(gate_desc *idt, const struct idt_data *t, int size) +static void +idt_setup_from_table(gate_desc *idt, const struct idt_data *t, int size, bool sys) { gate_desc desc; for (; size > 0; t++, size--) { idt_init_desc(&desc, t); - set_bit(t->vector, used_vectors); write_idt_entry(idt, t->vector, &desc); + if (sys) + set_bit(t->vector, used_vectors); } } @@ -233,7 +234,8 @@ idt_setup_from_table(gate_desc *idt, const struct idt_data *t, int size) */ void __init idt_setup_early_traps(void) { - idt_setup_from_table(idt_table, early_idts, ARRAY_SIZE(early_idts)); + idt_setup_from_table(idt_table, early_idts, ARRAY_SIZE(early_idts), + true); load_idt(&idt_descr); } @@ -242,7 +244,7 @@ void __init idt_setup_early_traps(void) */ void __init idt_setup_traps(void) { - idt_setup_from_table(idt_table, def_idts, ARRAY_SIZE(def_idts)); + idt_setup_from_table(idt_table, def_idts, ARRAY_SIZE(def_idts), true); } #ifdef CONFIG_X86_64 @@ -259,7 +261,7 @@ void __init idt_setup_traps(void) void __init idt_setup_early_pf(void) { idt_setup_from_table(idt_table, early_pf_idts, - ARRAY_SIZE(early_pf_idts)); + ARRAY_SIZE(early_pf_idts), true); } /** @@ -267,7 +269,7 @@ void __init idt_setup_early_pf(void) */ void __init idt_setup_ist_traps(void) { - idt_setup_from_table(idt_table, ist_idts, ARRAY_SIZE(ist_idts)); + idt_setup_from_table(idt_table, ist_idts, ARRAY_SIZE(ist_idts), true); } /** @@ -277,7 +279,7 @@ void __init idt_setup_debugidt_traps(void) { memcpy(&debug_idt_table, &idt_table, IDT_ENTRIES * 16); - idt_setup_from_table(debug_idt_table, dbg_idts, ARRAY_SIZE(dbg_idts)); + idt_setup_from_table(debug_idt_table, dbg_idts, ARRAY_SIZE(dbg_idts), false); } #endif @@ -289,7 +291,7 @@ void __init idt_setup_apic_and_irq_gates(void) int i = FIRST_EXTERNAL_VECTOR; void *entry; - idt_setup_from_table(idt_table, apic_idts, ARRAY_SIZE(apic_idts)); + idt_setup_from_table(idt_table, apic_idts, ARRAY_SIZE(apic_idts), true); for_each_clear_bit_from(i, used_vectors, FIRST_SYSTEM_VECTOR) { entry = irq_entries_start + 8 * (i - FIRST_EXTERNAL_VECTOR); @@ -333,3 +335,26 @@ void idt_invalidate(void *addr) load_idt(&idt); } + +void set_intr_gate(unsigned int n, const void *addr) +{ + struct idt_data data; + + BUG_ON(n > 0xFF); + + memset(&data, 0, sizeof(data)); + data.vector = n; + data.addr = addr; + data.segment = __KERNEL_CS; + data.bits.type = GATE_INTERRUPT; + data.bits.p = 1; + + idt_setup_from_table(idt_table, &data, 1, false); +} + +void alloc_intr_gate(unsigned int n, const void *addr) +{ + BUG_ON(test_bit(n, used_vectors) || n < FIRST_SYSTEM_VECTOR); + set_bit(n, used_vectors); + set_intr_gate(n, addr); +} |