File Index
Files and directories
Sign in
FILE

alternative-macros.h

File preview with syntax highlighting.

linux-6.19.14/arch/riscv/include/asm/alternative-macros.h C
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#ifndef __ASM_ALTERNATIVE_MACROS_H
  3#define __ASM_ALTERNATIVE_MACROS_H
  4
  5#ifdef CONFIG_RISCV_ALTERNATIVE
  6
  7#ifdef __ASSEMBLER__
  8
  9.macro ALT_ENTRY oldptr newptr vendor_id patch_id new_len
 10	.4byte \oldptr - .
 11	.4byte \newptr - .
 12	.2byte \vendor_id
 13	.2byte \new_len
 14	.4byte \patch_id
 15.endm
 16
 17.macro ALT_NEW_CONTENT vendor_id, patch_id, enable = 1, new_c
 18	.if \enable
 19	.pushsection .alternative, "a"
 20	ALT_ENTRY 886b, 888f, \vendor_id, \patch_id, 889f - 888f
 21	.popsection
 22	.subsection 1
 23888 :
 24	.option push
 25	.option norvc
 26	.option norelax
 27	\new_c
 28	.option pop
 29889 :
 30	.org    . - (889b - 888b) + (887b - 886b)
 31	.org    . - (887b - 886b) + (889b - 888b)
 32	.previous
 33	.endif
 34.endm
 35
 36.macro ALTERNATIVE_CFG old_c, new_c, vendor_id, patch_id, enable
 37886 :
 38	.option push
 39	.option norvc
 40	.option norelax
 41	\old_c
 42	.option pop
 43887 :
 44	ALT_NEW_CONTENT \vendor_id, \patch_id, \enable, "\new_c"
 45.endm
 46
 47.macro ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, patch_id_1, enable_1,	\
 48				new_c_2, vendor_id_2, patch_id_2, enable_2
 49	ALTERNATIVE_CFG "\old_c", "\new_c_1", \vendor_id_1, \patch_id_1, \enable_1
 50	ALT_NEW_CONTENT \vendor_id_2, \patch_id_2, \enable_2, "\new_c_2"
 51.endm
 52
 53#define __ALTERNATIVE_CFG(...)		ALTERNATIVE_CFG __VA_ARGS__
 54#define __ALTERNATIVE_CFG_2(...)	ALTERNATIVE_CFG_2 __VA_ARGS__
 55
 56#else /* !__ASSEMBLER__ */
 57
 58#include <asm/asm.h>
 59#include <linux/stringify.h>
 60
 61#define ALT_ENTRY(oldptr, newptr, vendor_id, patch_id, newlen)		\
 62	".4byte	((" oldptr ") - .) \n"					\
 63	".4byte	((" newptr ") - .) \n"					\
 64	".2byte	" vendor_id "\n"					\
 65	".2byte " newlen "\n"						\
 66	".4byte	" patch_id "\n"
 67
 68#define ALT_NEW_CONTENT(vendor_id, patch_id, enable, new_c)		\
 69	".if " __stringify(enable) " == 1\n"				\
 70	".pushsection .alternative, \"a\"\n"				\
 71	ALT_ENTRY("886b", "888f", __stringify(vendor_id), __stringify(patch_id), "889f - 888f") \
 72	".popsection\n"							\
 73	".subsection 1\n"						\
 74	"888 :\n"							\
 75	".option push\n"						\
 76	".option norvc\n"						\
 77	".option norelax\n"						\
 78	new_c "\n"							\
 79	".option pop\n"							\
 80	"889 :\n"							\
 81	".org	. - (887b - 886b) + (889b - 888b)\n"			\
 82	".org	. - (889b - 888b) + (887b - 886b)\n"			\
 83	".previous\n"							\
 84	".endif\n"
 85
 86#define __ALTERNATIVE_CFG(old_c, new_c, vendor_id, patch_id, enable)	\
 87	"886 :\n"							\
 88	".option push\n"						\
 89	".option norvc\n"						\
 90	".option norelax\n"						\
 91	old_c "\n"							\
 92	".option pop\n"							\
 93	"887 :\n"							\
 94	ALT_NEW_CONTENT(vendor_id, patch_id, enable, new_c)
 95
 96#define __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, patch_id_1, enable_1,	\
 97				   new_c_2, vendor_id_2, patch_id_2, enable_2)	\
 98	__ALTERNATIVE_CFG(old_c, new_c_1, vendor_id_1, patch_id_1, enable_1)	\
 99	ALT_NEW_CONTENT(vendor_id_2, patch_id_2, enable_2, new_c_2)
100
101#endif /* __ASSEMBLER__ */
102
103#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, patch_id, CONFIG_k)	\
104	__ALTERNATIVE_CFG(old_c, new_c, vendor_id, patch_id, IS_ENABLED(CONFIG_k))
105
106#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, patch_id_1, CONFIG_k_1,		\
107				  new_c_2, vendor_id_2, patch_id_2, CONFIG_k_2)		\
108	__ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, patch_id_1, IS_ENABLED(CONFIG_k_1),	\
109				   new_c_2, vendor_id_2, patch_id_2, IS_ENABLED(CONFIG_k_2))
110
111#else /* CONFIG_RISCV_ALTERNATIVE */
112#ifdef __ASSEMBLER__
113
114.macro ALTERNATIVE_CFG old_c
115	\old_c
116.endm
117
118#define __ALTERNATIVE_CFG(old_c, ...)		ALTERNATIVE_CFG old_c
119#define __ALTERNATIVE_CFG_2(old_c, ...)		ALTERNATIVE_CFG old_c
120
121#else /* !__ASSEMBLER__ */
122
123#define __ALTERNATIVE_CFG(old_c, ...)		old_c "\n"
124#define __ALTERNATIVE_CFG_2(old_c, ...)		old_c "\n"
125
126#endif /* __ASSEMBLER__ */
127
128#define _ALTERNATIVE_CFG(old_c, ...)		__ALTERNATIVE_CFG(old_c)
129#define _ALTERNATIVE_CFG_2(old_c, ...)		__ALTERNATIVE_CFG_2(old_c)
130
131#endif /* CONFIG_RISCV_ALTERNATIVE */
132
133/*
134 * Usage:
135 *   ALTERNATIVE(old_content, new_content, vendor_id, patch_id, CONFIG_k)
136 * in the assembly code. Otherwise,
137 *   asm(ALTERNATIVE(old_content, new_content, vendor_id, patch_id, CONFIG_k));
138 *
139 * old_content: The old content which is probably replaced with new content.
140 * new_content: The new content.
141 * vendor_id: The CPU vendor ID.
142 * patch_id: The patch ID (erratum ID or cpufeature ID).
143 * CONFIG_k: The Kconfig of this patch ID. When Kconfig is disabled, the old
144 *	     content will always be executed.
145 */
146#define ALTERNATIVE(old_content, new_content, vendor_id, patch_id, CONFIG_k) \
147	_ALTERNATIVE_CFG(old_content, new_content, vendor_id, patch_id, CONFIG_k)
148
149/*
150 * A vendor wants to replace an old_content, but another vendor has used
151 * ALTERNATIVE() to patch its customized content at the same location. In
152 * this case, this vendor can create a new macro ALTERNATIVE_2() based
153 * on the following sample code and then replace ALTERNATIVE() with
154 * ALTERNATIVE_2() to append its customized content.
155 */
156#define ALTERNATIVE_2(old_content, new_content_1, vendor_id_1, patch_id_1, CONFIG_k_1,		\
157				   new_content_2, vendor_id_2, patch_id_2, CONFIG_k_2)		\
158	_ALTERNATIVE_CFG_2(old_content, new_content_1, vendor_id_1, patch_id_1, CONFIG_k_1,	\
159					new_content_2, vendor_id_2, patch_id_2, CONFIG_k_2)
160
161#endif
~/ Read-only file preview.