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
target(int x)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