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 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 */ 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