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

x86/paravirt: Switch iret pvops to ALTERNATIVE



The iret paravirt op is rather special as it is using a jmp instead
of a call instruction. Switch it to ALTERNATIVE.

Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20210311142319.4723-12-jgross@suse.com
parent 0b8d366a
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -747,9 +747,9 @@ extern void default_banner(void);
#define PARA_INDIRECT(addr)	*addr(%rip)

#define INTERRUPT_RETURN						\
	PARA_SITE(PARA_PATCH(PV_CPU_iret),				\
	ANNOTATE_RETPOLINE_SAFE;					\
		  jmp PARA_INDIRECT(pv_ops+PV_CPU_iret);)
	ALTERNATIVE_TERNARY("jmp *paravirt_iret(%rip);",		\
		X86_FEATURE_XENPV, "jmp xen_iret;", "jmp native_iret;")

#ifdef CONFIG_DEBUG_ENTRY
#define SAVE_FLAGS(clobbers)                                        \
+1 −4
Original line number Diff line number Diff line
@@ -151,10 +151,6 @@ struct pv_cpu_ops {

	u64 (*read_pmc)(int counter);

	/* Normal iret.  Jump to this with the standard iret stack
	   frame set up. */
	void (*iret)(void);

	void (*start_context_switch)(struct task_struct *prev);
	void (*end_context_switch)(struct task_struct *next);
#endif
@@ -294,6 +290,7 @@ 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 *))
+0 −5
Original line number Diff line number Diff line
@@ -61,11 +61,6 @@ static void __used common(void)
	OFFSET(IA32_RT_SIGFRAME_sigcontext, rt_sigframe_ia32, uc.uc_mcontext);
#endif

#ifdef CONFIG_PARAVIRT_XXL
	BLANK();
	OFFSET(PV_CPU_iret, paravirt_patch_template, cpu.iret);
#endif

#ifdef CONFIG_XEN
	BLANK();
	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
+2 −24
Original line number Diff line number Diff line
@@ -86,25 +86,6 @@ u64 notrace _paravirt_ident_64(u64 x)
{
	return x;
}

static unsigned paravirt_patch_jmp(void *insn_buff, const void *target,
				   unsigned long addr, unsigned len)
{
	struct branch *b = insn_buff;
	unsigned long delta = (unsigned long)target - (addr+5);

	if (len < 5) {
#ifdef CONFIG_RETPOLINE
		WARN_ONCE(1, "Failing to patch indirect JMP in %ps\n", (void *)addr);
#endif
		return len;	/* call too long for patch site */
	}

	b->opcode = 0xe9;	/* jmp */
	b->delta = delta;

	return 5;
}
#endif

DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key);
@@ -136,9 +117,6 @@ unsigned paravirt_patch_default(u8 type, void *insn_buff,
	else if (opfunc == _paravirt_ident_64)
		ret = paravirt_patch_ident_64(insn_buff, len);

	else if (type == PARAVIRT_PATCH(cpu.iret))
		/* If operation requires a jmp, then jmp */
		ret = paravirt_patch_jmp(insn_buff, opfunc, addr, len);
#endif
	else
		/* Otherwise call the function. */
@@ -313,8 +291,6 @@ struct paravirt_patch_template pv_ops = {

	.cpu.load_sp0		= native_load_sp0,

	.cpu.iret		= native_iret,

#ifdef CONFIG_X86_IOPL_IOPERM
	.cpu.invalidate_io_bitmap	= native_tss_invalidate_io_bitmap,
	.cpu.update_io_bitmap		= native_tss_update_io_bitmap,
@@ -419,6 +395,8 @@ struct paravirt_patch_template pv_ops = {
NOKPROBE_SYMBOL(native_get_debugreg);
NOKPROBE_SYMBOL(native_set_debugreg);
NOKPROBE_SYMBOL(native_load_idt);

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

EXPORT_SYMBOL(pv_ops);
+1 −2
Original line number Diff line number Diff line
@@ -1070,8 +1070,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {

	.read_pmc = xen_read_pmc,

	.iret = xen_iret,

	.load_tr_desc = paravirt_nop,
	.set_ldt = xen_set_ldt,
	.load_gdt = xen_load_gdt,
@@ -1235,6 +1233,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
	pv_info = xen_info;
	pv_ops.init.patch = paravirt_patch_default;
	pv_ops.cpu = xen_cpu_ops;
	paravirt_iret = xen_iret;
	xen_init_irq_ops();

	/*