x86/head: Move early exception panic code into early_fixup_exception()
authorAndy Lutomirski <luto@kernel.org>
Sat, 2 Apr 2016 14:01:34 +0000 (07:01 -0700)
committerIngo Molnar <mingo@kernel.org>
Wed, 13 Apr 2016 09:37:44 +0000 (11:37 +0200)
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>
arch/x86/include/asm/uaccess.h
arch/x86/kernel/head_32.S
arch/x86/kernel/head_64.S
arch/x86/mm/extable.c

index b6fb311b7d75727e6b46d1fae96cac71d7a3bdd5..d794fd1f582f127d07fb3c03a2c705496520af3d 100644 (file)
@@ -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
index 184291c72c22dfce26d86723bdaeb98b99d1d3d0..6770865fde6b6fe15f8a28454ef66b66f209f579 100644 (file)
@@ -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"
 
 /*
index 230843781dd43a74f978285b31f7e1ebba23a2d3..3de91a7e6c99c7e324ee62f9514ac08edc86799d 100644 (file)
@@ -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)
index 4be041910c2f6a4afe46c32755e7fc7742bad7d0..da442f37ca8b53d7db269640292621876ca4f0c3 100644 (file)
@@ -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();
 }