aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/include/asm/atomic_ll_sc.h1
-rw-r--r--arch/arm64/include/asm/cpufeature.h12
-rw-r--r--arch/arm64/include/asm/kvm_host.h8
-rw-r--r--arch/arm64/kernel/cpufeature.c23
-rw-r--r--arch/arm64/kernel/perf_event.c23
5 files changed, 53 insertions, 14 deletions
diff --git a/arch/arm64/include/asm/atomic_ll_sc.h b/arch/arm64/include/asm/atomic_ll_sc.h
index f819fdcff1ac..f5a2d09afb38 100644
--- a/arch/arm64/include/asm/atomic_ll_sc.h
+++ b/arch/arm64/include/asm/atomic_ll_sc.h
@@ -264,7 +264,6 @@ __LL_SC_PREFIX(__cmpxchg_case_##name(volatile void *ptr, \
264 " st" #rel "xr" #sz "\t%w[tmp], %" #w "[new], %[v]\n" \ 264 " st" #rel "xr" #sz "\t%w[tmp], %" #w "[new], %[v]\n" \
265 " cbnz %w[tmp], 1b\n" \ 265 " cbnz %w[tmp], 1b\n" \
266 " " #mb "\n" \ 266 " " #mb "\n" \
267 " mov %" #w "[oldval], %" #w "[old]\n" \
268 "2:" \ 267 "2:" \
269 : [tmp] "=&r" (tmp), [oldval] "=&r" (oldval), \ 268 : [tmp] "=&r" (tmp), [oldval] "=&r" (oldval), \
270 [v] "+Q" (*(unsigned long *)ptr) \ 269 [v] "+Q" (*(unsigned long *)ptr) \
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index e7f84a7b4465..428ee1f2468c 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -115,6 +115,7 @@ struct arm64_cpu_capabilities {
115 115
116extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); 116extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
117extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS]; 117extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
118extern struct static_key_false arm64_const_caps_ready;
118 119
119bool this_cpu_has_cap(unsigned int cap); 120bool this_cpu_has_cap(unsigned int cap);
120 121
@@ -124,7 +125,7 @@ static inline bool cpu_have_feature(unsigned int num)
124} 125}
125 126
126/* System capability check for constant caps */ 127/* System capability check for constant caps */
127static inline bool cpus_have_const_cap(int num) 128static inline bool __cpus_have_const_cap(int num)
128{ 129{
129 if (num >= ARM64_NCAPS) 130 if (num >= ARM64_NCAPS)
130 return false; 131 return false;
@@ -138,6 +139,14 @@ static inline bool cpus_have_cap(unsigned int num)
138 return test_bit(num, cpu_hwcaps); 139 return test_bit(num, cpu_hwcaps);
139} 140}
140 141
142static inline bool cpus_have_const_cap(int num)
143{
144 if (static_branch_likely(&arm64_const_caps_ready))
145 return __cpus_have_const_cap(num);
146 else
147 return cpus_have_cap(num);
148}
149
141static inline void cpus_set_cap(unsigned int num) 150static inline void cpus_set_cap(unsigned int num)
142{ 151{
143 if (num >= ARM64_NCAPS) { 152 if (num >= ARM64_NCAPS) {
@@ -145,7 +154,6 @@ static inline void cpus_set_cap(unsigned int num)
145 num, ARM64_NCAPS); 154 num, ARM64_NCAPS);
146 } else { 155 } else {
147 __set_bit(num, cpu_hwcaps); 156 __set_bit(num, cpu_hwcaps);
148 static_branch_enable(&cpu_hwcap_keys[num]);
149 } 157 }
150} 158}
151 159
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 5e19165c5fa8..1f252a95bc02 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -24,6 +24,7 @@
24 24
25#include <linux/types.h> 25#include <linux/types.h>
26#include <linux/kvm_types.h> 26#include <linux/kvm_types.h>
27#include <asm/cpufeature.h>
27#include <asm/kvm.h> 28#include <asm/kvm.h>
28#include <asm/kvm_asm.h> 29#include <asm/kvm_asm.h>
29#include <asm/kvm_mmio.h> 30#include <asm/kvm_mmio.h>
@@ -355,9 +356,12 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
355 unsigned long vector_ptr) 356 unsigned long vector_ptr)
356{ 357{
357 /* 358 /*
358 * Call initialization code, and switch to the full blown 359 * Call initialization code, and switch to the full blown HYP code.
359 * HYP code. 360 * If the cpucaps haven't been finalized yet, something has gone very
361 * wrong, and hyp will crash and burn when it uses any
362 * cpus_have_const_cap() wrapper.
360 */ 363 */
364 BUG_ON(!static_branch_likely(&arm64_const_caps_ready));
361 __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr); 365 __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
362} 366}
363 367
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 94b8f7fc3310..817ce3365e20 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -985,8 +985,16 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
985 */ 985 */
986void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) 986void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
987{ 987{
988 for (; caps->matches; caps++) 988 for (; caps->matches; caps++) {
989 if (caps->enable && cpus_have_cap(caps->capability)) 989 unsigned int num = caps->capability;
990
991 if (!cpus_have_cap(num))
992 continue;
993
994 /* Ensure cpus_have_const_cap(num) works */
995 static_branch_enable(&cpu_hwcap_keys[num]);
996
997 if (caps->enable) {
990 /* 998 /*
991 * Use stop_machine() as it schedules the work allowing 999 * Use stop_machine() as it schedules the work allowing
992 * us to modify PSTATE, instead of on_each_cpu() which 1000 * us to modify PSTATE, instead of on_each_cpu() which
@@ -994,6 +1002,8 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
994 * we return. 1002 * we return.
995 */ 1003 */
996 stop_machine(caps->enable, NULL, cpu_online_mask); 1004 stop_machine(caps->enable, NULL, cpu_online_mask);
1005 }
1006 }
997} 1007}
998 1008
999/* 1009/*
@@ -1096,6 +1106,14 @@ static void __init setup_feature_capabilities(void)
1096 enable_cpu_capabilities(arm64_features); 1106 enable_cpu_capabilities(arm64_features);
1097} 1107}
1098 1108
1109DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
1110EXPORT_SYMBOL(arm64_const_caps_ready);
1111
1112static void __init mark_const_caps_ready(void)
1113{
1114 static_branch_enable(&arm64_const_caps_ready);
1115}
1116
1099/* 1117/*
1100 * Check if the current CPU has a given feature capability. 1118 * Check if the current CPU has a given feature capability.
1101 * Should be called from non-preemptible context. 1119 * Should be called from non-preemptible context.
@@ -1131,6 +1149,7 @@ void __init setup_cpu_features(void)
1131 /* Set the CPU feature capabilies */ 1149 /* Set the CPU feature capabilies */
1132 setup_feature_capabilities(); 1150 setup_feature_capabilities();
1133 enable_errata_workarounds(); 1151 enable_errata_workarounds();
1152 mark_const_caps_ready();
1134 setup_elf_hwcaps(arm64_elf_hwcaps); 1153 setup_elf_hwcaps(arm64_elf_hwcaps);
1135 1154
1136 if (system_supports_32bit_el0()) 1155 if (system_supports_32bit_el0())
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index bcc79471b38e..83a1b1ad189f 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -877,15 +877,24 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event,
877 877
878 if (attr->exclude_idle) 878 if (attr->exclude_idle)
879 return -EPERM; 879 return -EPERM;
880 if (is_kernel_in_hyp_mode() && 880
881 attr->exclude_kernel != attr->exclude_hv) 881 /*
882 return -EINVAL; 882 * If we're running in hyp mode, then we *are* the hypervisor.
883 * Therefore we ignore exclude_hv in this configuration, since
884 * there's no hypervisor to sample anyway. This is consistent
885 * with other architectures (x86 and Power).
886 */
887 if (is_kernel_in_hyp_mode()) {
888 if (!attr->exclude_kernel)
889 config_base |= ARMV8_PMU_INCLUDE_EL2;
890 } else {
891 if (attr->exclude_kernel)
892 config_base |= ARMV8_PMU_EXCLUDE_EL1;
893 if (!attr->exclude_hv)
894 config_base |= ARMV8_PMU_INCLUDE_EL2;
895 }
883 if (attr->exclude_user) 896 if (attr->exclude_user)
884 config_base |= ARMV8_PMU_EXCLUDE_EL0; 897 config_base |= ARMV8_PMU_EXCLUDE_EL0;
885 if (!is_kernel_in_hyp_mode() && attr->exclude_kernel)
886 config_base |= ARMV8_PMU_EXCLUDE_EL1;
887 if (!attr->exclude_hv)
888 config_base |= ARMV8_PMU_INCLUDE_EL2;
889 898
890 /* 899 /*
891 * Install the filter into config_base as this is used to 900 * Install the filter into config_base as this is used to