Skip to content

Commit 4db7327

Browse files
haokexinmpe
authored andcommitted
powerpc: Add option to use jump label for cpu_has_feature()
We do binary patching of asm code using CPU features, which is a one-time operation, done during early boot. However checks of CPU features in C code are currently done at run time, even though the set of CPU features can never change after boot. We can optimise this by using jump labels to implement cpu_has_feature(), meaning checks in C code are binary patched into a single nop or branch. For a C sequence along the lines of: if (cpu_has_feature(FOO)) return 2; The generated code before is roughly: ld r9,-27640(r2) ld r9,0(r9) lwz r9,32(r9) cmpwi cr7,r9,0 bge cr7, 1f li r3,2 blr 1: ... After (true): nop li r3,2 blr After (false): b 1f li r3,2 blr 1: ... mpe: Rename MAX_CPU_FEATURES as we already have a #define with that name, and define it simply as a constant, rather than doing tricks with sizeof and NULL pointers. Rename the array to cpu_feature_keys. Use the kconfig we added to guard it. Add BUILD_BUG_ON() if the feature is not a compile time constant. Rewrite the change log. Signed-off-by: Kevin Hao <haokexin@gmail.com> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
1 parent bfbfc8a commit 4db7327

File tree

5 files changed

+52
-0
lines changed

5 files changed

+52
-0
lines changed

arch/powerpc/include/asm/cpu_has_feature.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,34 @@ static inline bool early_cpu_has_feature(unsigned long feature)
1111
(CPU_FTRS_POSSIBLE & cur_cpu_spec->cpu_features & feature));
1212
}
1313

14+
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
15+
#include <linux/jump_label.h>
16+
17+
#define NUM_CPU_FTR_KEYS 64
18+
19+
extern struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS];
20+
21+
static __always_inline bool cpu_has_feature(unsigned long feature)
22+
{
23+
int i;
24+
25+
BUILD_BUG_ON(!__builtin_constant_p(feature));
26+
27+
if (CPU_FTRS_ALWAYS & feature)
28+
return true;
29+
30+
if (!(CPU_FTRS_POSSIBLE & feature))
31+
return false;
32+
33+
i = __builtin_ctzl(feature);
34+
return static_branch_likely(&cpu_feature_keys[i]);
35+
}
36+
#else
1437
static inline bool cpu_has_feature(unsigned long feature)
1538
{
1639
return early_cpu_has_feature(feature);
1740
}
41+
#endif
1842

1943
#endif /* __ASSEMBLY__ */
2044
#endif /* __ASM_POWERPC_CPUFEATURE_H */

arch/powerpc/include/asm/cputable.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
123123

124124
extern const char *powerpc_base_platform;
125125

126+
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
127+
extern void cpu_feature_keys_init(void);
128+
#else
129+
static inline void cpu_feature_keys_init(void) { }
130+
#endif
131+
126132
/* TLB flush actions. Used as argument to cpu_spec.flush_tlb() hook */
127133
enum {
128134
TLB_INVAL_SCOPE_GLOBAL = 0, /* invalidate all TLBs */

arch/powerpc/include/asm/mmu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
#define MMU_FTRS_PA6T MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \
113113
MMU_FTR_CI_LARGE_PAGE | MMU_FTR_NO_SLBIE_B
114114
#ifndef __ASSEMBLY__
115+
#include <linux/bug.h>
115116
#include <asm/cputable.h>
116117

117118
#ifdef CONFIG_PPC_FSL_BOOK3E

arch/powerpc/kernel/cputable.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/threads.h>
1616
#include <linux/init.h>
1717
#include <linux/export.h>
18+
#include <linux/jump_label.h>
1819

1920
#include <asm/oprofile_impl.h>
2021
#include <asm/cputable.h>
@@ -2224,3 +2225,22 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
22242225

22252226
return NULL;
22262227
}
2228+
2229+
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
2230+
struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS] = {
2231+
[0 ... NUM_CPU_FTR_KEYS - 1] = STATIC_KEY_TRUE_INIT
2232+
};
2233+
EXPORT_SYMBOL_GPL(cpu_feature_keys);
2234+
2235+
void __init cpu_feature_keys_init(void)
2236+
{
2237+
int i;
2238+
2239+
for (i = 0; i < NUM_CPU_FTR_KEYS; i++) {
2240+
unsigned long f = 1ul << i;
2241+
2242+
if (!(cur_cpu_spec->cpu_features & f))
2243+
static_branch_disable(&cpu_feature_keys[i]);
2244+
}
2245+
}
2246+
#endif

arch/powerpc/lib/feature-fixups.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ void __init apply_feature_fixups(void)
195195
* CPU/MMU features.
196196
*/
197197
jump_label_init();
198+
cpu_feature_keys_init();
198199
}
199200

200201
static int __init check_features(void)

0 commit comments

Comments
 (0)