x86/head: Pass a real pt_regs and trapnr to early_fixup_exception()

early_fixup_exception() is limited by the fact that it doesn't have a
real struct pt_regs.  Change both the 32-bit and 64-bit asm and the
C code to pass and accept a real pt_regs.

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/e3fb680fcfd5e23e38237e8328b64a25cc121d37.1459605520.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Andy Lutomirski 2016-04-02 07:01:32 -07:00 committed by Ingo Molnar
parent 6aa6dbfced
commit 7bbcdb1ca4
4 changed files with 91 additions and 57 deletions

View 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(unsigned long *ip);
extern int early_fixup_exception(struct pt_regs *regs, int trapnr);
/*
* These are the main single-value transfer routines. They automatically

View File

@ -568,29 +568,64 @@ early_idt_handler_common:
je hlt_loop
incl %ss:early_recursion_flag
push %eax # 16(%esp)
push %ecx # 12(%esp)
push %edx # 8(%esp)
push %ds # 4(%esp)
push %es # 0(%esp)
movl $(__KERNEL_DS),%eax
movl %eax,%ds
movl %eax,%es
/* The vector number is in pt_regs->gs */
cmpl $(__KERNEL_CS),32(%esp)
cld
pushl %fs /* pt_regs->fs */
movw $0, 2(%esp) /* clear high bits (some CPUs leave garbage) */
pushl %es /* pt_regs->es */
movw $0, 2(%esp) /* clear high bits (some CPUs leave garbage) */
pushl %ds /* pt_regs->ds */
movw $0, 2(%esp) /* clear high bits (some CPUs leave garbage) */
pushl %eax /* pt_regs->ax */
pushl %ebp /* pt_regs->bp */
pushl %edi /* pt_regs->di */
pushl %esi /* pt_regs->si */
pushl %edx /* pt_regs->dx */
pushl %ecx /* pt_regs->cx */
pushl %ebx /* pt_regs->bx */
/* Fix up DS and ES */
movl $(__KERNEL_DS), %ecx
movl %ecx, %ds
movl %ecx, %es
/* Load the vector number into EDX */
movl PT_GS(%esp), %edx
/* Load GS into pt_regs->gs and clear high bits */
movw %gs, PT_GS(%esp)
movw $0, PT_GS+2(%esp)
cmpl $(__KERNEL_CS),PT_CS(%esp)
jne 10f
leal 28(%esp),%eax # Pointer to %eip
call early_fixup_exception
andl %eax,%eax
jnz ex_entry /* found an exception entry */
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 */
popl %edx /* pt_regs->dx */
popl %esi /* pt_regs->si */
popl %edi /* pt_regs->di */
popl %ebp /* pt_regs->bp */
popl %eax /* pt_regs->ax */
popl %ds /* pt_regs->ds */
popl %es /* pt_regs->es */
popl %fs /* pt_regs->fs */
popl %gs /* pt_regs->gs */
decl %ss:early_recursion_flag
addl $4, %esp /* pop pt_regs->orig_ax */
iret
10:
#ifdef CONFIG_PRINTK
xorl %eax,%eax
movw %ax,2(%esp) /* clean up the segment values on some cpus */
movw %ax,6(%esp)
movw %ax,34(%esp)
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
@ -608,13 +643,6 @@ hlt_loop:
hlt
jmp hlt_loop
ex_entry:
pop %es
pop %ds
pop %edx
pop %ecx
pop %eax
decl %ss:early_recursion_flag
.Lis_nmi:
addl $8,%esp /* drop vector number and error code */
iret

View File

@ -20,6 +20,7 @@
#include <asm/processor-flags.h>
#include <asm/percpu.h>
#include <asm/nops.h>
#include "../entry/calling.h"
#ifdef CONFIG_PARAVIRT
#include <asm/asm-offsets.h>
@ -357,39 +358,52 @@ early_idt_handler_common:
jz 1f
incl early_recursion_flag(%rip)
pushq %rax # 64(%rsp)
pushq %rcx # 56(%rsp)
pushq %rdx # 48(%rsp)
pushq %rsi # 40(%rsp)
pushq %rdi # 32(%rsp)
pushq %r8 # 24(%rsp)
pushq %r9 # 16(%rsp)
pushq %r10 # 8(%rsp)
pushq %r11 # 0(%rsp)
/* The vector number is currently in the pt_regs->di slot. */
pushq %rsi /* pt_regs->si */
movq 8(%rsp), %rsi /* RSI = vector number */
movq %rdi, 8(%rsp) /* pt_regs->di = RDI */
pushq %rdx /* pt_regs->dx */
pushq %rcx /* pt_regs->cx */
pushq %rax /* pt_regs->ax */
pushq %r8 /* pt_regs->r8 */
pushq %r9 /* pt_regs->r9 */
pushq %r10 /* pt_regs->r10 */
pushq %r11 /* pt_regs->r11 */
pushq %rbx /* pt_regs->bx */
pushq %rbp /* pt_regs->bp */
pushq %r12 /* pt_regs->r12 */
pushq %r13 /* pt_regs->r13 */
pushq %r14 /* pt_regs->r14 */
pushq %r15 /* pt_regs->r15 */
cmpl $__KERNEL_CS,96(%rsp)
cmpl $__KERNEL_CS,CS(%rsp)
jne 11f
cmpl $14,72(%rsp) # Page fault?
cmpq $14,%rsi /* Page fault? */
jnz 10f
GET_CR2_INTO(%rdi) # can clobber any volatile register if pv
GET_CR2_INTO(%rdi) /* Can clobber any volatile register if pv */
call early_make_pgtable
andl %eax,%eax
jz 20f # All good
jz 20f /* All good */
10:
leaq 88(%rsp),%rdi # Pointer to %rip
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
GET_CR2_INTO(%r9) # can clobber any volatile register if pv
movl 80(%rsp),%r8d # error code
movl 72(%rsp),%esi # vector number
movl 96(%rsp),%edx # %cs
movq 88(%rsp),%rcx # %rip
/*
* 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
@ -398,24 +412,16 @@ early_idt_handler_common:
call dump_stack
#ifdef CONFIG_KALLSYMS
leaq early_idt_ripmsg(%rip),%rdi
movq 40(%rsp),%rsi # %rip again
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
popq %r11
popq %r10
popq %r9
popq %r8
popq %rdi
popq %rsi
popq %rdx
popq %rcx
popq %rax
20: /* Exception table entry found or page table generated */
decl early_recursion_flag(%rip)
jmp restore_regs_and_iret
.Lis_nmi:
addq $16,%rsp # drop vector number and error code
INTERRUPT_RETURN

View File

@ -83,13 +83,13 @@ int fixup_exception(struct pt_regs *regs, int trapnr)
}
/* Restricted version used during very early boot */
int __init early_fixup_exception(unsigned long *ip)
int __init early_fixup_exception(struct pt_regs *regs, int trapnr)
{
const struct exception_table_entry *e;
unsigned long new_ip;
ex_handler_t handler;
e = search_exception_tables(*ip);
e = search_exception_tables(regs->ip);
if (!e)
return 0;
@ -100,6 +100,6 @@ int __init early_fixup_exception(unsigned long *ip)
if (handler != ex_handler_default)
return 0;
*ip = new_ip;
regs->ip = new_ip;
return 1;
}