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 {
extern int fixup_exception(struct pt_regs *regs, int trapnr);
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
......
......@@ -561,8 +561,6 @@ early_idt_handler_common:
*/
cld
cmpl $2,%ss:early_recursion_flag
je hlt_loop
incl %ss:early_recursion_flag
/* The vector number is in pt_regs->gs */
......@@ -594,13 +592,8 @@ early_idt_handler_common:
movw %gs, PT_GS(%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) */
call early_fixup_exception
andl %eax,%eax
jz 10f /* Exception wasn't fixed up */
popl %ebx /* pt_regs->bx */
popl %ecx /* pt_regs->cx */
......@@ -616,29 +609,6 @@ early_idt_handler_common:
decl %ss:early_recursion_flag
addl $4, %esp /* pop pt_regs->orig_ax */
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)
/* This is the default interrupt "handler" :-) */
......@@ -674,10 +644,14 @@ ignore_int:
popl %eax
#endif
iret
hlt_loop:
hlt
jmp hlt_loop
ENDPROC(ignore_int)
__INITDATA
.align 4
early_recursion_flag:
GLOBAL(early_recursion_flag)
.long 0
__REFDATA
......@@ -742,19 +716,6 @@ __INITRODATA
int_msg:
.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"
/*
......
......@@ -351,8 +351,6 @@ early_idt_handler_common:
*/
cld
cmpl $2,early_recursion_flag(%rip)
jz 1f
incl early_recursion_flag(%rip)
/* The vector number is currently in the pt_regs->di slot. */
......@@ -373,9 +371,6 @@ early_idt_handler_common:
pushq %r14 /* pt_regs->r14 */
pushq %r15 /* pt_regs->r15 */
cmpl $__KERNEL_CS,CS(%rsp)
jne 11f
cmpq $14,%rsi /* Page fault? */
jnz 10f
GET_CR2_INTO(%rdi) /* Can clobber any volatile register if pv */
......@@ -386,37 +381,8 @@ early_idt_handler_common:
10:
movq %rsp,%rdi /* RDI = pt_regs; RSI is already trapnr */
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)
jmp restore_regs_and_iret
ENDPROC(early_idt_handler_common)
......@@ -424,16 +390,9 @@ ENDPROC(early_idt_handler_common)
__INITDATA
.balign 4
early_recursion_flag:
GLOBAL(early_recursion_flag)
.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) \
.balign PAGE_SIZE; \
GLOBAL(name)
......
......@@ -83,8 +83,10 @@ int fixup_exception(struct pt_regs *regs, int trapnr)
return handler(e, regs, trapnr);
}
extern unsigned int early_recursion_flag;
/* 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;
unsigned long new_ip;
......@@ -92,19 +94,36 @@ int __init early_fixup_exception(struct pt_regs *regs, int trapnr)
/* Ignore early NMIs. */
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);
if (!e)
return 0;
goto fail;
new_ip = ex_fixup_addr(e);
handler = ex_fixup_handler(e);
/* special handling not supported during early boot */
if (handler != ex_handler_default)
return 0;
goto fail;
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