History

Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull arm64 fixes/cleanups from Catalin Marinas: - Avoid taking a mutex in the secondary CPU bring-up path when interrupts are disabled - Ignore perf exclude_hv when the kernel is running in Hyp mode - Remove redundant instruction in cmpxchg * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64/cpufeature: don't use mutex in bringup path arm64: perf: Ignore exclude_hv when kernel is running in HYP arm64: Remove redundant mov from LL/SC cmpxchg

Linus Torvalds committed 9 years ago

Commit 2fe296a2 parents e5a489a 63a1e1c5 files · +53 −14Browse files

Unified · Split

5 files
  1. arch/arm64/include/asm/atomic_ll_sc.h +0 −1
  2. arch/arm64/include/asm/cpufeature.h +10 −2
  3. arch/arm64/include/asm/kvm_host.h +6 −2
  4. arch/arm64/kernel/cpufeature.c +21 −2
  5. arch/arm64/kernel/perf_event.c +16 −7
arch/arm64/include/asm/atomic_ll_sc.h+0−1
@@ -264,7 +264,6 @@ __LL_SC_PREFIX(__cmpxchg_case_##name(volatile void *ptr, \ · 263 unmodified lines
264264 " st" #rel "xr" #sz "\t%w[tmp], %" #w "[new], %[v]\n" \
265265 " cbnz %w[tmp], 1b\n" \
266266 " " #mb "\n" \
267− " mov %" #w "[oldval], %" #w "[old]\n" \
268267 "2:" \
269268 : [tmp] "=&r" (tmp), [oldval] "=&r" (oldval), \
270269 [v] "+Q" (*(unsigned long *)ptr) \
arch/arm64/include/asm/cpufeature.h+10−2
@@ -115,6 +115,7 @@ struct arm64_cpu_capabilities { · 114 unmodified lines
115115
116116 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
117117 extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
118+extern struct static_key_false arm64_const_caps_ready;
118119
119120 bool this_cpu_has_cap(unsigned int cap);
120121
@@ -124,7 +125,7 @@ static inline bool cpu_have_feature(unsigned int num) · 3 unmodified lines
124125 }
125126
126127 /* System capability check for constant caps */
127−static inline bool cpus_have_const_cap(int num)
128+static inline bool __cpus_have_const_cap(int num)
128129 {
129130 if (num >= ARM64_NCAPS)
130131 return false;
@@ -138,6 +139,14 @@ static inline bool cpus_have_cap(unsigned int num) · 7 unmodified lines
138139 return test_bit(num, cpu_hwcaps);
139140 }
140141
142+static 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+
141150 static inline void cpus_set_cap(unsigned int num)
142151 {
143152 if (num >= ARM64_NCAPS) {
@@ -145,7 +154,6 @@ static inline void cpus_set_cap(unsigned int num) · 1 unmodified line
145154 num, ARM64_NCAPS);
146155 } else {
147156 __set_bit(num, cpu_hwcaps);
148− static_branch_enable(&cpu_hwcap_keys[num]);
149157 }
150158 }
151159
arch/arm64/include/asm/kvm_host.h+6−2
@@ -24,6 +24,7 @@ · 23 unmodified lines
2424
2525 #include <linux/types.h>
2626 #include <linux/kvm_types.h>
27+#include <asm/cpufeature.h>
2728 #include <asm/kvm.h>
2829 #include <asm/kvm_asm.h>
2930 #include <asm/kvm_mmio.h>
@@ -355,9 +356,12 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr, · 325 unmodified lines
355356 unsigned long vector_ptr)
356357 {
357358 /*
358− * Call initialization code, and switch to the full blown
359− * HYP code.
359+ * Call initialization code, and switch to the full blown 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.
360363 */
364+ BUG_ON(!static_branch_likely(&arm64_const_caps_ready));
361365 __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
362366 }
363367
arch/arm64/kernel/cpufeature.c+21−2
@@ -985,8 +985,16 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, · 984 unmodified lines
985985 */
986986 void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
987987 {
988− for (; caps->matches; caps++)
989− if (caps->enable && cpus_have_cap(caps->capability))
988+ for (; caps->matches; caps++) {
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) {
990998 /*
991999 * Use stop_machine() as it schedules the work allowing
9921000 * 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) · 1 unmodified line
9941002 * we return.
9951003 */
9961004 stop_machine(caps->enable, NULL, cpu_online_mask);
1005+ }
1006+ }
9971007 }
9981008
9991009 /*
@@ -1096,6 +1106,14 @@ static void __init setup_feature_capabilities(void) · 96 unmodified lines
10961106 enable_cpu_capabilities(arm64_features);
10971107 }
10981108
1109+DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
1110+EXPORT_SYMBOL(arm64_const_caps_ready);
1111+
1112+static void __init mark_const_caps_ready(void)
1113+{
1114+ static_branch_enable(&arm64_const_caps_ready);
1115+}
1116+
10991117 /*
11001118 * Check if the current CPU has a given feature capability.
11011119 * Should be called from non-preemptible context.
@@ -1131,6 +1149,7 @@ void __init setup_cpu_features(void) · 29 unmodified lines
11311149 /* Set the CPU feature capabilies */
11321150 setup_feature_capabilities();
11331151 enable_errata_workarounds();
1152+ mark_const_caps_ready();
11341153 setup_elf_hwcaps(arm64_elf_hwcaps);
11351154
11361155 if (system_supports_32bit_el0())
arch/arm64/kernel/perf_event.c+16−7
@@ -877,15 +877,24 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event, · 876 unmodified lines
877877
878878 if (attr->exclude_idle)
879879 return -EPERM;
880− if (is_kernel_in_hyp_mode() &&
881− attr->exclude_kernel != attr->exclude_hv)
882− return -EINVAL;
880+
881+ /*
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+ }
883896 if (attr->exclude_user)
884897 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;
889898
890899 /*
891900 * Install the filter into config_base as this is used to