Commit 91a5cefa authored by James Morse's avatar James Morse Committed by Will Deacon

arm64: kernel: Add optional CONFIG_ parameter to ALTERNATIVE()

Some uses of ALTERNATIVE() may depend on a feature that is disabled at
compile time by a Kconfig option. In this case the unused alternative
instructions waste space, and if the original instruction is a nop, it
wastes time and space.

This patch adds an optional 'config' option to ALTERNATIVE() and
alternative_insn that allows the compiler to remove both the original
and alternative instructions if the config option is not defined.
Suggested-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Acked-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent 18ffa046
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/kconfig.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/stringify.h> #include <linux/stringify.h>
...@@ -40,7 +41,8 @@ void free_alternatives_memory(void); ...@@ -40,7 +41,8 @@ void free_alternatives_memory(void);
* be fixed in a binutils release posterior to 2.25.51.0.2 (anything * be fixed in a binutils release posterior to 2.25.51.0.2 (anything
* containing commit 4e4d08cf7399b606 or c1baaddf8861). * containing commit 4e4d08cf7399b606 or c1baaddf8861).
*/ */
#define ALTERNATIVE(oldinstr, newinstr, feature) \ #define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \
".if "__stringify(cfg_enabled)" == 1\n" \
"661:\n\t" \ "661:\n\t" \
oldinstr "\n" \ oldinstr "\n" \
"662:\n" \ "662:\n" \
...@@ -53,7 +55,11 @@ void free_alternatives_memory(void); ...@@ -53,7 +55,11 @@ void free_alternatives_memory(void);
"664:\n\t" \ "664:\n\t" \
".popsection\n\t" \ ".popsection\n\t" \
".org . - (664b-663b) + (662b-661b)\n\t" \ ".org . - (664b-663b) + (662b-661b)\n\t" \
".org . - (662b-661b) + (664b-663b)\n" ".org . - (662b-661b) + (664b-663b)\n" \
".endif\n"
#define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \
__ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg))
#else #else
...@@ -65,7 +71,8 @@ void free_alternatives_memory(void); ...@@ -65,7 +71,8 @@ void free_alternatives_memory(void);
.byte \alt_len .byte \alt_len
.endm .endm
.macro alternative_insn insn1 insn2 cap .macro alternative_insn insn1, insn2, cap, enable = 1
.if \enable
661: \insn1 661: \insn1
662: .pushsection .altinstructions, "a" 662: .pushsection .altinstructions, "a"
altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f
...@@ -75,6 +82,7 @@ void free_alternatives_memory(void); ...@@ -75,6 +82,7 @@ void free_alternatives_memory(void);
664: .popsection 664: .popsection
.org . - (664b-663b) + (662b-661b) .org . - (664b-663b) + (662b-661b)
.org . - (662b-661b) + (664b-663b) .org . - (662b-661b) + (664b-663b)
.endif
.endm .endm
/* /*
...@@ -118,6 +126,20 @@ void free_alternatives_memory(void); ...@@ -118,6 +126,20 @@ void free_alternatives_memory(void);
.org . - (662b-661b) + (664b-663b) .org . - (662b-661b) + (664b-663b)
.endm .endm
#define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...) \
alternative_insn insn1, insn2, cap, IS_ENABLED(cfg)
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/*
* Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature));
*
* Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature, CONFIG_FOO));
* N.B. If CONFIG_FOO is specified, but not selected, the whole block
* will be omitted, including oldinstr.
*/
#define ALTERNATIVE(oldinstr, newinstr, ...) \
_ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1)
#endif /* __ASM_ALTERNATIVE_H */ #endif /* __ASM_ALTERNATIVE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment