1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * An x86 alternative with an empty replacement, as the second entry of
4 * ALTERNATIVE_2("orig", "repl", ft1, "", ft2) produces. Its replacement
5 * offset still gets a relocation, but the label it points at is the end of the
6 * previous replacement, which is also where the *next* one begins -- here,
7 * neighbor()'s. The value is meaningless; it is only ever used with a length
8 * of zero.
9 *
10 * struct alt_instr is written out by hand so the fixture builds without kernel
11 * headers: s32 instr_offset, s32 repl_offset, u32 ft_flags, u8 instrlen,
12 * u8 replacementlen. The section carries an entsize because klp diff needs
13 * either that or an ANNOTATE_DATA_SPECIAL annotation to find entry boundaries.
14 *
15 * The replacement labels are global so the relocations name them rather than
16 * .altinstr_replacement plus an addend.
17 */
18
19 static const char __modinfo[]
20 __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
21
22 extern int neighbor_only(int x);
23
target(int x)24 int target(int x)
25 {
26 asm volatile(
27 "661: nop\n\t"
28 ".pushsection .altinstr_replacement, \"ax\"\n\t"
29 ".globl target_repl\n\t"
30 "target_repl:\n\t"
31 " nop\n\t"
32 "target_repl_end:\n\t"
33 ".popsection\n\t"
34 ".pushsection .altinstructions, \"aM\", @progbits, 14\n\t"
35 /* a real replacement */
36 ".long 661b - .\n\t"
37 ".long target_repl - .\n\t"
38 ".long 0\n\t"
39 ".byte 1\n\t"
40 ".byte target_repl_end - target_repl\n\t"
41 /* an empty one, pointing at neighbor()'s replacement */
42 ".long 661b - .\n\t"
43 ".long neighbor_repl - .\n\t"
44 ".long 0\n\t"
45 ".byte 1\n\t"
46 ".byte 0\n\t"
47 ".popsection\n\t");
48 #ifdef PATCHED
49 return x + 2;
50 #else
51 return x + 1;
52 #endif
53 }
54
55 /*
56 * Unrelated, unpatched, and referencing a symbol nothing else does, so that
57 * dragging its replacement in is visible.
58 */
neighbor(int x)59 int neighbor(int x)
60 {
61 asm volatile(
62 "771: nop\n\t"
63 ".pushsection .altinstr_replacement, \"ax\"\n\t"
64 ".globl neighbor_repl\n\t"
65 "neighbor_repl:\n\t"
66 " call neighbor_only\n\t"
67 "neighbor_repl_end:\n\t"
68 ".popsection\n\t"
69 ".pushsection .altinstructions, \"aM\", @progbits, 14\n\t"
70 ".long 771b - .\n\t"
71 ".long neighbor_repl - .\n\t"
72 ".long 0\n\t"
73 ".byte 1\n\t"
74 ".byte neighbor_repl_end - neighbor_repl\n\t"
75 ".popsection\n\t");
76 return x;
77 }
78