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>
This commit is contained in:

committed by
Michael Ellerman

parent
bfbfc8a43c
commit
4db7327194
@@ -15,6 +15,7 @@
|
||||
#include <linux/threads.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/jump_label.h>
|
||||
|
||||
#include <asm/oprofile_impl.h>
|
||||
#include <asm/cputable.h>
|
||||
@@ -2224,3 +2225,22 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
|
||||
struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS] = {
|
||||
[0 ... NUM_CPU_FTR_KEYS - 1] = STATIC_KEY_TRUE_INIT
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cpu_feature_keys);
|
||||
|
||||
void __init cpu_feature_keys_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_CPU_FTR_KEYS; i++) {
|
||||
unsigned long f = 1ul << i;
|
||||
|
||||
if (!(cur_cpu_spec->cpu_features & f))
|
||||
static_branch_disable(&cpu_feature_keys[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user