forked from Minki/linux
[PATCH] i386: Do better early exception handlers
Add early i386 fault handlers with debug information for common faults. Handles: divide error invalid opcode protection fault page fault Also adds code to detect early recursive/multiple faults and halt the system when they happen (taken from x86_64.) Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Andi Kleen <ak@muc.de> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org>
This commit is contained in:
parent
78be3706b2
commit
ec5c09269b
@ -371,8 +371,65 @@ rp_sidt:
|
||||
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:
|
||||
xor %edx,%edx
|
||||
pushl $0 /* fake errcode */
|
||||
jmp early_fault
|
||||
|
||||
early_illegal_opcode:
|
||||
movl $6,%edx
|
||||
pushl $0 /* fake errcode */
|
||||
jmp early_fault
|
||||
|
||||
early_protection_fault:
|
||||
movl $13,%edx
|
||||
jmp early_fault
|
||||
|
||||
early_page_fault:
|
||||
movl $14,%edx
|
||||
jmp early_fault
|
||||
|
||||
early_fault:
|
||||
cld
|
||||
#ifdef CONFIG_PRINTK
|
||||
movl $(__KERNEL_DS),%eax
|
||||
movl %eax,%ds
|
||||
movl %eax,%es
|
||||
cmpl $2,early_recursion_flag
|
||||
je hlt_loop
|
||||
incl early_recursion_flag
|
||||
movl %cr2,%eax
|
||||
pushl %eax
|
||||
pushl %edx /* trapno */
|
||||
pushl $fault_msg
|
||||
#ifdef CONFIG_EARLY_PRINTK
|
||||
call early_printk
|
||||
#else
|
||||
call printk
|
||||
#endif
|
||||
#endif
|
||||
hlt_loop:
|
||||
hlt
|
||||
jmp hlt_loop
|
||||
|
||||
/* This is the default interrupt "handler" :-) */
|
||||
ALIGN
|
||||
ignore_int:
|
||||
@ -386,6 +443,9 @@ ignore_int:
|
||||
movl $(__KERNEL_DS),%eax
|
||||
movl %eax,%ds
|
||||
movl %eax,%es
|
||||
cmpl $2,early_recursion_flag
|
||||
je hlt_loop
|
||||
incl early_recursion_flag
|
||||
pushl 16(%esp)
|
||||
pushl 24(%esp)
|
||||
pushl 32(%esp)
|
||||
@ -431,9 +491,16 @@ ENTRY(stack_start)
|
||||
|
||||
ready: .byte 0
|
||||
|
||||
early_recursion_flag:
|
||||
.long 0
|
||||
|
||||
int_msg:
|
||||
.asciz "Unknown interrupt or fault at EIP %p %p %p\n"
|
||||
|
||||
fault_msg:
|
||||
.ascii "Int %d: CR2 %p err %p EIP %p CS %p flags %p\n"
|
||||
.asciz "Stack: %p %p %p %p %p %p %p %p\n"
|
||||
|
||||
/*
|
||||
* The IDT and GDT 'descriptors' are a strange 48-bit object
|
||||
* only used by the lidt and lgdt instructions. They are not
|
||||
|
Loading…
Reference in New Issue
Block a user