diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2008-06-25 00:19:27 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-08 07:13:37 -0400 |
commit | c7245da6ae7e5208504ff027c4e0eec69b788651 (patch) | |
tree | 47767af25940999d36f4682dd3e0820c1580092a | |
parent | d75cd22fdd5f7d203fb60014d426942df33dd9a6 (diff) |
x86/paravirt, 64-bit: don't restore user rsp within sysret
There's no need to combine restoring the user rsp within the sysret
pvop, so split it out. This makes the pvop's semantics closer to the
machine instruction.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citirx.com>
Cc: xen-devel <xen-devel@lists.xensource.com>
Cc: Stephen Tweedie <sct@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/kernel/asm-offsets_64.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 6 | ||||
-rw-r--r-- | arch/x86/kernel/paravirt.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/paravirt_patch_64.c | 4 | ||||
-rw-r--r-- | include/asm-x86/irqflags.h | 3 | ||||
-rw-r--r-- | include/asm-x86/paravirt.h | 8 |
6 files changed, 14 insertions, 15 deletions
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 27ac2deca465..a19aba8c5bb3 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c | |||
@@ -62,7 +62,7 @@ int main(void) | |||
62 | OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable); | 62 | OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable); |
63 | OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable); | 63 | OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable); |
64 | OFFSET(PV_CPU_iret, pv_cpu_ops, iret); | 64 | OFFSET(PV_CPU_iret, pv_cpu_ops, iret); |
65 | OFFSET(PV_CPU_usersp_sysret, pv_cpu_ops, usersp_sysret); | 65 | OFFSET(PV_CPU_usergs_sysret, pv_cpu_ops, usergs_sysret); |
66 | OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs); | 66 | OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs); |
67 | OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2); | 67 | OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2); |
68 | #endif | 68 | #endif |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 0056bc4c61a9..18447a373fbd 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -59,8 +59,7 @@ | |||
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | #ifdef CONFIG_PARAVIRT | 61 | #ifdef CONFIG_PARAVIRT |
62 | ENTRY(native_usersp_sysret) | 62 | ENTRY(native_usergs_sysret) |
63 | movq %gs:pda_oldrsp,%rsp | ||
64 | swapgs | 63 | swapgs |
65 | sysretq | 64 | sysretq |
66 | #endif /* CONFIG_PARAVIRT */ | 65 | #endif /* CONFIG_PARAVIRT */ |
@@ -275,7 +274,8 @@ sysret_check: | |||
275 | CFI_REGISTER rip,rcx | 274 | CFI_REGISTER rip,rcx |
276 | RESTORE_ARGS 0,-ARG_SKIP,1 | 275 | RESTORE_ARGS 0,-ARG_SKIP,1 |
277 | /*CFI_REGISTER rflags,r11*/ | 276 | /*CFI_REGISTER rflags,r11*/ |
278 | USERSP_SYSRET | 277 | movq %gs:pda_oldrsp, %rsp |
278 | USERGS_SYSRET | ||
279 | 279 | ||
280 | CFI_RESTORE_STATE | 280 | CFI_RESTORE_STATE |
281 | /* Handle reschedules */ | 281 | /* Handle reschedules */ |
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 565ee7a990ea..b0b17f0bc7e9 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c | |||
@@ -141,7 +141,7 @@ unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf, | |||
141 | ret = paravirt_patch_nop(); | 141 | ret = paravirt_patch_nop(); |
142 | else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) || | 142 | else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) || |
143 | type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) || | 143 | type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) || |
144 | type == PARAVIRT_PATCH(pv_cpu_ops.usersp_sysret)) | 144 | type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret)) |
145 | /* If operation requires a jmp, then jmp */ | 145 | /* If operation requires a jmp, then jmp */ |
146 | ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len); | 146 | ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len); |
147 | else | 147 | else |
@@ -193,7 +193,7 @@ static void native_flush_tlb_single(unsigned long addr) | |||
193 | /* These are in entry.S */ | 193 | /* These are in entry.S */ |
194 | extern void native_iret(void); | 194 | extern void native_iret(void); |
195 | extern void native_irq_enable_sysexit(void); | 195 | extern void native_irq_enable_sysexit(void); |
196 | extern void native_usersp_sysret(void); | 196 | extern void native_usergs_sysret(void); |
197 | 197 | ||
198 | static int __init print_banner(void) | 198 | static int __init print_banner(void) |
199 | { | 199 | { |
@@ -332,7 +332,7 @@ struct pv_cpu_ops pv_cpu_ops = { | |||
332 | #ifdef CONFIG_X86_32 | 332 | #ifdef CONFIG_X86_32 |
333 | .irq_enable_sysexit = native_irq_enable_sysexit, | 333 | .irq_enable_sysexit = native_irq_enable_sysexit, |
334 | #else | 334 | #else |
335 | .usersp_sysret = native_usersp_sysret, | 335 | .usergs_sysret = native_usergs_sysret, |
336 | #endif | 336 | #endif |
337 | .iret = native_iret, | 337 | .iret = native_iret, |
338 | .swapgs = native_swapgs, | 338 | .swapgs = native_swapgs, |
diff --git a/arch/x86/kernel/paravirt_patch_64.c b/arch/x86/kernel/paravirt_patch_64.c index 4a170552b852..d4c0712a3e64 100644 --- a/arch/x86/kernel/paravirt_patch_64.c +++ b/arch/x86/kernel/paravirt_patch_64.c | |||
@@ -15,7 +15,7 @@ DEF_NATIVE(pv_cpu_ops, clts, "clts"); | |||
15 | DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd"); | 15 | DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd"); |
16 | 16 | ||
17 | /* the three commands give us more control to how to return from a syscall */ | 17 | /* the three commands give us more control to how to return from a syscall */ |
18 | DEF_NATIVE(pv_cpu_ops, usersp_sysret, "movq %gs:" __stringify(pda_oldrsp) ", %rsp; swapgs; sysretq;"); | 18 | DEF_NATIVE(pv_cpu_ops, usergs_sysret, "swapgs; sysretq;"); |
19 | DEF_NATIVE(pv_cpu_ops, swapgs, "swapgs"); | 19 | DEF_NATIVE(pv_cpu_ops, swapgs, "swapgs"); |
20 | 20 | ||
21 | unsigned native_patch(u8 type, u16 clobbers, void *ibuf, | 21 | unsigned native_patch(u8 type, u16 clobbers, void *ibuf, |
@@ -35,7 +35,7 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf, | |||
35 | PATCH_SITE(pv_irq_ops, irq_enable); | 35 | PATCH_SITE(pv_irq_ops, irq_enable); |
36 | PATCH_SITE(pv_irq_ops, irq_disable); | 36 | PATCH_SITE(pv_irq_ops, irq_disable); |
37 | PATCH_SITE(pv_cpu_ops, iret); | 37 | PATCH_SITE(pv_cpu_ops, iret); |
38 | PATCH_SITE(pv_cpu_ops, usersp_sysret); | 38 | PATCH_SITE(pv_cpu_ops, usergs_sysret); |
39 | PATCH_SITE(pv_cpu_ops, swapgs); | 39 | PATCH_SITE(pv_cpu_ops, swapgs); |
40 | PATCH_SITE(pv_mmu_ops, read_cr2); | 40 | PATCH_SITE(pv_mmu_ops, read_cr2); |
41 | PATCH_SITE(pv_mmu_ops, read_cr3); | 41 | PATCH_SITE(pv_mmu_ops, read_cr3); |
diff --git a/include/asm-x86/irqflags.h b/include/asm-x86/irqflags.h index 99ee5256a7e3..544836c96b61 100644 --- a/include/asm-x86/irqflags.h +++ b/include/asm-x86/irqflags.h | |||
@@ -112,8 +112,7 @@ static inline unsigned long __raw_local_irq_save(void) | |||
112 | 112 | ||
113 | #ifdef CONFIG_X86_64 | 113 | #ifdef CONFIG_X86_64 |
114 | #define INTERRUPT_RETURN iretq | 114 | #define INTERRUPT_RETURN iretq |
115 | #define USERSP_SYSRET \ | 115 | #define USERGS_SYSRET \ |
116 | movq %gs:pda_oldrsp, %rsp; \ | ||
117 | swapgs; \ | 116 | swapgs; \ |
118 | sysretq; | 117 | sysretq; |
119 | #else | 118 | #else |
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index 2668903b70f5..dad5b4186f51 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h | |||
@@ -143,7 +143,7 @@ struct pv_cpu_ops { | |||
143 | 143 | ||
144 | /* These three are jmp to, not actually called. */ | 144 | /* These three are jmp to, not actually called. */ |
145 | void (*irq_enable_sysexit)(void); | 145 | void (*irq_enable_sysexit)(void); |
146 | void (*usersp_sysret)(void); | 146 | void (*usergs_sysret)(void); |
147 | void (*iret)(void); | 147 | void (*iret)(void); |
148 | 148 | ||
149 | void (*swapgs)(void); | 149 | void (*swapgs)(void); |
@@ -1505,10 +1505,10 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1505 | movq %rax, %rcx; \ | 1505 | movq %rax, %rcx; \ |
1506 | xorq %rax, %rax; | 1506 | xorq %rax, %rax; |
1507 | 1507 | ||
1508 | #define USERSP_SYSRET \ | 1508 | #define USERGS_SYSRET \ |
1509 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usersp_sysret), \ | 1509 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret), \ |
1510 | CLBR_NONE, \ | 1510 | CLBR_NONE, \ |
1511 | jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usersp_sysret)) | 1511 | jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret)) |
1512 | #endif | 1512 | #endif |
1513 | 1513 | ||
1514 | #endif /* __ASSEMBLY__ */ | 1514 | #endif /* __ASSEMBLY__ */ |