Commit ba27d1a8 authored by Peter Zijlstra's avatar Peter Zijlstra
Browse files

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

parent bbf92368
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;
}

+3 −20
Original line number Diff line number Diff line
@@ -69,29 +69,12 @@ noinstr void paravirt_BUG(void)
	BUG();
}

struct branch {
	unsigned char opcode;
	u32 delta;
} __attribute__((packed));

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