Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: alternatives: Split up alternative.h

asm/alternative.h contains both the macros needed to use alternatives,
as well the type definitions and function prototypes for applying them.

Split the header in two, so that alternatives can be used from core
header files such as linux/compiler.h without the risk of circular
includes

Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>

+222 -209
+217
arch/arm64/include/asm/alternative-macros.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __ASM_ALTERNATIVE_MACROS_H 3 + #define __ASM_ALTERNATIVE_MACROS_H 4 + 5 + #include <asm/cpucaps.h> 6 + 7 + #define ARM64_CB_PATCH ARM64_NCAPS 8 + 9 + /* A64 instructions are always 32 bits. */ 10 + #define AARCH64_INSN_SIZE 4 11 + 12 + #ifndef __ASSEMBLY__ 13 + 14 + #include <linux/stringify.h> 15 + 16 + #define ALTINSTR_ENTRY(feature) \ 17 + " .word 661b - .\n" /* label */ \ 18 + " .word 663f - .\n" /* new instruction */ \ 19 + " .hword " __stringify(feature) "\n" /* feature bit */ \ 20 + " .byte 662b-661b\n" /* source len */ \ 21 + " .byte 664f-663f\n" /* replacement len */ 22 + 23 + #define ALTINSTR_ENTRY_CB(feature, cb) \ 24 + " .word 661b - .\n" /* label */ \ 25 + " .word " __stringify(cb) "- .\n" /* callback */ \ 26 + " .hword " __stringify(feature) "\n" /* feature bit */ \ 27 + " .byte 662b-661b\n" /* source len */ \ 28 + " .byte 664f-663f\n" /* replacement len */ 29 + 30 + /* 31 + * alternative assembly primitive: 32 + * 33 + * If any of these .org directive fail, it means that insn1 and insn2 34 + * don't have the same length. This used to be written as 35 + * 36 + * .if ((664b-663b) != (662b-661b)) 37 + * .error "Alternatives instruction length mismatch" 38 + * .endif 39 + * 40 + * but most assemblers die if insn1 or insn2 have a .inst. This should 41 + * be fixed in a binutils release posterior to 2.25.51.0.2 (anything 42 + * containing commit 4e4d08cf7399b606 or c1baaddf8861). 43 + * 44 + * Alternatives with callbacks do not generate replacement instructions. 45 + */ 46 + #define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \ 47 + ".if "__stringify(cfg_enabled)" == 1\n" \ 48 + "661:\n\t" \ 49 + oldinstr "\n" \ 50 + "662:\n" \ 51 + ".pushsection .altinstructions,\"a\"\n" \ 52 + ALTINSTR_ENTRY(feature) \ 53 + ".popsection\n" \ 54 + ".subsection 1\n" \ 55 + "663:\n\t" \ 56 + newinstr "\n" \ 57 + "664:\n\t" \ 58 + ".org . - (664b-663b) + (662b-661b)\n\t" \ 59 + ".org . - (662b-661b) + (664b-663b)\n\t" \ 60 + ".previous\n" \ 61 + ".endif\n" 62 + 63 + #define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb) \ 64 + ".if "__stringify(cfg_enabled)" == 1\n" \ 65 + "661:\n\t" \ 66 + oldinstr "\n" \ 67 + "662:\n" \ 68 + ".pushsection .altinstructions,\"a\"\n" \ 69 + ALTINSTR_ENTRY_CB(feature, cb) \ 70 + ".popsection\n" \ 71 + "663:\n\t" \ 72 + "664:\n\t" \ 73 + ".endif\n" 74 + 75 + #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \ 76 + __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg)) 77 + 78 + #define ALTERNATIVE_CB(oldinstr, cb) \ 79 + __ALTERNATIVE_CFG_CB(oldinstr, ARM64_CB_PATCH, 1, cb) 80 + #else 81 + 82 + #include <asm/assembler.h> 83 + 84 + .macro altinstruction_entry orig_offset alt_offset feature orig_len alt_len 85 + .word \orig_offset - . 86 + .word \alt_offset - . 87 + .hword \feature 88 + .byte \orig_len 89 + .byte \alt_len 90 + .endm 91 + 92 + .macro alternative_insn insn1, insn2, cap, enable = 1 93 + .if \enable 94 + 661: \insn1 95 + 662: .pushsection .altinstructions, "a" 96 + altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f 97 + .popsection 98 + .subsection 1 99 + 663: \insn2 100 + 664: .previous 101 + .org . - (664b-663b) + (662b-661b) 102 + .org . - (662b-661b) + (664b-663b) 103 + .endif 104 + .endm 105 + 106 + /* 107 + * Alternative sequences 108 + * 109 + * The code for the case where the capability is not present will be 110 + * assembled and linked as normal. There are no restrictions on this 111 + * code. 112 + * 113 + * The code for the case where the capability is present will be 114 + * assembled into a special section to be used for dynamic patching. 115 + * Code for that case must: 116 + * 117 + * 1. Be exactly the same length (in bytes) as the default code 118 + * sequence. 119 + * 120 + * 2. Not contain a branch target that is used outside of the 121 + * alternative sequence it is defined in (branches into an 122 + * alternative sequence are not fixed up). 123 + */ 124 + 125 + /* 126 + * Begin an alternative code sequence. 127 + */ 128 + .macro alternative_if_not cap 129 + .set .Lasm_alt_mode, 0 130 + .pushsection .altinstructions, "a" 131 + altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f 132 + .popsection 133 + 661: 134 + .endm 135 + 136 + .macro alternative_if cap 137 + .set .Lasm_alt_mode, 1 138 + .pushsection .altinstructions, "a" 139 + altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f 140 + .popsection 141 + .subsection 1 142 + .align 2 /* So GAS knows label 661 is suitably aligned */ 143 + 661: 144 + .endm 145 + 146 + .macro alternative_cb cb 147 + .set .Lasm_alt_mode, 0 148 + .pushsection .altinstructions, "a" 149 + altinstruction_entry 661f, \cb, ARM64_CB_PATCH, 662f-661f, 0 150 + .popsection 151 + 661: 152 + .endm 153 + 154 + /* 155 + * Provide the other half of the alternative code sequence. 156 + */ 157 + .macro alternative_else 158 + 662: 159 + .if .Lasm_alt_mode==0 160 + .subsection 1 161 + .else 162 + .previous 163 + .endif 164 + 663: 165 + .endm 166 + 167 + /* 168 + * Complete an alternative code sequence. 169 + */ 170 + .macro alternative_endif 171 + 664: 172 + .if .Lasm_alt_mode==0 173 + .previous 174 + .endif 175 + .org . - (664b-663b) + (662b-661b) 176 + .org . - (662b-661b) + (664b-663b) 177 + .endm 178 + 179 + /* 180 + * Callback-based alternative epilogue 181 + */ 182 + .macro alternative_cb_end 183 + 662: 184 + .endm 185 + 186 + /* 187 + * Provides a trivial alternative or default sequence consisting solely 188 + * of NOPs. The number of NOPs is chosen automatically to match the 189 + * previous case. 190 + */ 191 + .macro alternative_else_nop_endif 192 + alternative_else 193 + nops (662b-661b) / AARCH64_INSN_SIZE 194 + alternative_endif 195 + .endm 196 + 197 + #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...) \ 198 + alternative_insn insn1, insn2, cap, IS_ENABLED(cfg) 199 + 200 + .macro user_alt, label, oldinstr, newinstr, cond 201 + 9999: alternative_insn "\oldinstr", "\newinstr", \cond 202 + _asm_extable 9999b, \label 203 + .endm 204 + 205 + #endif /* __ASSEMBLY__ */ 206 + 207 + /* 208 + * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature)); 209 + * 210 + * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature, CONFIG_FOO)); 211 + * N.B. If CONFIG_FOO is specified, but not selected, the whole block 212 + * will be omitted, including oldinstr. 213 + */ 214 + #define ALTERNATIVE(oldinstr, newinstr, ...) \ 215 + _ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1) 216 + 217 + #endif /* __ASM_ALTERNATIVE_MACROS_H */
+2 -206
arch/arm64/include/asm/alternative.h
··· 2 2 #ifndef __ASM_ALTERNATIVE_H 3 3 #define __ASM_ALTERNATIVE_H 4 4 5 - #include <asm/cpucaps.h> 6 - #include <asm/insn.h> 7 - 8 - #define ARM64_CB_PATCH ARM64_NCAPS 5 + #include <asm/alternative-macros.h> 9 6 10 7 #ifndef __ASSEMBLY__ 11 8 12 9 #include <linux/init.h> 13 10 #include <linux/types.h> 14 11 #include <linux/stddef.h> 15 - #include <linux/stringify.h> 16 12 17 13 struct alt_instr { 18 14 s32 orig_offset; /* offset to original instruction */ ··· 31 35 static inline void apply_alternatives_module(void *start, size_t length) { } 32 36 #endif 33 37 34 - #define ALTINSTR_ENTRY(feature) \ 35 - " .word 661b - .\n" /* label */ \ 36 - " .word 663f - .\n" /* new instruction */ \ 37 - " .hword " __stringify(feature) "\n" /* feature bit */ \ 38 - " .byte 662b-661b\n" /* source len */ \ 39 - " .byte 664f-663f\n" /* replacement len */ 40 - 41 - #define ALTINSTR_ENTRY_CB(feature, cb) \ 42 - " .word 661b - .\n" /* label */ \ 43 - " .word " __stringify(cb) "- .\n" /* callback */ \ 44 - " .hword " __stringify(feature) "\n" /* feature bit */ \ 45 - " .byte 662b-661b\n" /* source len */ \ 46 - " .byte 664f-663f\n" /* replacement len */ 47 - 48 - /* 49 - * alternative assembly primitive: 50 - * 51 - * If any of these .org directive fail, it means that insn1 and insn2 52 - * don't have the same length. This used to be written as 53 - * 54 - * .if ((664b-663b) != (662b-661b)) 55 - * .error "Alternatives instruction length mismatch" 56 - * .endif 57 - * 58 - * but most assemblers die if insn1 or insn2 have a .inst. This should 59 - * be fixed in a binutils release posterior to 2.25.51.0.2 (anything 60 - * containing commit 4e4d08cf7399b606 or c1baaddf8861). 61 - * 62 - * Alternatives with callbacks do not generate replacement instructions. 63 - */ 64 - #define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \ 65 - ".if "__stringify(cfg_enabled)" == 1\n" \ 66 - "661:\n\t" \ 67 - oldinstr "\n" \ 68 - "662:\n" \ 69 - ".pushsection .altinstructions,\"a\"\n" \ 70 - ALTINSTR_ENTRY(feature) \ 71 - ".popsection\n" \ 72 - ".subsection 1\n" \ 73 - "663:\n\t" \ 74 - newinstr "\n" \ 75 - "664:\n\t" \ 76 - ".org . - (664b-663b) + (662b-661b)\n\t" \ 77 - ".org . - (662b-661b) + (664b-663b)\n\t" \ 78 - ".previous\n" \ 79 - ".endif\n" 80 - 81 - #define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb) \ 82 - ".if "__stringify(cfg_enabled)" == 1\n" \ 83 - "661:\n\t" \ 84 - oldinstr "\n" \ 85 - "662:\n" \ 86 - ".pushsection .altinstructions,\"a\"\n" \ 87 - ALTINSTR_ENTRY_CB(feature, cb) \ 88 - ".popsection\n" \ 89 - "663:\n\t" \ 90 - "664:\n\t" \ 91 - ".endif\n" 92 - 93 - #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \ 94 - __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg)) 95 - 96 - #define ALTERNATIVE_CB(oldinstr, cb) \ 97 - __ALTERNATIVE_CFG_CB(oldinstr, ARM64_CB_PATCH, 1, cb) 98 - #else 99 - 100 - #include <asm/assembler.h> 101 - 102 - .macro altinstruction_entry orig_offset alt_offset feature orig_len alt_len 103 - .word \orig_offset - . 104 - .word \alt_offset - . 105 - .hword \feature 106 - .byte \orig_len 107 - .byte \alt_len 108 - .endm 109 - 110 - .macro alternative_insn insn1, insn2, cap, enable = 1 111 - .if \enable 112 - 661: \insn1 113 - 662: .pushsection .altinstructions, "a" 114 - altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f 115 - .popsection 116 - .subsection 1 117 - 663: \insn2 118 - 664: .previous 119 - .org . - (664b-663b) + (662b-661b) 120 - .org . - (662b-661b) + (664b-663b) 121 - .endif 122 - .endm 123 - 124 - /* 125 - * Alternative sequences 126 - * 127 - * The code for the case where the capability is not present will be 128 - * assembled and linked as normal. There are no restrictions on this 129 - * code. 130 - * 131 - * The code for the case where the capability is present will be 132 - * assembled into a special section to be used for dynamic patching. 133 - * Code for that case must: 134 - * 135 - * 1. Be exactly the same length (in bytes) as the default code 136 - * sequence. 137 - * 138 - * 2. Not contain a branch target that is used outside of the 139 - * alternative sequence it is defined in (branches into an 140 - * alternative sequence are not fixed up). 141 - */ 142 - 143 - /* 144 - * Begin an alternative code sequence. 145 - */ 146 - .macro alternative_if_not cap 147 - .set .Lasm_alt_mode, 0 148 - .pushsection .altinstructions, "a" 149 - altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f 150 - .popsection 151 - 661: 152 - .endm 153 - 154 - .macro alternative_if cap 155 - .set .Lasm_alt_mode, 1 156 - .pushsection .altinstructions, "a" 157 - altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f 158 - .popsection 159 - .subsection 1 160 - .align 2 /* So GAS knows label 661 is suitably aligned */ 161 - 661: 162 - .endm 163 - 164 - .macro alternative_cb cb 165 - .set .Lasm_alt_mode, 0 166 - .pushsection .altinstructions, "a" 167 - altinstruction_entry 661f, \cb, ARM64_CB_PATCH, 662f-661f, 0 168 - .popsection 169 - 661: 170 - .endm 171 - 172 - /* 173 - * Provide the other half of the alternative code sequence. 174 - */ 175 - .macro alternative_else 176 - 662: 177 - .if .Lasm_alt_mode==0 178 - .subsection 1 179 - .else 180 - .previous 181 - .endif 182 - 663: 183 - .endm 184 - 185 - /* 186 - * Complete an alternative code sequence. 187 - */ 188 - .macro alternative_endif 189 - 664: 190 - .if .Lasm_alt_mode==0 191 - .previous 192 - .endif 193 - .org . - (664b-663b) + (662b-661b) 194 - .org . - (662b-661b) + (664b-663b) 195 - .endm 196 - 197 - /* 198 - * Callback-based alternative epilogue 199 - */ 200 - .macro alternative_cb_end 201 - 662: 202 - .endm 203 - 204 - /* 205 - * Provides a trivial alternative or default sequence consisting solely 206 - * of NOPs. The number of NOPs is chosen automatically to match the 207 - * previous case. 208 - */ 209 - .macro alternative_else_nop_endif 210 - alternative_else 211 - nops (662b-661b) / AARCH64_INSN_SIZE 212 - alternative_endif 213 - .endm 214 - 215 - #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...) \ 216 - alternative_insn insn1, insn2, cap, IS_ENABLED(cfg) 217 - 218 - .macro user_alt, label, oldinstr, newinstr, cond 219 - 9999: alternative_insn "\oldinstr", "\newinstr", \cond 220 - _asm_extable 9999b, \label 221 - .endm 222 - 223 - #endif /* __ASSEMBLY__ */ 224 - 225 - /* 226 - * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature)); 227 - * 228 - * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature, CONFIG_FOO)); 229 - * N.B. If CONFIG_FOO is specified, but not selected, the whole block 230 - * will be omitted, including oldinstr. 231 - */ 232 - #define ALTERNATIVE(oldinstr, newinstr, ...) \ 233 - _ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1) 234 - 38 + #endif /* __ASSEMBLY__ */ 235 39 #endif /* __ASM_ALTERNATIVE_H */
+1 -1
arch/arm64/include/asm/asm-uaccess.h
··· 2 2 #ifndef __ASM_ASM_UACCESS_H 3 3 #define __ASM_ASM_UACCESS_H 4 4 5 - #include <asm/alternative.h> 5 + #include <asm/alternative-macros.h> 6 6 #include <asm/kernel-pgtable.h> 7 7 #include <asm/mmu.h> 8 8 #include <asm/sysreg.h>
+1 -2
arch/arm64/include/asm/insn.h
··· 10 10 #include <linux/build_bug.h> 11 11 #include <linux/types.h> 12 12 13 - /* A64 instructions are always 32 bits. */ 14 - #define AARCH64_INSN_SIZE 4 13 + #include <asm/alternative.h> 15 14 16 15 #ifndef __ASSEMBLY__ 17 16 /*
+1
arch/arm64/kernel/proton-pack.c
··· 24 24 #include <linux/prctl.h> 25 25 #include <linux/sched/task_stack.h> 26 26 27 + #include <asm/insn.h> 27 28 #include <asm/spectre.h> 28 29 #include <asm/traps.h> 29 30