x86/xen/64: Rearrange the SYSCALL entries
Xen's raw SYSCALL entries are much less weird than native. Rather than fudging them to look like native entries, use the Xen-provided stack frame directly. This lets us eliminate entry_SYSCALL_64_after_swapgs and two uses of the SWAPGS_UNSAFE_STACK paravirt hook. The SYSENTER code would benefit from similar treatment. This makes one change to the native code path: the compat instruction that clears the high 32 bits of %rax is moved slightly later. I'd be surprised if this affects performance at all. Tested-by: Juergen Gross <jgross@suse.com> Signed-off-by: Andy Lutomirski <luto@kernel.org> Reviewed-by: Juergen Gross <jgross@suse.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Borislav Petkov <bpetkov@suse.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/7c88ed36805d36841ab03ec3b48b4122c4418d71.1502164668.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Родитель
1d0f49e140
Коммит
8a9949bc71
|
@ -142,14 +142,8 @@ ENTRY(entry_SYSCALL_64)
|
||||||
* We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
|
* We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
|
||||||
* it is too small to ever cause noticeable irq latency.
|
* it is too small to ever cause noticeable irq latency.
|
||||||
*/
|
*/
|
||||||
SWAPGS_UNSAFE_STACK
|
|
||||||
/*
|
|
||||||
* A hypervisor implementation might want to use a label
|
|
||||||
* after the swapgs, so that it can do the swapgs
|
|
||||||
* for the guest and jump here on syscall.
|
|
||||||
*/
|
|
||||||
GLOBAL(entry_SYSCALL_64_after_swapgs)
|
|
||||||
|
|
||||||
|
swapgs
|
||||||
movq %rsp, PER_CPU_VAR(rsp_scratch)
|
movq %rsp, PER_CPU_VAR(rsp_scratch)
|
||||||
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
||||||
|
|
||||||
|
@ -161,6 +155,7 @@ GLOBAL(entry_SYSCALL_64_after_swapgs)
|
||||||
pushq %r11 /* pt_regs->flags */
|
pushq %r11 /* pt_regs->flags */
|
||||||
pushq $__USER_CS /* pt_regs->cs */
|
pushq $__USER_CS /* pt_regs->cs */
|
||||||
pushq %rcx /* pt_regs->ip */
|
pushq %rcx /* pt_regs->ip */
|
||||||
|
GLOBAL(entry_SYSCALL_64_after_hwframe)
|
||||||
pushq %rax /* pt_regs->orig_ax */
|
pushq %rax /* pt_regs->orig_ax */
|
||||||
pushq %rdi /* pt_regs->di */
|
pushq %rdi /* pt_regs->di */
|
||||||
pushq %rsi /* pt_regs->si */
|
pushq %rsi /* pt_regs->si */
|
||||||
|
|
|
@ -183,21 +183,20 @@ ENDPROC(entry_SYSENTER_compat)
|
||||||
*/
|
*/
|
||||||
ENTRY(entry_SYSCALL_compat)
|
ENTRY(entry_SYSCALL_compat)
|
||||||
/* Interrupts are off on entry. */
|
/* Interrupts are off on entry. */
|
||||||
SWAPGS_UNSAFE_STACK
|
swapgs
|
||||||
|
|
||||||
/* Stash user ESP and switch to the kernel stack. */
|
/* Stash user ESP and switch to the kernel stack. */
|
||||||
movl %esp, %r8d
|
movl %esp, %r8d
|
||||||
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
||||||
|
|
||||||
/* Zero-extending 32-bit regs, do not remove */
|
|
||||||
movl %eax, %eax
|
|
||||||
|
|
||||||
/* Construct struct pt_regs on stack */
|
/* Construct struct pt_regs on stack */
|
||||||
pushq $__USER32_DS /* pt_regs->ss */
|
pushq $__USER32_DS /* pt_regs->ss */
|
||||||
pushq %r8 /* pt_regs->sp */
|
pushq %r8 /* pt_regs->sp */
|
||||||
pushq %r11 /* pt_regs->flags */
|
pushq %r11 /* pt_regs->flags */
|
||||||
pushq $__USER32_CS /* pt_regs->cs */
|
pushq $__USER32_CS /* pt_regs->cs */
|
||||||
pushq %rcx /* pt_regs->ip */
|
pushq %rcx /* pt_regs->ip */
|
||||||
|
GLOBAL(entry_SYSCALL_compat_after_hwframe)
|
||||||
|
movl %eax, %eax /* discard orig_ax high bits */
|
||||||
pushq %rax /* pt_regs->orig_ax */
|
pushq %rax /* pt_regs->orig_ax */
|
||||||
pushq %rdi /* pt_regs->di */
|
pushq %rdi /* pt_regs->di */
|
||||||
pushq %rsi /* pt_regs->si */
|
pushq %rsi /* pt_regs->si */
|
||||||
|
|
|
@ -82,34 +82,29 @@ RELOC(xen_sysret64, 1b+1)
|
||||||
* rip
|
* rip
|
||||||
* r11
|
* r11
|
||||||
* rsp->rcx
|
* rsp->rcx
|
||||||
*
|
|
||||||
* In all the entrypoints, we undo all that to make it look like a
|
|
||||||
* CPU-generated syscall/sysenter and jump to the normal entrypoint.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.macro undo_xen_syscall
|
|
||||||
mov 0*8(%rsp), %rcx
|
|
||||||
mov 1*8(%rsp), %r11
|
|
||||||
mov 5*8(%rsp), %rsp
|
|
||||||
.endm
|
|
||||||
|
|
||||||
/* Normal 64-bit system call target */
|
/* Normal 64-bit system call target */
|
||||||
ENTRY(xen_syscall_target)
|
ENTRY(xen_syscall_target)
|
||||||
undo_xen_syscall
|
popq %rcx
|
||||||
jmp entry_SYSCALL_64_after_swapgs
|
popq %r11
|
||||||
|
jmp entry_SYSCALL_64_after_hwframe
|
||||||
ENDPROC(xen_syscall_target)
|
ENDPROC(xen_syscall_target)
|
||||||
|
|
||||||
#ifdef CONFIG_IA32_EMULATION
|
#ifdef CONFIG_IA32_EMULATION
|
||||||
|
|
||||||
/* 32-bit compat syscall target */
|
/* 32-bit compat syscall target */
|
||||||
ENTRY(xen_syscall32_target)
|
ENTRY(xen_syscall32_target)
|
||||||
undo_xen_syscall
|
popq %rcx
|
||||||
jmp entry_SYSCALL_compat
|
popq %r11
|
||||||
|
jmp entry_SYSCALL_compat_after_hwframe
|
||||||
ENDPROC(xen_syscall32_target)
|
ENDPROC(xen_syscall32_target)
|
||||||
|
|
||||||
/* 32-bit compat sysenter target */
|
/* 32-bit compat sysenter target */
|
||||||
ENTRY(xen_sysenter_target)
|
ENTRY(xen_sysenter_target)
|
||||||
undo_xen_syscall
|
mov 0*8(%rsp), %rcx
|
||||||
|
mov 1*8(%rsp), %r11
|
||||||
|
mov 5*8(%rsp), %rsp
|
||||||
jmp entry_SYSENTER_compat
|
jmp entry_SYSENTER_compat
|
||||||
ENDPROC(xen_sysenter_target)
|
ENDPROC(xen_sysenter_target)
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче