Commit 6becb502 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Borislav Petkov (AMD)

x86/alternative: Make debug-alternative selective

Using debug-alternative generates a *LOT* of output, extend it a bit
to select which of the many rewrites it reports on.
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230208171431.253636689@infradead.org
parent ac9a7868
...@@ -37,11 +37,23 @@ EXPORT_SYMBOL_GPL(alternatives_patched); ...@@ -37,11 +37,23 @@ EXPORT_SYMBOL_GPL(alternatives_patched);
#define MAX_PATCH_LEN (255-1) #define MAX_PATCH_LEN (255-1)
static int __initdata_or_module debug_alternative; #define DA_ALL (~0)
#define DA_ALT 0x01
#define DA_RET 0x02
#define DA_RETPOLINE 0x04
#define DA_ENDBR 0x08
#define DA_SMP 0x10
static unsigned int __initdata_or_module debug_alternative;
static int __init debug_alt(char *str) static int __init debug_alt(char *str)
{ {
debug_alternative = 1; if (str && *str == '=')
str++;
if (!str || kstrtouint(str, 0, &debug_alternative))
debug_alternative = DA_ALL;
return 1; return 1;
} }
__setup("debug-alternative", debug_alt); __setup("debug-alternative", debug_alt);
...@@ -55,15 +67,15 @@ static int __init setup_noreplace_smp(char *str) ...@@ -55,15 +67,15 @@ static int __init setup_noreplace_smp(char *str)
} }
__setup("noreplace-smp", setup_noreplace_smp); __setup("noreplace-smp", setup_noreplace_smp);
#define DPRINTK(fmt, args...) \ #define DPRINTK(type, fmt, args...) \
do { \ do { \
if (debug_alternative) \ if (debug_alternative & DA_##type) \
printk(KERN_DEBUG pr_fmt(fmt) "\n", ##args); \ printk(KERN_DEBUG pr_fmt(fmt) "\n", ##args); \
} while (0) } while (0)
#define DUMP_BYTES(buf, len, fmt, args...) \ #define DUMP_BYTES(type, buf, len, fmt, args...) \
do { \ do { \
if (unlikely(debug_alternative)) { \ if (unlikely(debug_alternative & DA_##type)) { \
int j; \ int j; \
\ \
if (!(len)) \ if (!(len)) \
...@@ -148,7 +160,7 @@ recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insn_buff) ...@@ -148,7 +160,7 @@ recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insn_buff)
tgt_rip = next_rip + o_dspl; tgt_rip = next_rip + o_dspl;
n_dspl = tgt_rip - orig_insn; n_dspl = tgt_rip - orig_insn;
DPRINTK("target RIP: %px, new_displ: 0x%x", tgt_rip, n_dspl); DPRINTK(ALT, "target RIP: %px, new_displ: 0x%x", tgt_rip, n_dspl);
if (tgt_rip - orig_insn >= 0) { if (tgt_rip - orig_insn >= 0) {
if (n_dspl - 2 <= 127) if (n_dspl - 2 <= 127)
...@@ -183,7 +195,7 @@ recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insn_buff) ...@@ -183,7 +195,7 @@ recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insn_buff)
done: done:
DPRINTK("final displ: 0x%08x, JMP 0x%lx", DPRINTK(ALT, "final displ: 0x%08x, JMP 0x%lx",
n_dspl, (unsigned long)orig_insn + n_dspl + repl_len); n_dspl, (unsigned long)orig_insn + n_dspl + repl_len);
} }
...@@ -217,7 +229,7 @@ static __always_inline int optimize_nops_range(u8 *instr, u8 instrlen, int off) ...@@ -217,7 +229,7 @@ static __always_inline int optimize_nops_range(u8 *instr, u8 instrlen, int off)
add_nops(instr + off, nnops); add_nops(instr + off, nnops);
local_irq_restore(flags); local_irq_restore(flags);
DUMP_BYTES(instr, instrlen, "%px: [%d:%d) optimized NOPs: ", instr, off, i); DUMP_BYTES(ALT, instr, instrlen, "%px: [%d:%d) optimized NOPs: ", instr, off, i);
return nnops; return nnops;
} }
...@@ -270,7 +282,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, ...@@ -270,7 +282,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
u8 *instr, *replacement; u8 *instr, *replacement;
u8 insn_buff[MAX_PATCH_LEN]; u8 insn_buff[MAX_PATCH_LEN];
DPRINTK("alt table %px, -> %px", start, end); DPRINTK(ALT, "alt table %px, -> %px", start, end);
/* /*
* The scan order should be from start to end. A later scanned * The scan order should be from start to end. A later scanned
* alternative code can overwrite previously scanned alternative code. * alternative code can overwrite previously scanned alternative code.
...@@ -297,15 +309,15 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, ...@@ -297,15 +309,15 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
if (!boot_cpu_has(a->cpuid) == !(a->flags & ALT_FLAG_NOT)) if (!boot_cpu_has(a->cpuid) == !(a->flags & ALT_FLAG_NOT))
goto next; goto next;
DPRINTK("feat: %s%d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d)", DPRINTK(ALT, "feat: %s%d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d)",
(a->flags & ALT_FLAG_NOT) ? "!" : "", (a->flags & ALT_FLAG_NOT) ? "!" : "",
a->cpuid >> 5, a->cpuid >> 5,
a->cpuid & 0x1f, a->cpuid & 0x1f,
instr, instr, a->instrlen, instr, instr, a->instrlen,
replacement, a->replacementlen); replacement, a->replacementlen);
DUMP_BYTES(instr, a->instrlen, "%px: old_insn: ", instr); DUMP_BYTES(ALT, instr, a->instrlen, "%px: old_insn: ", instr);
DUMP_BYTES(replacement, a->replacementlen, "%px: rpl_insn: ", replacement); DUMP_BYTES(ALT, replacement, a->replacementlen, "%px: rpl_insn: ", replacement);
memcpy(insn_buff, replacement, a->replacementlen); memcpy(insn_buff, replacement, a->replacementlen);
insn_buff_sz = a->replacementlen; insn_buff_sz = a->replacementlen;
...@@ -318,7 +330,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, ...@@ -318,7 +330,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
*/ */
if (a->replacementlen == 5 && *insn_buff == 0xe8) { if (a->replacementlen == 5 && *insn_buff == 0xe8) {
*(s32 *)(insn_buff + 1) += replacement - instr; *(s32 *)(insn_buff + 1) += replacement - instr;
DPRINTK("Fix CALL offset: 0x%x, CALL 0x%lx", DPRINTK(ALT, "Fix CALL offset: 0x%x, CALL 0x%lx",
*(s32 *)(insn_buff + 1), *(s32 *)(insn_buff + 1),
(unsigned long)instr + *(s32 *)(insn_buff + 1) + 5); (unsigned long)instr + *(s32 *)(insn_buff + 1) + 5);
} }
...@@ -329,7 +341,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, ...@@ -329,7 +341,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
for (; insn_buff_sz < a->instrlen; insn_buff_sz++) for (; insn_buff_sz < a->instrlen; insn_buff_sz++)
insn_buff[insn_buff_sz] = 0x90; insn_buff[insn_buff_sz] = 0x90;
DUMP_BYTES(insn_buff, insn_buff_sz, "%px: final_insn: ", instr); DUMP_BYTES(ALT, insn_buff, insn_buff_sz, "%px: final_insn: ", instr);
text_poke_early(instr, insn_buff, insn_buff_sz); text_poke_early(instr, insn_buff, insn_buff_sz);
...@@ -555,15 +567,15 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end) ...@@ -555,15 +567,15 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end)
continue; continue;
} }
DPRINTK("retpoline at: %pS (%px) len: %d to: %pS", DPRINTK(RETPOLINE, "retpoline at: %pS (%px) len: %d to: %pS",
addr, addr, insn.length, addr, addr, insn.length,
addr + insn.length + insn.immediate.value); addr + insn.length + insn.immediate.value);
len = patch_retpoline(addr, &insn, bytes); len = patch_retpoline(addr, &insn, bytes);
if (len == insn.length) { if (len == insn.length) {
optimize_nops(bytes, len); optimize_nops(bytes, len);
DUMP_BYTES(((u8*)addr), len, "%px: orig: ", addr); DUMP_BYTES(RETPOLINE, ((u8*)addr), len, "%px: orig: ", addr);
DUMP_BYTES(((u8*)bytes), len, "%px: repl: ", addr); DUMP_BYTES(RETPOLINE, ((u8*)bytes), len, "%px: repl: ", addr);
text_poke_early(addr, bytes, len); text_poke_early(addr, bytes, len);
} }
} }
...@@ -630,14 +642,14 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end) ...@@ -630,14 +642,14 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end)
addr, dest, 5, addr)) addr, dest, 5, addr))
continue; continue;
DPRINTK("return thunk at: %pS (%px) len: %d to: %pS", DPRINTK(RET, "return thunk at: %pS (%px) len: %d to: %pS",
addr, addr, insn.length, addr, addr, insn.length,
addr + insn.length + insn.immediate.value); addr + insn.length + insn.immediate.value);
len = patch_return(addr, &insn, bytes); len = patch_return(addr, &insn, bytes);
if (len == insn.length) { if (len == insn.length) {
DUMP_BYTES(((u8*)addr), len, "%px: orig: ", addr); DUMP_BYTES(RET, ((u8*)addr), len, "%px: orig: ", addr);
DUMP_BYTES(((u8*)bytes), len, "%px: repl: ", addr); DUMP_BYTES(RET, ((u8*)bytes), len, "%px: repl: ", addr);
text_poke_early(addr, bytes, len); text_poke_early(addr, bytes, len);
} }
} }
...@@ -667,13 +679,13 @@ static void poison_endbr(void *addr, bool warn) ...@@ -667,13 +679,13 @@ static void poison_endbr(void *addr, bool warn)
return; return;
} }
DPRINTK("ENDBR at: %pS (%px)", addr, addr); DPRINTK(ENDBR, "ENDBR at: %pS (%px)", addr, addr);
/* /*
* When we have IBT, the lack of ENDBR will trigger #CP * When we have IBT, the lack of ENDBR will trigger #CP
*/ */
DUMP_BYTES(((u8*)addr), 4, "%px: orig: ", addr); DUMP_BYTES(ENDBR, ((u8*)addr), 4, "%px: orig: ", addr);
DUMP_BYTES(((u8*)&poison), 4, "%px: repl: ", addr); DUMP_BYTES(ENDBR, ((u8*)&poison), 4, "%px: repl: ", addr);
text_poke_early(addr, &poison, 4); text_poke_early(addr, &poison, 4);
} }
...@@ -1148,7 +1160,7 @@ void __init_or_module alternatives_smp_module_add(struct module *mod, ...@@ -1148,7 +1160,7 @@ void __init_or_module alternatives_smp_module_add(struct module *mod,
smp->locks_end = locks_end; smp->locks_end = locks_end;
smp->text = text; smp->text = text;
smp->text_end = text_end; smp->text_end = text_end;
DPRINTK("locks %p -> %p, text %p -> %p, name %s\n", DPRINTK(SMP, "locks %p -> %p, text %p -> %p, name %s\n",
smp->locks, smp->locks_end, smp->locks, smp->locks_end,
smp->text, smp->text_end, smp->name); smp->text, smp->text_end, smp->name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment