aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-06-25 00:19:27 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-08 07:13:37 -0400
commitc7245da6ae7e5208504ff027c4e0eec69b788651 (patch)
tree47767af25940999d36f4682dd3e0820c1580092a
parentd75cd22fdd5f7d203fb60014d426942df33dd9a6 (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.c2
-rw-r--r--arch/x86/kernel/entry_64.S6
-rw-r--r--arch/x86/kernel/paravirt.c6
-rw-r--r--arch/x86/kernel/paravirt_patch_64.c4
-rw-r--r--include/asm-x86/irqflags.h3
-rw-r--r--include/asm-x86/paravirt.h8
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
62ENTRY(native_usersp_sysret) 62ENTRY(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 */
194extern void native_iret(void); 194extern void native_iret(void);
195extern void native_irq_enable_sysexit(void); 195extern void native_irq_enable_sysexit(void);
196extern void native_usersp_sysret(void); 196extern void native_usergs_sysret(void);
197 197
198static int __init print_banner(void) 198static 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");
15DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd"); 15DEF_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 */
18DEF_NATIVE(pv_cpu_ops, usersp_sysret, "movq %gs:" __stringify(pda_oldrsp) ", %rsp; swapgs; sysretq;"); 18DEF_NATIVE(pv_cpu_ops, usergs_sysret, "swapgs; sysretq;");
19DEF_NATIVE(pv_cpu_ops, swapgs, "swapgs"); 19DEF_NATIVE(pv_cpu_ops, swapgs, "swapgs");
20 20
21unsigned native_patch(u8 type, u16 clobbers, void *ibuf, 21unsigned 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__ */