Skip to content

Commit afd3052

Browse files
jgross1suryasaimadhu
authored andcommitted
x86/xen: Drop USERGS_SYSRET64 paravirt call
USERGS_SYSRET64 is used to return from a syscall via SYSRET, but a Xen PV guest will nevertheless use the IRET hypercall, as there is no sysret PV hypercall defined. So instead of testing all the prerequisites for doing a sysret and then mangling the stack for Xen PV again for doing an iret just use the iret exit from the beginning. This can easily be done via an ALTERNATIVE like it is done for the sysenter compat case already. It should be noted that this drops the optimization in Xen for not restoring a few registers when returning to user mode, but it seems as if the saved instructions in the kernel more than compensate for this drop (a kernel build in a Xen PV guest was slightly faster with this patch applied). While at it remove the stale sysret32 remnants. Signed-off-by: Juergen Gross <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 53c9d92 commit afd3052

File tree

10 files changed

+8
-61
lines changed

10 files changed

+8
-61
lines changed

arch/x86/entry/entry_64.S

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,6 @@
4646
.code64
4747
.section .entry.text, "ax"
4848

49-
#ifdef CONFIG_PARAVIRT_XXL
50-
SYM_CODE_START(native_usergs_sysret64)
51-
UNWIND_HINT_EMPTY
52-
swapgs
53-
sysretq
54-
SYM_CODE_END(native_usergs_sysret64)
55-
#endif /* CONFIG_PARAVIRT_XXL */
56-
5749
/*
5850
* 64-bit SYSCALL instruction entry. Up to 6 arguments in registers.
5951
*
@@ -123,7 +115,12 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
123115
* Try to use SYSRET instead of IRET if we're returning to
124116
* a completely clean 64-bit userspace context. If we're not,
125117
* go to the slow exit path.
118+
* In the Xen PV case we must use iret anyway.
126119
*/
120+
121+
ALTERNATIVE "", "jmp swapgs_restore_regs_and_return_to_usermode", \
122+
X86_FEATURE_XENPV
123+
127124
movq RCX(%rsp), %rcx
128125
movq RIP(%rsp), %r11
129126

@@ -215,7 +212,8 @@ syscall_return_via_sysret:
215212

216213
popq %rdi
217214
popq %rsp
218-
USERGS_SYSRET64
215+
swapgs
216+
sysretq
219217
SYM_CODE_END(entry_SYSCALL_64)
220218

221219
/*

arch/x86/include/asm/irqflags.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,6 @@ static __always_inline unsigned long arch_local_irq_save(void)
132132
#endif
133133

134134
#define INTERRUPT_RETURN jmp native_iret
135-
#define USERGS_SYSRET64 \
136-
swapgs; \
137-
sysretq;
138-
#define USERGS_SYSRET32 \
139-
swapgs; \
140-
sysretl
141135

142136
#else
143137
#define INTERRUPT_RETURN iret

arch/x86/include/asm/paravirt.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -776,11 +776,6 @@ extern void default_banner(void);
776776

777777
#ifdef CONFIG_X86_64
778778
#ifdef CONFIG_PARAVIRT_XXL
779-
#define USERGS_SYSRET64 \
780-
PARA_SITE(PARA_PATCH(PV_CPU_usergs_sysret64), \
781-
ANNOTATE_RETPOLINE_SAFE; \
782-
jmp PARA_INDIRECT(pv_ops+PV_CPU_usergs_sysret64);)
783-
784779
#ifdef CONFIG_DEBUG_ENTRY
785780
#define SAVE_FLAGS(clobbers) \
786781
PARA_SITE(PARA_PATCH(PV_IRQ_save_fl), \

arch/x86/include/asm/paravirt_types.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,6 @@ struct pv_cpu_ops {
156156

157157
u64 (*read_pmc)(int counter);
158158

159-
/*
160-
* Switch to usermode gs and return to 64-bit usermode using
161-
* sysret. Only used in 64-bit kernels to return to 64-bit
162-
* processes. Usermode register state, including %rsp, must
163-
* already be restored.
164-
*/
165-
void (*usergs_sysret64)(void);
166-
167159
/* Normal iret. Jump to this with the standard iret stack
168160
frame set up. */
169161
void (*iret)(void);

arch/x86/kernel/asm-offsets_64.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ int main(void)
1313
{
1414
#ifdef CONFIG_PARAVIRT
1515
#ifdef CONFIG_PARAVIRT_XXL
16-
OFFSET(PV_CPU_usergs_sysret64, paravirt_patch_template,
17-
cpu.usergs_sysret64);
1816
#ifdef CONFIG_DEBUG_ENTRY
1917
OFFSET(PV_IRQ_save_fl, paravirt_patch_template, irq.save_fl);
2018
#endif

arch/x86/kernel/paravirt.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,7 @@ unsigned paravirt_patch_default(u8 type, void *insn_buff,
135135
else if (opfunc == _paravirt_ident_64)
136136
ret = paravirt_patch_ident_64(insn_buff, len);
137137

138-
else if (type == PARAVIRT_PATCH(cpu.iret) ||
139-
type == PARAVIRT_PATCH(cpu.usergs_sysret64))
138+
else if (type == PARAVIRT_PATCH(cpu.iret))
140139
/* If operation requires a jmp, then jmp */
141140
ret = paravirt_patch_jmp(insn_buff, opfunc, addr, len);
142141
#endif
@@ -170,7 +169,6 @@ static u64 native_steal_clock(int cpu)
170169

171170
/* These are in entry.S */
172171
extern void native_iret(void);
173-
extern void native_usergs_sysret64(void);
174172

175173
static struct resource reserve_ioports = {
176174
.start = 0,
@@ -310,7 +308,6 @@ struct paravirt_patch_template pv_ops = {
310308

311309
.cpu.load_sp0 = native_load_sp0,
312310

313-
.cpu.usergs_sysret64 = native_usergs_sysret64,
314311
.cpu.iret = native_iret,
315312

316313
#ifdef CONFIG_X86_IOPL_IOPERM

arch/x86/kernel/paravirt_patch.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ struct patch_xxl {
2727
const unsigned char mmu_write_cr3[3];
2828
const unsigned char irq_restore_fl[2];
2929
const unsigned char cpu_wbinvd[2];
30-
const unsigned char cpu_usergs_sysret64[6];
3130
const unsigned char mov64[3];
3231
};
3332

@@ -40,8 +39,6 @@ static const struct patch_xxl patch_data_xxl = {
4039
.mmu_write_cr3 = { 0x0f, 0x22, 0xdf }, // mov %rdi, %cr3
4140
.irq_restore_fl = { 0x57, 0x9d }, // push %rdi; popfq
4241
.cpu_wbinvd = { 0x0f, 0x09 }, // wbinvd
43-
.cpu_usergs_sysret64 = { 0x0f, 0x01, 0xf8,
44-
0x48, 0x0f, 0x07 }, // swapgs; sysretq
4542
.mov64 = { 0x48, 0x89, 0xf8 }, // mov %rdi, %rax
4643
};
4744

@@ -83,7 +80,6 @@ unsigned int native_patch(u8 type, void *insn_buff, unsigned long addr,
8380
PATCH_CASE(mmu, read_cr3, xxl, insn_buff, len);
8481
PATCH_CASE(mmu, write_cr3, xxl, insn_buff, len);
8582

86-
PATCH_CASE(cpu, usergs_sysret64, xxl, insn_buff, len);
8783
PATCH_CASE(cpu, wbinvd, xxl, insn_buff, len);
8884
#endif
8985

arch/x86/xen/enlighten_pv.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
10731073
.read_pmc = xen_read_pmc,
10741074

10751075
.iret = xen_iret,
1076-
.usergs_sysret64 = xen_sysret64,
10771076

10781077
.load_tr_desc = paravirt_nop,
10791078
.set_ldt = xen_set_ldt,

arch/x86/xen/xen-asm.S

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -215,26 +215,6 @@ SYM_CODE_START(xen_iret)
215215
jmp hypercall_iret
216216
SYM_CODE_END(xen_iret)
217217

218-
SYM_CODE_START(xen_sysret64)
219-
/*
220-
* We're already on the usermode stack at this point, but
221-
* still with the kernel gs, so we can easily switch back.
222-
*
223-
* tss.sp2 is scratch space.
224-
*/
225-
movq %rsp, PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
226-
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
227-
228-
pushq $__USER_DS
229-
pushq PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
230-
pushq %r11
231-
pushq $__USER_CS
232-
pushq %rcx
233-
234-
pushq $VGCF_in_syscall
235-
jmp hypercall_iret
236-
SYM_CODE_END(xen_sysret64)
237-
238218
/*
239219
* Xen handles syscall callbacks much like ordinary exceptions, which
240220
* means we have:

arch/x86/xen/xen-ops.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,6 @@ __visible unsigned long xen_read_cr2_direct(void);
138138

139139
/* These are not functions, and cannot be called normally */
140140
__visible void xen_iret(void);
141-
__visible void xen_sysret32(void);
142-
__visible void xen_sysret64(void);
143141

144142
extern int xen_panic_handler_init(void);
145143

0 commit comments

Comments
 (0)