cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

alternative-macros.h (5537B)


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