This slightly delays when we setup the idt. But by doing it in C things are noticeably simpler. Signed-off-by: Eric W. Biederman <ebiederm@xxxxxxxxxxxx> --- arch/i386/kernel/head.S | 68 +++----------------------------------------- arch/i386/kernel/head32.c | 26 +++++++++++++++++ 2 files changed, 31 insertions(+), 63 deletions(-) diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 22ddb3f..0ee615b 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -197,19 +197,6 @@ ENTRY(startup_32_smp) pushl $0 popfl -#ifdef CONFIG_SMP - cmpb $0, ready - jz 1f /* Initial CPU cleans BSS */ - jmp checkCPUtype -1: -#endif /* CONFIG_SMP */ - -/* - * start system 32-bit setup. We need to re-do some of the things done - * in 16-bit mode for the "real" operations. - */ - call setup_idt - checkCPUtype: movl $-1,X86_CPUID # -1 for no CPUID initially @@ -274,7 +261,6 @@ is386: movl $2,%ecx # set MP call check_x87 lgdt early_gdt_descr - lidt idt_descr ljmp $(__KERNEL_CS),$1f 1: movl $(__KERNEL_DS),%eax # reload all the segment registers movl %eax,%ss # after changing gdt. @@ -321,65 +307,21 @@ check_x87: .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ ret -/* - * setup_idt - * - * sets up a idt with 256 entries pointing to - * ignore_int, interrupt gates. It doesn't actually load - * idt - that can be done only after paging has been enabled - * and the kernel moved to PAGE_OFFSET. Interrupts - * are enabled elsewhere, when we can be relatively - * sure everything is ok. - * - * Warning: %esi is live across this function. - */ -setup_idt: - lea ignore_int,%edx - movl $(__KERNEL_CS << 16),%eax - movw %dx,%ax /* selector = 0x0010 = cs */ - movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ - - lea idt_table,%edi - mov $256,%ecx -rp_sidt: - movl %eax,(%edi) - movl %edx,4(%edi) - addl $8,%edi - dec %ecx - jne rp_sidt - -.macro set_early_handler handler,trapno - lea \handler,%edx - movl $(__KERNEL_CS << 16),%eax - movw %dx,%ax - movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ - lea idt_table,%edi - movl %eax,8*\trapno(%edi) - movl %edx,8*\trapno+4(%edi) -.endm - - set_early_handler handler=early_divide_err,trapno=0 - set_early_handler handler=early_illegal_opcode,trapno=6 - set_early_handler handler=early_protection_fault,trapno=13 - set_early_handler handler=early_page_fault,trapno=14 - - ret - -early_divide_err: +ENTRY(early_divide_err) xor %edx,%edx pushl $0 /* fake errcode */ jmp early_fault -early_illegal_opcode: +ENTRY(early_illegal_opcode) movl $6,%edx pushl $0 /* fake errcode */ jmp early_fault -early_protection_fault: +ENTRY(early_protection_fault) movl $13,%edx jmp early_fault -early_page_fault: +ENTRY(early_page_fault) movl $14,%edx jmp early_fault @@ -408,7 +350,7 @@ hlt_loop: /* This is the default interrupt "handler" :-) */ ALIGN -ignore_int: +ENTRY(ignore_int) cld #ifdef CONFIG_PRINTK pushl %eax diff --git a/arch/i386/kernel/head32.c b/arch/i386/kernel/head32.c index 3db0590..d2f85d5 100644 --- a/arch/i386/kernel/head32.c +++ b/arch/i386/kernel/head32.c @@ -7,8 +7,34 @@ #include <linux/init.h> #include <linux/start_kernel.h> +#include <asm/desc.h> + +extern void ignore_int(void); +extern void early_divide_err(void); +extern void early_illegal_opcode(void); +extern void early_protection_fault(void); +extern void early_page_fault(void); + +/* + * setup_idt + * + * sets up a idt with 256 entries pointing to ignore_int. Interrupts + * are enabled elsewhere, when we can be relatively sure everything is ok. + */ +static void __init setup_idt(void) +{ + int i; + for (i = 0; i < IDT_ENTRIES; i++) + set_intr_gate(i, ignore_int); + set_intr_gate(0, early_divide_err); + set_intr_gate(6, early_illegal_opcode); + set_intr_gate(13, early_protection_fault); + set_intr_gate(14, early_page_fault); + load_idt(&idt_descr); +} void __init i386_start_kernel(void) { + setup_idt(); start_kernel(); } -- 1.5.1.1.181.g2de0 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/virtualization