mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-02 15:21:03 +00:00
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: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: Andy Lutomirski <luto@kernel.org> Acked-by: Linus 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.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
0d0efc07f3
commit
0e861fbb5b
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user