diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-19 16:34:34 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-19 16:34:34 -0400 |
| commit | 2fe296a61a4e2ec11efc41cb8d645c52e0113f55 (patch) | |
| tree | 5632d414c32055b225dabb14044923b9f195f69c | |
| parent | e5a489abcfd216d07ad6b33ea0d191e61d0f25ea (diff) | |
| parent | 63a1e1c95e60e798fa09ab3c536fb555aa5bbf2b (diff) | |
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
| -rw-r--r-- | arch/arm64/include/asm/atomic_ll_sc.h | 1 | ||||
| -rw-r--r-- | arch/arm64/include/asm/cpufeature.h | 12 | ||||
| -rw-r--r-- | arch/arm64/include/asm/kvm_host.h | 8 | ||||
| -rw-r--r-- | arch/arm64/kernel/cpufeature.c | 23 | ||||
| -rw-r--r-- | arch/arm64/kernel/perf_event.c | 23 |
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 | ||
| 116 | extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); | 116 | extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); |
| 117 | extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS]; | 117 | extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS]; |
| 118 | extern struct static_key_false arm64_const_caps_ready; | ||
| 118 | 119 | ||
| 119 | bool this_cpu_has_cap(unsigned int cap); | 120 | bool 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 */ |
| 127 | static inline bool cpus_have_const_cap(int num) | 128 | static 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 | ||
| 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 | |||
| 141 | static inline void cpus_set_cap(unsigned int num) | 150 | static 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 | */ |
| 986 | void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) | 986 | void __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 | ||
| 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 | |||
| 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 |
