xref: /linux/tools/objtool/tests/x86/fixtures/checksum_alt.c (revision 5b6dca02b3e2254d2fd5706d76d7ab4610a67296)
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