Commit ab234a26 authored by Juergen Gross's avatar Juergen Gross Committed by Borislav Petkov
Browse files

x86/pv: Rework arch_local_irq_restore() to not use popf



POPF is a rather expensive operation, so don't use it for restoring
irq flags. Instead, test whether interrupts are enabled in the flags
parameter and enable interrupts via STI in that case.

This results in the restore_fl paravirt op to be no longer needed.

Suggested-by: default avatarAndy Lutomirski <luto@kernel.org>
Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20210120135555.32594-7-jgross@suse.com
parent afd30525
Loading
Loading
Loading
Loading
+6 −14
Original line number Diff line number Diff line
@@ -35,15 +35,6 @@ extern __always_inline unsigned long native_save_fl(void)
	return flags;
}

extern inline void native_restore_fl(unsigned long flags);
extern inline void native_restore_fl(unsigned long flags)
{
	asm volatile("push %0 ; popf"
		     : /* no output */
		     :"g" (flags)
		     :"memory", "cc");
}

static __always_inline void native_irq_disable(void)
{
	asm volatile("cli": : :"memory");
@@ -79,11 +70,6 @@ static __always_inline unsigned long arch_local_save_flags(void)
	return native_save_fl();
}

static __always_inline void arch_local_irq_restore(unsigned long flags)
{
	native_restore_fl(flags);
}

static __always_inline void arch_local_irq_disable(void)
{
	native_irq_disable();
@@ -152,6 +138,12 @@ static __always_inline int arch_irqs_disabled(void)

	return arch_irqs_disabled_flags(flags);
}

static __always_inline void arch_local_irq_restore(unsigned long flags)
{
	if (!arch_irqs_disabled_flags(flags))
		arch_local_irq_enable();
}
#else
#ifdef CONFIG_X86_64
#ifdef CONFIG_XEN_PV
+0 −5
Original line number Diff line number Diff line
@@ -648,11 +648,6 @@ static inline notrace unsigned long arch_local_save_flags(void)
	return PVOP_CALLEE0(unsigned long, irq.save_fl);
}

static inline notrace void arch_local_irq_restore(unsigned long f)
{
	PVOP_VCALLEE1(irq.restore_fl, f);
}

static inline notrace void arch_local_irq_disable(void)
{
	PVOP_VCALLEE0(irq.irq_disable);
+2 −5
Original line number Diff line number Diff line
@@ -168,16 +168,13 @@ struct pv_cpu_ops {
struct pv_irq_ops {
#ifdef CONFIG_PARAVIRT_XXL
	/*
	 * Get/set interrupt state.  save_fl and restore_fl are only
	 * expected to use X86_EFLAGS_IF; all other bits
	 * returned from save_fl are undefined, and may be ignored by
	 * restore_fl.
	 * Get/set interrupt state.  save_fl is expected to use X86_EFLAGS_IF;
	 * all other bits returned from save_fl are undefined.
	 *
	 * NOTE: These functions callers expect the callee to preserve
	 * more registers than the standard C calling convention.
	 */
	struct paravirt_callee_save save_fl;
	struct paravirt_callee_save restore_fl;
	struct paravirt_callee_save irq_disable;
	struct paravirt_callee_save irq_enable;

+0 −11
Original line number Diff line number Diff line
@@ -13,14 +13,3 @@ SYM_FUNC_START(native_save_fl)
	ret
SYM_FUNC_END(native_save_fl)
EXPORT_SYMBOL(native_save_fl)

/*
 * void native_restore_fl(unsigned long flags)
 * %eax/%rdi: flags
 */
SYM_FUNC_START(native_restore_fl)
	push %_ASM_ARG1
	popf
	ret
SYM_FUNC_END(native_restore_fl)
EXPORT_SYMBOL(native_restore_fl)
+0 −1
Original line number Diff line number Diff line
@@ -320,7 +320,6 @@ struct paravirt_patch_template pv_ops = {

	/* Irq ops. */
	.irq.save_fl		= __PV_IS_CALLEE_SAVE(native_save_fl),
	.irq.restore_fl		= __PV_IS_CALLEE_SAVE(native_restore_fl),
	.irq.irq_disable	= __PV_IS_CALLEE_SAVE(native_irq_disable),
	.irq.irq_enable		= __PV_IS_CALLEE_SAVE(native_irq_enable),
	.irq.safe_halt		= native_safe_halt,
Loading