Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/alternatives: Use optimized NOPs for padding

Alternatives allow now for an empty old instruction. In this case we go
and pad the space with NOPs at assembly time. However, there are the
optimal, longer NOPs which should be used. Do that at patching time by
adding alt_instr.padlen-sized NOPs at the old instruction address.

Cc: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: Borislav Petkov <bp@suse.de>

+13 -1
+13 -1
arch/x86/kernel/alternative.c
··· 323 323 n_dspl, (unsigned long)orig_insn + n_dspl + repl_len); 324 324 } 325 325 326 + static void __init_or_module optimize_nops(struct alt_instr *a, u8 *instr) 327 + { 328 + add_nops(instr + (a->instrlen - a->padlen), a->padlen); 329 + 330 + DUMP_BYTES(instr, a->instrlen, "%p: [%d:%d) optimized NOPs: ", 331 + instr, a->instrlen - a->padlen, a->padlen); 332 + } 333 + 326 334 /* 327 335 * Replace instructions with better alternatives for this CPU type. This runs 328 336 * before SMP is initialized to avoid SMP problems with self modifying code. ··· 362 354 replacement = (u8 *)&a->repl_offset + a->repl_offset; 363 355 BUG_ON(a->instrlen > sizeof(insnbuf)); 364 356 BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32); 365 - if (!boot_cpu_has(a->cpuid)) 357 + if (!boot_cpu_has(a->cpuid)) { 358 + if (a->padlen > 1) 359 + optimize_nops(a, instr); 360 + 366 361 continue; 362 + } 367 363 368 364 DPRINTK("feat: %d*32+%d, old: (%p, len: %d), repl: (%p, len: %d)", 369 365 a->cpuid >> 5,