x86/idt: Consolidate idt functionality
- Move load_current_idt() out of line and replace the hideous comment with a lockdep assert. This allows to make idt_table and idt_descr static. - Mark idt_table read only after the IDT initialization is complete. - Shuffle code around to consolidate the #ifdef sections into one. - Adapt the F00F bug code. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20200528145523.084915381@linutronix.de
This commit is contained in:
		
							parent
							
								
									00229a5430
								
							
						
					
					
						commit
						3e77abda65
					
				| @ -40,9 +40,6 @@ static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *in | ||||
| 	desc->l			= 0; | ||||
| } | ||||
| 
 | ||||
| extern struct desc_ptr idt_descr; | ||||
| extern gate_desc idt_table[]; | ||||
| 
 | ||||
| struct gdt_page { | ||||
| 	struct desc_struct gdt[GDT_ENTRIES]; | ||||
| } __attribute__((aligned(PAGE_SIZE))); | ||||
| @ -388,22 +385,12 @@ void alloc_intr_gate(unsigned int n, const void *addr); | ||||
| 
 | ||||
| extern unsigned long system_vectors[]; | ||||
| 
 | ||||
| /*
 | ||||
|  * The load_current_idt() must be called with interrupts disabled | ||||
|  * to avoid races. That way the IDT will always be set back to the expected | ||||
|  * descriptor. It's also called when a CPU is being initialized, and | ||||
|  * that doesn't need to disable interrupts, as nothing should be | ||||
|  * bothering the CPU then. | ||||
|  */ | ||||
| static __always_inline void load_current_idt(void) | ||||
| { | ||||
| 	load_idt((const struct desc_ptr *)&idt_descr); | ||||
| } | ||||
| 
 | ||||
| extern void load_current_idt(void); | ||||
| extern void idt_setup_early_handler(void); | ||||
| extern void idt_setup_early_traps(void); | ||||
| extern void idt_setup_traps(void); | ||||
| extern void idt_setup_apic_and_irq_gates(void); | ||||
| extern bool idt_is_f00f_address(unsigned long address); | ||||
| 
 | ||||
| #ifdef CONFIG_X86_64 | ||||
| extern void idt_setup_early_pf(void); | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| #include <linux/interrupt.h> | ||||
| 
 | ||||
| #include <asm/cpu_entry_area.h> | ||||
| #include <asm/set_memory.h> | ||||
| #include <asm/traps.h> | ||||
| #include <asm/proto.h> | ||||
| #include <asm/desc.h> | ||||
| @ -156,37 +157,25 @@ static const __initconst struct idt_data apic_idts[] = { | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| #ifdef CONFIG_X86_64 | ||||
| /*
 | ||||
|  * Early traps running on the DEFAULT_STACK because the other interrupt | ||||
|  * stacks work only after cpu_init(). | ||||
|  */ | ||||
| static const __initconst struct idt_data early_pf_idts[] = { | ||||
| 	INTG(X86_TRAP_PF,		asm_exc_page_fault), | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| /* Must be page-aligned because the real IDT is used in a fixmap. */ | ||||
| gate_desc idt_table[IDT_ENTRIES] __page_aligned_bss; | ||||
| /* Must be page-aligned because the real IDT is used in the cpu entry area */ | ||||
| static gate_desc idt_table[IDT_ENTRIES] __page_aligned_bss; | ||||
| 
 | ||||
| struct desc_ptr idt_descr __ro_after_init = { | ||||
| 	.size		= IDT_TABLE_SIZE - 1, | ||||
| 	.address	= (unsigned long) idt_table, | ||||
| }; | ||||
| 
 | ||||
| #ifdef CONFIG_X86_64 | ||||
| /*
 | ||||
|  * The exceptions which use Interrupt stacks. They are setup after | ||||
|  * cpu_init() when the TSS has been initialized. | ||||
|  */ | ||||
| static const __initconst struct idt_data ist_idts[] = { | ||||
| 	ISTG(X86_TRAP_DB,	asm_exc_debug,		IST_INDEX_DB), | ||||
| 	ISTG(X86_TRAP_NMI,	asm_exc_nmi,		IST_INDEX_NMI), | ||||
| 	ISTG(X86_TRAP_DF,	asm_exc_double_fault,	IST_INDEX_DF), | ||||
| #ifdef CONFIG_X86_MCE | ||||
| 	ISTG(X86_TRAP_MC,	asm_exc_machine_check,	IST_INDEX_MCE), | ||||
| #endif | ||||
| }; | ||||
| void load_current_idt(void) | ||||
| { | ||||
| 	lockdep_assert_irqs_disabled(); | ||||
| 	load_idt(&idt_descr); | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_X86_F00F_BUG | ||||
| bool idt_is_f00f_address(unsigned long address) | ||||
| { | ||||
| 	return ((address - idt_descr.address) >> 3) == 6; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static inline void idt_init_desc(gate_desc *gate, const struct idt_data *d) | ||||
| @ -255,6 +244,27 @@ void __init idt_setup_traps(void) | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_X86_64 | ||||
| /*
 | ||||
|  * Early traps running on the DEFAULT_STACK because the other interrupt | ||||
|  * stacks work only after cpu_init(). | ||||
|  */ | ||||
| static const __initconst struct idt_data early_pf_idts[] = { | ||||
| 	INTG(X86_TRAP_PF,		asm_exc_page_fault), | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * The exceptions which use Interrupt stacks. They are setup after | ||||
|  * cpu_init() when the TSS has been initialized. | ||||
|  */ | ||||
| static const __initconst struct idt_data ist_idts[] = { | ||||
| 	ISTG(X86_TRAP_DB,	asm_exc_debug,		IST_INDEX_DB), | ||||
| 	ISTG(X86_TRAP_NMI,	asm_exc_nmi,		IST_INDEX_NMI), | ||||
| 	ISTG(X86_TRAP_DF,	asm_exc_double_fault,	IST_INDEX_DF), | ||||
| #ifdef CONFIG_X86_MCE | ||||
| 	ISTG(X86_TRAP_MC,	asm_exc_machine_check,	IST_INDEX_MCE), | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * idt_setup_early_pf - Initialize the idt table with early pagefault handler | ||||
|  * | ||||
| @ -325,6 +335,9 @@ void __init idt_setup_apic_and_irq_gates(void) | ||||
| 	idt_map_in_cea(); | ||||
| 	load_idt(&idt_descr); | ||||
| 
 | ||||
| 	/* Make the IDT table read only */ | ||||
| 	set_memory_ro((unsigned long)&idt_table, 1); | ||||
| 
 | ||||
| 	idt_setup_done = true; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -414,21 +414,13 @@ static int is_errata100(struct pt_regs *regs, unsigned long address) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* Pentium F0 0F C7 C8 bug workaround: */ | ||||
| static int is_f00f_bug(struct pt_regs *regs, unsigned long address) | ||||
| { | ||||
| #ifdef CONFIG_X86_F00F_BUG | ||||
| 	unsigned long nr; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Pentium F0 0F C7 C8 bug workaround: | ||||
| 	 */ | ||||
| 	if (boot_cpu_has_bug(X86_BUG_F00F)) { | ||||
| 		nr = (address - idt_descr.address) >> 3; | ||||
| 
 | ||||
| 		if (nr == 6) { | ||||
| 			handle_invalid_op(regs); | ||||
| 			return 1; | ||||
| 		} | ||||
| 	if (boot_cpu_has_bug(X86_BUG_F00F) && idt_is_f00f_address(address)) { | ||||
| 		handle_invalid_op(regs); | ||||
| 		return 1; | ||||
| 	} | ||||
| #endif | ||||
| 	return 0; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user