Skip to content

Commit

Permalink
x86/entry,xen: Early rewrite of restore_regs_and_return_to_kernel()
Browse files Browse the repository at this point in the history
By doing an early rewrite of 'jmp native_iret` in
restore_regs_and_return_to_kernel() we can get rid of the last
INTERRUPT_RETURN user and paravirt_iret.

Suggested-by: Andrew Cooper <Andrew.Cooper3@citrix.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Link: https://lore.kernel.org/r/20220308154317.815039833@infradead.org
  • Loading branch information
Peter Zijlstra committed Mar 15, 2022
1 parent 6cf3e4c commit 8b87d8c
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 15 deletions.
11 changes: 8 additions & 3 deletions arch/x86/entry/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
/* Restore RDI. */
popq %rdi
swapgs
jmp native_iret
jmp .Lnative_iret


SYM_INNER_LABEL(restore_regs_and_return_to_kernel, SYM_L_GLOBAL)
Expand All @@ -626,9 +626,14 @@ SYM_INNER_LABEL(restore_regs_and_return_to_kernel, SYM_L_GLOBAL)
* ARCH_HAS_MEMBARRIER_SYNC_CORE rely on IRET core serialization
* when returning from IPI handler.
*/
INTERRUPT_RETURN
#ifdef CONFIG_XEN_PV
SYM_INNER_LABEL(early_xen_iret_patch, SYM_L_GLOBAL)
ANNOTATE_NOENDBR
.byte 0xe9
.long .Lnative_iret - (. + 4)
#endif

SYM_INNER_LABEL_ALIGN(native_iret, SYM_L_GLOBAL)
.Lnative_iret:
UNWIND_HINT_IRET_REGS
/*
* Are we returning to a stack segment from the LDT? Note: in
Expand Down
5 changes: 0 additions & 5 deletions arch/x86/include/asm/irqflags.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,8 @@ static __always_inline void arch_local_irq_restore(unsigned long flags)
#ifdef CONFIG_X86_64
#ifdef CONFIG_XEN_PV
#define SWAPGS ALTERNATIVE "swapgs", "", X86_FEATURE_XENPV
#define INTERRUPT_RETURN \
ANNOTATE_RETPOLINE_SAFE; \
ALTERNATIVE_TERNARY("jmp *paravirt_iret(%rip);", \
X86_FEATURE_XENPV, "jmp xen_iret;", "jmp native_iret;")
#else
#define SWAPGS swapgs
#define INTERRUPT_RETURN jmp native_iret
#endif
#endif
#endif /* !__ASSEMBLY__ */
Expand Down
1 change: 0 additions & 1 deletion arch/x86/include/asm/paravirt_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,6 @@ struct paravirt_patch_template {

extern struct pv_info pv_info;
extern struct paravirt_patch_template pv_ops;
extern void (*paravirt_iret)(void);

#define PARAVIRT_PATCH(x) \
(offsetof(struct paravirt_patch_template, x) / sizeof(void *))
Expand Down
3 changes: 2 additions & 1 deletion arch/x86/kernel/head_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,6 @@ SYM_CODE_START_NOALIGN(vc_boot_ghcb)
/* Remove Error Code */
addq $8, %rsp

/* Pure iret required here - don't use INTERRUPT_RETURN */
iretq
SYM_CODE_END(vc_boot_ghcb)
#endif
Expand Down Expand Up @@ -426,6 +425,8 @@ SYM_CODE_END(early_idt_handler_common)
* early_idt_handler_array can't be used because it returns via the
* paravirtualized INTERRUPT_RETURN and pv-ops don't work that early.
*
* XXX it does, fix this.
*
* This handler will end up in the .init.text section and not be
* available to boot secondary CPUs.
*/
Expand Down
4 changes: 0 additions & 4 deletions arch/x86/kernel/paravirt.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,6 @@ void paravirt_set_sched_clock(u64 (*func)(void))
}

/* These are in entry.S */
extern void native_iret(void);

static struct resource reserve_ioports = {
.start = 0,
.end = IO_SPACE_LIMIT,
Expand Down Expand Up @@ -397,8 +395,6 @@ struct paravirt_patch_template pv_ops = {

#ifdef CONFIG_PARAVIRT_XXL
NOKPROBE_SYMBOL(native_load_idt);

void (*paravirt_iret)(void) = native_iret;
#endif

EXPORT_SYMBOL(pv_ops);
Expand Down
7 changes: 6 additions & 1 deletion arch/x86/xen/enlighten_pv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,8 @@ static void __init xen_domu_set_legacy_features(void)
x86_platform.legacy.rtc = 0;
}

extern void early_xen_iret_patch(void);

/* First C function to be called on Xen boot */
asmlinkage __visible void __init xen_start_kernel(void)
{
Expand All @@ -1187,6 +1189,10 @@ asmlinkage __visible void __init xen_start_kernel(void)
if (!xen_start_info)
return;

__text_gen_insn(&early_xen_iret_patch,
JMP32_INSN_OPCODE, &early_xen_iret_patch, &xen_iret,
JMP32_INSN_SIZE);

xen_domain_type = XEN_PV_DOMAIN;
xen_start_flags = xen_start_info->flags;

Expand All @@ -1195,7 +1201,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
/* Install Xen paravirt ops */
pv_info = xen_info;
pv_ops.cpu = xen_cpu_ops.cpu;
paravirt_iret = xen_iret;
xen_init_irq_ops();

/*
Expand Down
1 change: 1 addition & 0 deletions arch/x86/xen/xen-asm.S
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
*/
SYM_CODE_START(xen_iret)
UNWIND_HINT_EMPTY
ANNOTATE_NOENDBR
pushq $0
jmp hypercall_iret
SYM_CODE_END(xen_iret)
Expand Down

0 comments on commit 8b87d8c

Please sign in to comment.