Skip to content

Commit

Permalink
x86/head: Move early exception panic code into early_fixup_exception()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andy Lutomirski authored and Ingo Molnar committed Apr 13, 2016
1 parent 0d0efc0 commit 0e861fb
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 93 deletions.
2 changes: 1 addition & 1 deletion arch/x86/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
49 changes: 5 additions & 44 deletions arch/x86/kernel/head_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand All @@ -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" :-) */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"

/*
Expand Down
45 changes: 2 additions & 43 deletions arch/x86/kernel/head_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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 */
Expand All @@ -386,54 +381,18 @@ 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)

__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)
Expand Down
29 changes: 24 additions & 5 deletions arch/x86/mm/extable.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,28 +83,47 @@ 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;
ex_handler_t handler;

/* 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();
}

0 comments on commit 0e861fb

Please sign in to comment.