[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
|
addl $8,%edi
|
||||||
dec %ecx
|
dec %ecx
|
||||||
jne rp_sidt
|
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
|
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" :-) */
|
/* This is the default interrupt "handler" :-) */
|
||||||
ALIGN
|
ALIGN
|
||||||
ignore_int:
|
ignore_int:
|
||||||
@ -386,6 +443,9 @@ ignore_int:
|
|||||||
movl $(__KERNEL_DS),%eax
|
movl $(__KERNEL_DS),%eax
|
||||||
movl %eax,%ds
|
movl %eax,%ds
|
||||||
movl %eax,%es
|
movl %eax,%es
|
||||||
|
cmpl $2,early_recursion_flag
|
||||||
|
je hlt_loop
|
||||||
|
incl early_recursion_flag
|
||||||
pushl 16(%esp)
|
pushl 16(%esp)
|
||||||
pushl 24(%esp)
|
pushl 24(%esp)
|
||||||
pushl 32(%esp)
|
pushl 32(%esp)
|
||||||
@ -431,9 +491,16 @@ ENTRY(stack_start)
|
|||||||
|
|
||||||
ready: .byte 0
|
ready: .byte 0
|
||||||
|
|
||||||
|
early_recursion_flag:
|
||||||
|
.long 0
|
||||||
|
|
||||||
int_msg:
|
int_msg:
|
||||||
.asciz "Unknown interrupt or fault at EIP %p %p %p\n"
|
.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
|
* The IDT and GDT 'descriptors' are a strange 48-bit object
|
||||||
* only used by the lidt and lgdt instructions. They are not
|
* only used by the lidt and lgdt instructions. They are not
|
||||||
|
Loading…
x
Reference in New Issue
Block a user