x86/ibt,paravirt: Use text_gen_insn() for paravirt_patch()
Upstream commit: ba27d1a80871eb8dbeddf34ec7d396c149cbb8d7 Less duplication is more better. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Link: https://lore.kernel.org/r/20220308154317.697253958@infradead.org [ Keep struct branch. ] Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
e752912ce1
commit
b253061d4b
@ -96,32 +96,40 @@ union text_poke_insn {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static __always_inline
|
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 */
|
union text_poke_insn *insn = buf;
|
||||||
int size = text_opcode_size(opcode);
|
|
||||||
|
BUG_ON(size < text_opcode_size(opcode));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hide the addresses to avoid the compiler folding in constants when
|
* Hide the addresses to avoid the compiler folding in constants when
|
||||||
* referencing code, these can mess up annotations like
|
* referencing code, these can mess up annotations like
|
||||||
* ANNOTATE_NOENDBR.
|
* ANNOTATE_NOENDBR.
|
||||||
*/
|
*/
|
||||||
|
OPTIMIZER_HIDE_VAR(insn);
|
||||||
OPTIMIZER_HIDE_VAR(addr);
|
OPTIMIZER_HIDE_VAR(addr);
|
||||||
OPTIMIZER_HIDE_VAR(dest);
|
OPTIMIZER_HIDE_VAR(dest);
|
||||||
|
|
||||||
insn.opcode = opcode;
|
insn->opcode = opcode;
|
||||||
|
|
||||||
if (size > 1) {
|
if (size > 1) {
|
||||||
insn.disp = (long)dest - (long)(addr + size);
|
insn->disp = (long)dest - (long)(addr + size);
|
||||||
if (size == 2) {
|
if (size == 2) {
|
||||||
/*
|
/*
|
||||||
* Ensure that for JMP8 the displacement
|
* Ensure that for JMP8 the displacement
|
||||||
* actually fits the signed byte.
|
* 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;
|
return &insn.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,28 +55,16 @@ void __init default_banner(void)
|
|||||||
static const unsigned char ud2a[] = { 0x0f, 0x0b };
|
static const unsigned char ud2a[] = { 0x0f, 0x0b };
|
||||||
|
|
||||||
struct branch {
|
struct branch {
|
||||||
unsigned char opcode;
|
unsigned char opcode;
|
||||||
u32 delta;
|
u32 delta;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
static unsigned paravirt_patch_call(void *insn_buff, const void *target,
|
static unsigned paravirt_patch_call(void *insn_buff, const void *target,
|
||||||
unsigned long addr, unsigned len)
|
unsigned long addr, unsigned len)
|
||||||
{
|
{
|
||||||
const int call_len = 5;
|
__text_gen_insn(insn_buff, CALL_INSN_OPCODE,
|
||||||
struct branch *b = insn_buff;
|
(void *)addr, target, CALL_INSN_SIZE);
|
||||||
unsigned long delta = (unsigned long)target - (addr+call_len);
|
return CALL_INSN_SIZE;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PARAVIRT_XXL
|
#ifdef CONFIG_PARAVIRT_XXL
|
||||||
|
Loading…
Reference in New Issue
Block a user