Commit 822da186 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by sanglipeng1
Browse files

x86/ibt,paravirt: Use text_gen_insn() for paravirt_patch()

stable inclusion
from stable-v5.10.211
commit b253061d4b863f0e9ebf25a3cf0313501a5d51b4
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAF2J4

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=b253061d4b863f0e9ebf25a3cf0313501a5d51b4



--------------------------------

Upstream commit: ba27d1a8

Less duplication is more better.

Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Link: https://lore.kernel.org/r/20220308154317.697253958@infradead.org


 [ Keep struct branch. ]
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarsanglipeng1 <sanglipeng1@jd.com>
parent 66e7f47c
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -96,32 +96,40 @@ union text_poke_insn {
};

static __always_inline
void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
void __text_gen_insn(void *buf, u8 opcode, const void *addr, const void *dest, int size)
{
	static union text_poke_insn insn; /* per instance */
	int size = text_opcode_size(opcode);
	union text_poke_insn *insn = buf;

	BUG_ON(size < text_opcode_size(opcode));

	/*
	 * Hide the addresses to avoid the compiler folding in constants when
	 * referencing code, these can mess up annotations like
	 * ANNOTATE_NOENDBR.
	 */
	OPTIMIZER_HIDE_VAR(insn);
	OPTIMIZER_HIDE_VAR(addr);
	OPTIMIZER_HIDE_VAR(dest);

	insn.opcode = opcode;
	insn->opcode = opcode;

	if (size > 1) {
		insn.disp = (long)dest - (long)(addr + size);
		insn->disp = (long)dest - (long)(addr + size);
		if (size == 2) {
			/*
			 * Ensure that for JMP8 the displacement
			 * actually fits the signed byte.
			 */
			BUG_ON((insn.disp >> 31) != (insn.disp >> 7));
			BUG_ON((insn->disp >> 31) != (insn->disp >> 7));
		}
	}
}

static __always_inline
void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
{
	static union text_poke_insn insn; /* per instance */
	__text_gen_insn(&insn, opcode, addr, dest, text_opcode_size(opcode));
	return &insn.text;
}

+5 −17
Original line number Diff line number Diff line
@@ -62,21 +62,9 @@ struct branch {
static unsigned paravirt_patch_call(void *insn_buff, const void *target,
				    unsigned long addr, unsigned len)
{
	const int call_len = 5;
	struct branch *b = insn_buff;
	unsigned long delta = (unsigned long)target - (addr+call_len);

	if (len < call_len) {
		pr_warn("paravirt: Failed to patch indirect CALL at %ps\n", (void *)addr);
		/* Kernel might not be viable if patching fails, bail out: */
		BUG_ON(1);
	}

	b->opcode = 0xe8; /* call */
	b->delta = delta;
	BUILD_BUG_ON(sizeof(*b) != call_len);

	return call_len;
	__text_gen_insn(insn_buff, CALL_INSN_OPCODE,
			(void *)addr, target, CALL_INSN_SIZE);
	return CALL_INSN_SIZE;
}

#ifdef CONFIG_PARAVIRT_XXL