0001
0002 #ifndef __ASM_ALTERNATIVE_MACROS_H
0003 #define __ASM_ALTERNATIVE_MACROS_H
0004
0005 #include <asm/cpucaps.h>
0006 #include <asm/insn-def.h>
0007
0008 #define ARM64_CB_PATCH ARM64_NCAPS
0009
0010 #ifndef __ASSEMBLY__
0011
0012 #include <linux/stringify.h>
0013
0014 #define ALTINSTR_ENTRY(feature) \
0015 " .word 661b - .\n" \
0016 " .word 663f - .\n" \
0017 " .hword " __stringify(feature) "\n" \
0018 " .byte 662b-661b\n" \
0019 " .byte 664f-663f\n"
0020
0021 #define ALTINSTR_ENTRY_CB(feature, cb) \
0022 " .word 661b - .\n" \
0023 " .word " __stringify(cb) "- .\n" \
0024 " .hword " __stringify(feature) "\n" \
0025 " .byte 662b-661b\n" \
0026 " .byte 664f-663f\n"
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 #define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \
0045 ".if "__stringify(cfg_enabled)" == 1\n" \
0046 "661:\n\t" \
0047 oldinstr "\n" \
0048 "662:\n" \
0049 ".pushsection .altinstructions,\"a\"\n" \
0050 ALTINSTR_ENTRY(feature) \
0051 ".popsection\n" \
0052 ".subsection 1\n" \
0053 "663:\n\t" \
0054 newinstr "\n" \
0055 "664:\n\t" \
0056 ".org . - (664b-663b) + (662b-661b)\n\t" \
0057 ".org . - (662b-661b) + (664b-663b)\n\t" \
0058 ".previous\n" \
0059 ".endif\n"
0060
0061 #define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb) \
0062 ".if "__stringify(cfg_enabled)" == 1\n" \
0063 "661:\n\t" \
0064 oldinstr "\n" \
0065 "662:\n" \
0066 ".pushsection .altinstructions,\"a\"\n" \
0067 ALTINSTR_ENTRY_CB(feature, cb) \
0068 ".popsection\n" \
0069 "663:\n\t" \
0070 "664:\n\t" \
0071 ".endif\n"
0072
0073 #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \
0074 __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg))
0075
0076 #define ALTERNATIVE_CB(oldinstr, cb) \
0077 __ALTERNATIVE_CFG_CB(oldinstr, ARM64_CB_PATCH, 1, cb)
0078 #else
0079
0080 #include <asm/assembler.h>
0081
0082 .macro altinstruction_entry orig_offset alt_offset feature orig_len alt_len
0083 .word \orig_offset - .
0084 .word \alt_offset - .
0085 .hword \feature
0086 .byte \orig_len
0087 .byte \alt_len
0088 .endm
0089
0090 .macro alternative_insn insn1, insn2, cap, enable = 1
0091 .if \enable
0092 661: \insn1
0093 662: .pushsection .altinstructions, "a"
0094 altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f
0095 .popsection
0096 .subsection 1
0097 663: \insn2
0098 664: .org . - (664b-663b) + (662b-661b)
0099 .org . - (662b-661b) + (664b-663b)
0100 .previous
0101 .endif
0102 .endm
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 .macro alternative_if_not cap
0127 .set .Lasm_alt_mode, 0
0128 .pushsection .altinstructions, "a"
0129 altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f
0130 .popsection
0131 661:
0132 .endm
0133
0134 .macro alternative_if cap
0135 .set .Lasm_alt_mode, 1
0136 .pushsection .altinstructions, "a"
0137 altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f
0138 .popsection
0139 .subsection 1
0140 .align 2
0141 661:
0142 .endm
0143
0144 .macro alternative_cb cb
0145 .set .Lasm_alt_mode, 0
0146 .pushsection .altinstructions, "a"
0147 altinstruction_entry 661f, \cb, ARM64_CB_PATCH, 662f-661f, 0
0148 .popsection
0149 661:
0150 .endm
0151
0152
0153
0154
0155 .macro alternative_else
0156 662:
0157 .if .Lasm_alt_mode==0
0158 .subsection 1
0159 .else
0160 .previous
0161 .endif
0162 663:
0163 .endm
0164
0165
0166
0167
0168 .macro alternative_endif
0169 664:
0170 .org . - (664b-663b) + (662b-661b)
0171 .org . - (662b-661b) + (664b-663b)
0172 .if .Lasm_alt_mode==0
0173 .previous
0174 .endif
0175 .endm
0176
0177
0178
0179
0180 .macro alternative_cb_end
0181 662:
0182 .endm
0183
0184
0185
0186
0187
0188
0189 .macro alternative_else_nop_endif
0190 alternative_else
0191 nops (662b-661b) / AARCH64_INSN_SIZE
0192 alternative_endif
0193 .endm
0194
0195 #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...) \
0196 alternative_insn insn1, insn2, cap, IS_ENABLED(cfg)
0197
0198 #endif
0199
0200
0201
0202
0203
0204
0205
0206
0207 #define ALTERNATIVE(oldinstr, newinstr, ...) \
0208 _ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1)
0209
0210 #endif