diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-07-23 11:34:11 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-07-28 18:25:40 -0400 |
commit | 7209a75d2009dbf7745e2fd354abf25c3deb3ca3 (patch) | |
tree | e0c3050ed85e8d10aff456f7fa43eec73cbad4ca | |
parent | 64aa90f26c06e1cb2aacfb98a7d0eccfbd6c1a91 (diff) |
x86_64/entry/xen: Do not invoke espfix64 on Xen
This moves the espfix64 logic into native_iret. To make this work,
it gets rid of the native patch for INTERRUPT_RETURN:
INTERRUPT_RETURN on native kernels is now 'jmp native_iret'.
This changes the 16-bit SS behavior on Xen from OOPSing to leaking
some bits of the Xen hypervisor's RSP (I think).
[ hpa: this is a nonzero cost on native, but probably not enough to
measure. Xen needs to fix this in their own code, probably doing
something equivalent to espfix64. ]
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Link: http://lkml.kernel.org/r/7b8f1d8ef6597cb16ae004a43c56980a7de3cf94.1406129132.git.luto@amacapital.net
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: <stable@vger.kernel.org>
-rw-r--r-- | arch/x86/include/asm/irqflags.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 28 | ||||
-rw-r--r-- | arch/x86/kernel/paravirt_patch_64.c | 2 |
3 files changed, 11 insertions, 21 deletions
diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h index bba3cf88e624..0a8b519226b8 100644 --- a/arch/x86/include/asm/irqflags.h +++ b/arch/x86/include/asm/irqflags.h | |||
@@ -129,7 +129,7 @@ static inline notrace unsigned long arch_local_irq_save(void) | |||
129 | 129 | ||
130 | #define PARAVIRT_ADJUST_EXCEPTION_FRAME /* */ | 130 | #define PARAVIRT_ADJUST_EXCEPTION_FRAME /* */ |
131 | 131 | ||
132 | #define INTERRUPT_RETURN iretq | 132 | #define INTERRUPT_RETURN jmp native_iret |
133 | #define USERGS_SYSRET64 \ | 133 | #define USERGS_SYSRET64 \ |
134 | swapgs; \ | 134 | swapgs; \ |
135 | sysretq; | 135 | sysretq; |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index b25ca969edd2..c844f0816ab8 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -830,27 +830,24 @@ restore_args: | |||
830 | RESTORE_ARGS 1,8,1 | 830 | RESTORE_ARGS 1,8,1 |
831 | 831 | ||
832 | irq_return: | 832 | irq_return: |
833 | INTERRUPT_RETURN | ||
834 | |||
835 | ENTRY(native_iret) | ||
833 | /* | 836 | /* |
834 | * Are we returning to a stack segment from the LDT? Note: in | 837 | * Are we returning to a stack segment from the LDT? Note: in |
835 | * 64-bit mode SS:RSP on the exception stack is always valid. | 838 | * 64-bit mode SS:RSP on the exception stack is always valid. |
836 | */ | 839 | */ |
837 | #ifdef CONFIG_X86_ESPFIX64 | 840 | #ifdef CONFIG_X86_ESPFIX64 |
838 | testb $4,(SS-RIP)(%rsp) | 841 | testb $4,(SS-RIP)(%rsp) |
839 | jnz irq_return_ldt | 842 | jnz native_irq_return_ldt |
840 | #endif | 843 | #endif |
841 | 844 | ||
842 | irq_return_iret: | 845 | native_irq_return_iret: |
843 | INTERRUPT_RETURN | ||
844 | _ASM_EXTABLE(irq_return_iret, bad_iret) | ||
845 | |||
846 | #ifdef CONFIG_PARAVIRT | ||
847 | ENTRY(native_iret) | ||
848 | iretq | 846 | iretq |
849 | _ASM_EXTABLE(native_iret, bad_iret) | 847 | _ASM_EXTABLE(native_irq_return_iret, bad_iret) |
850 | #endif | ||
851 | 848 | ||
852 | #ifdef CONFIG_X86_ESPFIX64 | 849 | #ifdef CONFIG_X86_ESPFIX64 |
853 | irq_return_ldt: | 850 | native_irq_return_ldt: |
854 | pushq_cfi %rax | 851 | pushq_cfi %rax |
855 | pushq_cfi %rdi | 852 | pushq_cfi %rdi |
856 | SWAPGS | 853 | SWAPGS |
@@ -872,7 +869,7 @@ irq_return_ldt: | |||
872 | SWAPGS | 869 | SWAPGS |
873 | movq %rax,%rsp | 870 | movq %rax,%rsp |
874 | popq_cfi %rax | 871 | popq_cfi %rax |
875 | jmp irq_return_iret | 872 | jmp native_irq_return_iret |
876 | #endif | 873 | #endif |
877 | 874 | ||
878 | .section .fixup,"ax" | 875 | .section .fixup,"ax" |
@@ -956,13 +953,8 @@ __do_double_fault: | |||
956 | cmpl $__KERNEL_CS,CS(%rdi) | 953 | cmpl $__KERNEL_CS,CS(%rdi) |
957 | jne do_double_fault | 954 | jne do_double_fault |
958 | movq RIP(%rdi),%rax | 955 | movq RIP(%rdi),%rax |
959 | cmpq $irq_return_iret,%rax | 956 | cmpq $native_irq_return_iret,%rax |
960 | #ifdef CONFIG_PARAVIRT | ||
961 | je 1f | ||
962 | cmpq $native_iret,%rax | ||
963 | #endif | ||
964 | jne do_double_fault /* This shouldn't happen... */ | 957 | jne do_double_fault /* This shouldn't happen... */ |
965 | 1: | ||
966 | movq PER_CPU_VAR(kernel_stack),%rax | 958 | movq PER_CPU_VAR(kernel_stack),%rax |
967 | subq $(6*8-KERNEL_STACK_OFFSET),%rax /* Reset to original stack */ | 959 | subq $(6*8-KERNEL_STACK_OFFSET),%rax /* Reset to original stack */ |
968 | movq %rax,RSP(%rdi) | 960 | movq %rax,RSP(%rdi) |
@@ -1428,7 +1420,7 @@ error_sti: | |||
1428 | */ | 1420 | */ |
1429 | error_kernelspace: | 1421 | error_kernelspace: |
1430 | incl %ebx | 1422 | incl %ebx |
1431 | leaq irq_return_iret(%rip),%rcx | 1423 | leaq native_irq_return_iret(%rip),%rcx |
1432 | cmpq %rcx,RIP+8(%rsp) | 1424 | cmpq %rcx,RIP+8(%rsp) |
1433 | je error_swapgs | 1425 | je error_swapgs |
1434 | movl %ecx,%eax /* zero extend */ | 1426 | movl %ecx,%eax /* zero extend */ |
diff --git a/arch/x86/kernel/paravirt_patch_64.c b/arch/x86/kernel/paravirt_patch_64.c index 3f08f34f93eb..a1da6737ba5b 100644 --- a/arch/x86/kernel/paravirt_patch_64.c +++ b/arch/x86/kernel/paravirt_patch_64.c | |||
@@ -6,7 +6,6 @@ DEF_NATIVE(pv_irq_ops, irq_disable, "cli"); | |||
6 | DEF_NATIVE(pv_irq_ops, irq_enable, "sti"); | 6 | DEF_NATIVE(pv_irq_ops, irq_enable, "sti"); |
7 | DEF_NATIVE(pv_irq_ops, restore_fl, "pushq %rdi; popfq"); | 7 | DEF_NATIVE(pv_irq_ops, restore_fl, "pushq %rdi; popfq"); |
8 | DEF_NATIVE(pv_irq_ops, save_fl, "pushfq; popq %rax"); | 8 | DEF_NATIVE(pv_irq_ops, save_fl, "pushfq; popq %rax"); |
9 | DEF_NATIVE(pv_cpu_ops, iret, "iretq"); | ||
10 | DEF_NATIVE(pv_mmu_ops, read_cr2, "movq %cr2, %rax"); | 9 | DEF_NATIVE(pv_mmu_ops, read_cr2, "movq %cr2, %rax"); |
11 | DEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax"); | 10 | DEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax"); |
12 | DEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3"); | 11 | DEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3"); |
@@ -50,7 +49,6 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf, | |||
50 | PATCH_SITE(pv_irq_ops, save_fl); | 49 | PATCH_SITE(pv_irq_ops, save_fl); |
51 | PATCH_SITE(pv_irq_ops, irq_enable); | 50 | PATCH_SITE(pv_irq_ops, irq_enable); |
52 | PATCH_SITE(pv_irq_ops, irq_disable); | 51 | PATCH_SITE(pv_irq_ops, irq_disable); |
53 | PATCH_SITE(pv_cpu_ops, iret); | ||
54 | PATCH_SITE(pv_cpu_ops, irq_enable_sysexit); | 52 | PATCH_SITE(pv_cpu_ops, irq_enable_sysexit); |
55 | PATCH_SITE(pv_cpu_ops, usergs_sysret32); | 53 | PATCH_SITE(pv_cpu_ops, usergs_sysret32); |
56 | PATCH_SITE(pv_cpu_ops, usergs_sysret64); | 54 | PATCH_SITE(pv_cpu_ops, usergs_sysret64); |