1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * An x86 alternative whose replacement code is part of the patched function's 4 * checksum. 5 * 6 * checksum_update_insn() walks insn->alts after hashing the instruction 7 * itself, hashing the alternative's type and, when the replacement forms a 8 * group, its feature number and every instruction in it. So editing only the 9 * replacement -- code the CPU may or may not ever run -- has to move the 10 * function's checksum. 11 * 12 * It is reached through objtool's own alternative handling, so the object has 13 * to go through the check pass first: insn->alts is built there, not by the 14 * compiler. 15 * 16 * struct alt_instr is written out by hand as in empty_alternative.c: s32 17 * instr_offset, s32 repl_offset, u32 ft_flags, u8 instrlen, u8 replacementlen. 18 * 19 * Variants, applied to the patched build only: 20 * 21 * ALT_REPL the replacement instruction changes; the original does not 22 * ALT_FEATURE the feature number changes; no code changes at all 23 */ 24 25 static const char __modinfo[] 26 __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux"; 27 28 /* 29 * Both spellings are two bytes, because a replacement may not be longer than 30 * the instruction it replaces: "xchg %ax, %ax" is 66 90 and two nops are 31 * 90 90. The original below is padded to match. 32 */ 33 #if defined(PATCHED) && defined(ALT_REPL) 34 #define REPL_INSN " nop\n\t nop\n\t" 35 #else 36 #define REPL_INSN " xchg %ax, %ax\n\t" 37 #endif 38 39 #if defined(PATCHED) && defined(ALT_FEATURE) 40 #define FEATURE "7" 41 #else 42 #define FEATURE "3" 43 #endif 44 45 int target(int x) 46 { 47 asm volatile( 48 "661: nop\n\t" 49 " nop\n\t" 50 "662:\n\t" 51 ".pushsection .altinstr_replacement, \"ax\"\n\t" 52 ".globl target_repl\n\t" 53 "target_repl:\n\t" 54 REPL_INSN 55 "target_repl_end:\n\t" 56 ".popsection\n\t" 57 ".pushsection .altinstructions, \"aM\", @progbits, 14\n\t" 58 ".long 661b - .\n\t" 59 ".long target_repl - .\n\t" 60 ".long " FEATURE "\n\t" 61 ".byte 662b - 661b\n\t" 62 ".byte target_repl_end - target_repl\n\t" 63 ".popsection\n\t"); 64 65 return x + 1; 66 } 67