Commit 0e861fbb authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Ingo Molnar

x86/head: Move early exception panic code into early_fixup_exception()

This removes a bunch of assembly and adds some C code instead.  It
changes the actual printouts on both 32-bit and 64-bit kernels, but
they still seem okay.
Tested-by: default avatarBoris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: default avatarAndy Lutomirski <luto@kernel.org>
Acked-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: KVM list <kvm@vger.kernel.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: xen-devel <Xen-devel@lists.xen.org>
Link: http://lkml.kernel.org/r/4085070316fc3ab29538d3fcfe282648d1d4ee2e.1459605520.git.luto@kernel.orgSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 0d0efc07
...@@ -110,7 +110,7 @@ struct exception_table_entry { ...@@ -110,7 +110,7 @@ struct exception_table_entry {
extern int fixup_exception(struct pt_regs *regs, int trapnr); extern int fixup_exception(struct pt_regs *regs, int trapnr);
extern bool ex_has_fault_handler(unsigned long ip); extern bool ex_has_fault_handler(unsigned long ip);
extern int early_fixup_exception(struct pt_regs *regs, int trapnr); extern void early_fixup_exception(struct pt_regs *regs, int trapnr);
/* /*
* These are the main single-value transfer routines. They automatically * These are the main single-value transfer routines. They automatically
......
...@@ -561,8 +561,6 @@ early_idt_handler_common: ...@@ -561,8 +561,6 @@ early_idt_handler_common:
*/ */
cld cld
cmpl $2,%ss:early_recursion_flag
je hlt_loop
incl %ss:early_recursion_flag incl %ss:early_recursion_flag
/* The vector number is in pt_regs->gs */ /* The vector number is in pt_regs->gs */
...@@ -594,13 +592,8 @@ early_idt_handler_common: ...@@ -594,13 +592,8 @@ early_idt_handler_common:
movw %gs, PT_GS(%esp) movw %gs, PT_GS(%esp)
movw $0, PT_GS+2(%esp) movw $0, PT_GS+2(%esp)
cmpl $(__KERNEL_CS),PT_CS(%esp)
jne 10f
movl %esp, %eax /* args are pt_regs (EAX), trapnr (EDX) */ movl %esp, %eax /* args are pt_regs (EAX), trapnr (EDX) */
call early_fixup_exception call early_fixup_exception
andl %eax,%eax
jz 10f /* Exception wasn't fixed up */
popl %ebx /* pt_regs->bx */ popl %ebx /* pt_regs->bx */
popl %ecx /* pt_regs->cx */ popl %ecx /* pt_regs->cx */
...@@ -616,29 +609,6 @@ early_idt_handler_common: ...@@ -616,29 +609,6 @@ early_idt_handler_common:
decl %ss:early_recursion_flag decl %ss:early_recursion_flag
addl $4, %esp /* pop pt_regs->orig_ax */ addl $4, %esp /* pop pt_regs->orig_ax */
iret iret
10:
#ifdef CONFIG_PRINTK
xorl %eax,%eax
movw %ax,PT_FS+2(%esp) /* clean up the segment values on some cpus */
movw %ax,PT_DS+2(%esp)
movw %ax,PT_ES+2(%esp)
leal 40(%esp),%eax
pushl %eax /* %esp before the exception */
pushl %ebx
pushl %ebp
pushl %esi
pushl %edi
movl %cr2,%eax
pushl %eax
pushl (20+6*4)(%esp) /* trapno */
pushl $fault_msg
call printk
#endif
call dump_stack
hlt_loop:
hlt
jmp hlt_loop
ENDPROC(early_idt_handler_common) ENDPROC(early_idt_handler_common)
/* This is the default interrupt "handler" :-) */ /* This is the default interrupt "handler" :-) */
...@@ -674,10 +644,14 @@ ignore_int: ...@@ -674,10 +644,14 @@ ignore_int:
popl %eax popl %eax
#endif #endif
iret iret
hlt_loop:
hlt
jmp hlt_loop
ENDPROC(ignore_int) ENDPROC(ignore_int)
__INITDATA __INITDATA
.align 4 .align 4
early_recursion_flag: GLOBAL(early_recursion_flag)
.long 0 .long 0
__REFDATA __REFDATA
...@@ -742,19 +716,6 @@ __INITRODATA ...@@ -742,19 +716,6 @@ __INITRODATA
int_msg: int_msg:
.asciz "Unknown interrupt or fault at: %p %p %p\n" .asciz "Unknown interrupt or fault at: %p %p %p\n"
fault_msg:
/* fault info: */
.ascii "BUG: Int %d: CR2 %p\n"
/* regs pushed in early_idt_handler: */
.ascii " EDI %p ESI %p EBP %p EBX %p\n"
.ascii " ESP %p ES %p DS %p\n"
.ascii " EDX %p ECX %p EAX %p\n"
/* fault frame: */
.ascii " vec %p err %p EIP %p CS %p flg %p\n"
.ascii "Stack: %p %p %p %p %p %p %p %p\n"
.ascii " %p %p %p %p %p %p %p %p\n"
.asciz " %p %p %p %p %p %p %p %p\n"
#include "../../x86/xen/xen-head.S" #include "../../x86/xen/xen-head.S"
/* /*
......
...@@ -351,8 +351,6 @@ early_idt_handler_common: ...@@ -351,8 +351,6 @@ early_idt_handler_common:
*/ */
cld cld
cmpl $2,early_recursion_flag(%rip)
jz 1f
incl early_recursion_flag(%rip) incl early_recursion_flag(%rip)
/* The vector number is currently in the pt_regs->di slot. */ /* The vector number is currently in the pt_regs->di slot. */
...@@ -373,9 +371,6 @@ early_idt_handler_common: ...@@ -373,9 +371,6 @@ early_idt_handler_common:
pushq %r14 /* pt_regs->r14 */ pushq %r14 /* pt_regs->r14 */
pushq %r15 /* pt_regs->r15 */ pushq %r15 /* pt_regs->r15 */
cmpl $__KERNEL_CS,CS(%rsp)
jne 11f
cmpq $14,%rsi /* Page fault? */ cmpq $14,%rsi /* Page fault? */
jnz 10f jnz 10f
GET_CR2_INTO(%rdi) /* Can clobber any volatile register if pv */ GET_CR2_INTO(%rdi) /* Can clobber any volatile register if pv */
...@@ -386,37 +381,8 @@ early_idt_handler_common: ...@@ -386,37 +381,8 @@ early_idt_handler_common:
10: 10:
movq %rsp,%rdi /* RDI = pt_regs; RSI is already trapnr */ movq %rsp,%rdi /* RDI = pt_regs; RSI is already trapnr */
call early_fixup_exception call early_fixup_exception
andl %eax,%eax
jnz 20f # Found an exception entry
11:
#ifdef CONFIG_EARLY_PRINTK
/*
* On paravirt kernels, GET_CR2_INTO clobbers callee-clobbered regs.
* We only care about RSI, so we need to save it.
*/
movq %rsi,%rbx /* Save vector number */
GET_CR2_INTO(%r9)
movq ORIG_RAX(%rsp),%r8 /* error code */
movq %rbx,%rsi /* vector number */
movq CS(%rsp),%rdx
movq RIP(%rsp),%rcx
xorl %eax,%eax
leaq early_idt_msg(%rip),%rdi
call early_printk
cmpl $2,early_recursion_flag(%rip)
jz 1f
call dump_stack
#ifdef CONFIG_KALLSYMS
leaq early_idt_ripmsg(%rip),%rdi
movq RIP(%rsp),%rsi # %rip again
call __print_symbol
#endif
#endif /* EARLY_PRINTK */
1: hlt
jmp 1b
20: /* Exception table entry found or page table generated */ 20:
decl early_recursion_flag(%rip) decl early_recursion_flag(%rip)
jmp restore_regs_and_iret jmp restore_regs_and_iret
ENDPROC(early_idt_handler_common) ENDPROC(early_idt_handler_common)
...@@ -424,16 +390,9 @@ ENDPROC(early_idt_handler_common) ...@@ -424,16 +390,9 @@ ENDPROC(early_idt_handler_common)
__INITDATA __INITDATA
.balign 4 .balign 4
early_recursion_flag: GLOBAL(early_recursion_flag)
.long 0 .long 0
#ifdef CONFIG_EARLY_PRINTK
early_idt_msg:
.asciz "PANIC: early exception %02lx rip %lx:%lx error %lx cr2 %lx\n"
early_idt_ripmsg:
.asciz "RIP %s\n"
#endif /* CONFIG_EARLY_PRINTK */
#define NEXT_PAGE(name) \ #define NEXT_PAGE(name) \
.balign PAGE_SIZE; \ .balign PAGE_SIZE; \
GLOBAL(name) GLOBAL(name)
......
...@@ -83,8 +83,10 @@ int fixup_exception(struct pt_regs *regs, int trapnr) ...@@ -83,8 +83,10 @@ int fixup_exception(struct pt_regs *regs, int trapnr)
return handler(e, regs, trapnr); return handler(e, regs, trapnr);
} }
extern unsigned int early_recursion_flag;
/* Restricted version used during very early boot */ /* Restricted version used during very early boot */
int __init early_fixup_exception(struct pt_regs *regs, int trapnr) void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
{ {
const struct exception_table_entry *e; const struct exception_table_entry *e;
unsigned long new_ip; unsigned long new_ip;
...@@ -92,19 +94,36 @@ int __init early_fixup_exception(struct pt_regs *regs, int trapnr) ...@@ -92,19 +94,36 @@ int __init early_fixup_exception(struct pt_regs *regs, int trapnr)
/* Ignore early NMIs. */ /* Ignore early NMIs. */
if (trapnr == X86_TRAP_NMI) if (trapnr == X86_TRAP_NMI)
return 1; return;
if (early_recursion_flag > 2)
goto halt_loop;
if (regs->cs != __KERNEL_CS)
goto fail;
e = search_exception_tables(regs->ip); e = search_exception_tables(regs->ip);
if (!e) if (!e)
return 0; goto fail;
new_ip = ex_fixup_addr(e); new_ip = ex_fixup_addr(e);
handler = ex_fixup_handler(e); handler = ex_fixup_handler(e);
/* special handling not supported during early boot */ /* special handling not supported during early boot */
if (handler != ex_handler_default) if (handler != ex_handler_default)
return 0; goto fail;
regs->ip = new_ip; regs->ip = new_ip;
return 1; return;
fail:
early_printk("PANIC: early exception 0x%02x IP %lx:%lx error %lx cr2 0x%lx\n",
(unsigned)trapnr, (unsigned long)regs->cs, regs->ip,
regs->orig_ax, read_cr2());
show_regs(regs);
halt_loop:
while (true)
halt();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment