Pull arm64 fixes from Will Deacon: - Fix kexec and hibernation when using 5-level page-table configuration - Remove references to non-existent SF8MM4 and SF8MM8 ID register fields, hooking up hwcaps for the FPRCVT, F8MM4 and F8MM8 fields instead - Drop unused .ARM.attributes ELF sections - Fix array indexing when probing CPU cache topology from firmware - Fix potential use-after-free in AMU initialisation code - Work around broken GTDT entries by tolerating excessively large timer arrays - Force use of Rust's "softfloat" target to avoid a threatening warning about the NEON target feature - Typo fix in GCS documentation and removal of duplicate Kconfig select * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: rust: clean Rust 1.85.0 warning using softfloat target arm64: Add missing registrations of hwcaps ACPI: GTDT: Relax sanity checking on Platform Timers array count arm64: amu: Delay allocating cpumask for AMU FIE support arm64: cacheinfo: Avoid out-of-bounds write to cacheinfo array arm64: Handle .ARM.attributes section in linker scripts arm64/hwcap: Remove stray references to SF8MMx arm64/gcs: Fix documentation for HWCAP arm64: Kconfig: Remove selecting replaced HAVE_FUNCTION_GRAPH_RETVAL arm64: Fix 5-level paging support in kexec/hibernate trampoline
Unified · Split
| @@ -37,7 +37,7 @@ intended to be exhaustive. · 36 unmodified lines | |||
| 37 | shadow stacks rather than GCS. | 37 | shadow stacks rather than GCS. |
| 38 | 38 | ||
| 39 | * Support for GCS is reported to userspace via HWCAP_GCS in the aux vector | 39 | * Support for GCS is reported to userspace via HWCAP_GCS in the aux vector |
| 40 | AT_HWCAP2 entry. | 40 | AT_HWCAP entry. |
| 41 | 41 | ||
| 42 | * GCS is enabled per thread. While there is support for disabling GCS | 42 | * GCS is enabled per thread. While there is support for disabling GCS |
| 43 | at runtime this should be done with great care. | 43 | at runtime this should be done with great care. |
| @@ -225,7 +225,6 @@ config ARM64 · 224 unmodified lines | |||
| 225 | select HAVE_FUNCTION_ERROR_INJECTION | 225 | select HAVE_FUNCTION_ERROR_INJECTION |
| 226 | select HAVE_FUNCTION_GRAPH_FREGS | 226 | select HAVE_FUNCTION_GRAPH_FREGS |
| 227 | select HAVE_FUNCTION_GRAPH_TRACER | 227 | select HAVE_FUNCTION_GRAPH_TRACER |
| 228 | select HAVE_FUNCTION_GRAPH_RETVAL | ||
| 229 | select HAVE_GCC_PLUGINS | 228 | select HAVE_GCC_PLUGINS |
| 230 | select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \ | 229 | select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \ |
| 231 | HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI | 230 | HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI |
| @@ -48,7 +48,11 @@ KBUILD_CFLAGS += $(CC_FLAGS_NO_FPU) \ · 47 unmodified lines | |||
| 48 | KBUILD_CFLAGS += $(call cc-disable-warning, psabi) | 48 | KBUILD_CFLAGS += $(call cc-disable-warning, psabi) |
| 49 | KBUILD_AFLAGS += $(compat_vdso) | 49 | KBUILD_AFLAGS += $(compat_vdso) |
| 50 | 50 | ||
| 51 | ifeq ($(call test-ge, $(CONFIG_RUSTC_VERSION), 108500),y) | ||
| 52 | KBUILD_RUSTFLAGS += --target=aarch64-unknown-none-softfloat | ||
| 53 | else | ||
| 51 | KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon" | 54 | KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon" |
| 55 | endif | ||
| 52 | 56 | ||
| 53 | KBUILD_CFLAGS += $(call cc-option,-mabi=lp64) | 57 | KBUILD_CFLAGS += $(call cc-option,-mabi=lp64) |
| 54 | KBUILD_AFLAGS += $(call cc-option,-mabi=lp64) | 58 | KBUILD_AFLAGS += $(call cc-option,-mabi=lp64) |
| @@ -101,16 +101,18 @@ int populate_cache_leaves(unsigned int cpu) · 100 unmodified lines | |||
| 101 | unsigned int level, idx; | 101 | unsigned int level, idx; |
| 102 | enum cache_type type; | 102 | enum cache_type type; |
| 103 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); | 103 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); |
| 104 | struct cacheinfo *this_leaf = this_cpu_ci->info_list; | 104 | struct cacheinfo *infos = this_cpu_ci->info_list; |
| 105 | 105 | ||
| 106 | for (idx = 0, level = 1; level <= this_cpu_ci->num_levels && | 106 | for (idx = 0, level = 1; level <= this_cpu_ci->num_levels && |
| 107 | idx < this_cpu_ci->num_leaves; idx++, level++) { | 107 | idx < this_cpu_ci->num_leaves; level++) { |
| 108 | type = get_cache_type(level); | 108 | type = get_cache_type(level); |
| 109 | if (type == CACHE_TYPE_SEPARATE) { | 109 | if (type == CACHE_TYPE_SEPARATE) { |
| 110 | ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level); | 110 | if (idx + 1 >= this_cpu_ci->num_leaves) |
| 111 | ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level); | 111 | break; |
| 112 | ci_leaf_init(&infos[idx++], CACHE_TYPE_DATA, level); | ||
| 113 | ci_leaf_init(&infos[idx++], CACHE_TYPE_INST, level); | ||
| 112 | } else { | 114 | } else { |
| 113 | ci_leaf_init(this_leaf++, type, level); | 115 | ci_leaf_init(&infos[idx++], type, level); |
| 114 | } | 116 | } |
| 115 | } | 117 | } |
| 116 | return 0; | 118 | return 0; |
| @@ -3091,6 +3091,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { · 3090 unmodified lines | |||
| 3091 | HWCAP_CAP(ID_AA64ISAR0_EL1, TS, FLAGM, CAP_HWCAP, KERNEL_HWCAP_FLAGM), | 3091 | HWCAP_CAP(ID_AA64ISAR0_EL1, TS, FLAGM, CAP_HWCAP, KERNEL_HWCAP_FLAGM), |
| 3092 | HWCAP_CAP(ID_AA64ISAR0_EL1, TS, FLAGM2, CAP_HWCAP, KERNEL_HWCAP_FLAGM2), | 3092 | HWCAP_CAP(ID_AA64ISAR0_EL1, TS, FLAGM2, CAP_HWCAP, KERNEL_HWCAP_FLAGM2), |
| 3093 | HWCAP_CAP(ID_AA64ISAR0_EL1, RNDR, IMP, CAP_HWCAP, KERNEL_HWCAP_RNG), | 3093 | HWCAP_CAP(ID_AA64ISAR0_EL1, RNDR, IMP, CAP_HWCAP, KERNEL_HWCAP_RNG), |
| 3094 | HWCAP_CAP(ID_AA64ISAR3_EL1, FPRCVT, IMP, CAP_HWCAP, KERNEL_HWCAP_FPRCVT), | ||
| 3094 | HWCAP_CAP(ID_AA64PFR0_EL1, FP, IMP, CAP_HWCAP, KERNEL_HWCAP_FP), | 3095 | HWCAP_CAP(ID_AA64PFR0_EL1, FP, IMP, CAP_HWCAP, KERNEL_HWCAP_FP), |
| 3095 | HWCAP_CAP(ID_AA64PFR0_EL1, FP, FP16, CAP_HWCAP, KERNEL_HWCAP_FPHP), | 3096 | HWCAP_CAP(ID_AA64PFR0_EL1, FP, FP16, CAP_HWCAP, KERNEL_HWCAP_FPHP), |
| 3096 | HWCAP_CAP(ID_AA64PFR0_EL1, AdvSIMD, IMP, CAP_HWCAP, KERNEL_HWCAP_ASIMD), | 3097 | HWCAP_CAP(ID_AA64PFR0_EL1, AdvSIMD, IMP, CAP_HWCAP, KERNEL_HWCAP_ASIMD), |
| @@ -3180,8 +3181,6 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { · 83 unmodified lines | |||
| 3180 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8FMA), | 3181 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8FMA), |
| 3181 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP4), | 3182 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP4), |
| 3182 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP2), | 3183 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP2), |
| 3183 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8MM8, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8MM8), | ||
| 3184 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8MM4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8MM4), | ||
| 3185 | HWCAP_CAP(ID_AA64SMFR0_EL1, SBitPerm, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SBITPERM), | 3184 | HWCAP_CAP(ID_AA64SMFR0_EL1, SBitPerm, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SBITPERM), |
| 3186 | HWCAP_CAP(ID_AA64SMFR0_EL1, AES, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_AES), | 3185 | HWCAP_CAP(ID_AA64SMFR0_EL1, AES, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_AES), |
| 3187 | HWCAP_CAP(ID_AA64SMFR0_EL1, SFEXPA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SFEXPA), | 3186 | HWCAP_CAP(ID_AA64SMFR0_EL1, SFEXPA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SFEXPA), |
| @@ -3192,6 +3191,8 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { · 4 unmodified lines | |||
| 3192 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_F8FMA), | 3191 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_F8FMA), |
| 3193 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_F8DP4), | 3192 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_F8DP4), |
| 3194 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8DP2), | 3193 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8DP2), |
| 3194 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8MM8, IMP, CAP_HWCAP, KERNEL_HWCAP_F8MM8), | ||
| 3195 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8MM4, IMP, CAP_HWCAP, KERNEL_HWCAP_F8MM4), | ||
| 3195 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8E4M3, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E4M3), | 3196 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8E4M3, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E4M3), |
| 3196 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8E5M2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E5M2), | 3197 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8E5M2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E5M2), |
| 3197 | #ifdef CONFIG_ARM64_POE | 3198 | #ifdef CONFIG_ARM64_POE |
| @@ -194,12 +194,19 @@ static void amu_fie_setup(const struct cpumask *cpus) · 193 unmodified lines | |||
| 194 | int cpu; | 194 | int cpu; |
| 195 | 195 | ||
| 196 | /* We are already set since the last insmod of cpufreq driver */ | 196 | /* We are already set since the last insmod of cpufreq driver */ |
| 197 | if (unlikely(cpumask_subset(cpus, amu_fie_cpus))) | 197 | if (cpumask_available(amu_fie_cpus) && |
| 198 | unlikely(cpumask_subset(cpus, amu_fie_cpus))) | ||
| 198 | return; | 199 | return; |
| 199 | 200 | ||
| 200 | for_each_cpu(cpu, cpus) { | 201 | for_each_cpu(cpu, cpus) |
| 201 | if (!freq_counters_valid(cpu)) | 202 | if (!freq_counters_valid(cpu)) |
| 202 | return; | 203 | return; |
| 204 | |||
| 205 | if (!cpumask_available(amu_fie_cpus) && | ||
| 206 | !zalloc_cpumask_var(&amu_fie_cpus, GFP_KERNEL)) { | ||
| 207 | WARN_ONCE(1, "Failed to allocate FIE cpumask for CPUs[%*pbl]\n", | ||
| 208 | cpumask_pr_args(cpus)); | ||
| 209 | return; | ||
| 203 | } | 210 | } |
| 204 | 211 | ||
| 205 | cpumask_or(amu_fie_cpus, amu_fie_cpus, cpus); | 212 | cpumask_or(amu_fie_cpus, amu_fie_cpus, cpus); |
| @@ -237,17 +244,8 @@ static struct notifier_block init_amu_fie_notifier = { · 31 unmodified lines | |||
| 237 | 244 | ||
| 238 | static int __init init_amu_fie(void) | 245 | static int __init init_amu_fie(void) |
| 239 | { | 246 | { |
| 240 | int ret; | 247 | return cpufreq_register_notifier(&init_amu_fie_notifier, |
| 241 | |||
| 242 | if (!zalloc_cpumask_var(&amu_fie_cpus, GFP_KERNEL)) | ||
| 243 | return -ENOMEM; | ||
| 244 | |||
| 245 | ret = cpufreq_register_notifier(&init_amu_fie_notifier, | ||
| 246 | CPUFREQ_POLICY_NOTIFIER); | 248 | CPUFREQ_POLICY_NOTIFIER); |
| 247 | if (ret) | ||
| 248 | free_cpumask_var(amu_fie_cpus); | ||
| 249 | |||
| 250 | return ret; | ||
| 251 | } | 249 | } |
| 252 | core_initcall(init_amu_fie); | 250 | core_initcall(init_amu_fie); |
| 253 | 251 | ||
| @@ -41,6 +41,7 @@ SECTIONS · 40 unmodified lines | |||
| 41 | */ | 41 | */ |
| 42 | /DISCARD/ : { | 42 | /DISCARD/ : { |
| 43 | *(.note.GNU-stack .note.gnu.property) | 43 | *(.note.GNU-stack .note.gnu.property) |
| 44 | *(.ARM.attributes) | ||
| 44 | } | 45 | } |
| 45 | .note : { *(.note.*) } :text :note | 46 | .note : { *(.note.*) } :text :note |
| 46 | 47 | ||
| @@ -162,6 +162,7 @@ SECTIONS · 161 unmodified lines | |||
| 162 | /DISCARD/ : { | 162 | /DISCARD/ : { |
| 163 | *(.interp .dynamic) | 163 | *(.interp .dynamic) |
| 164 | *(.dynsym .dynstr .hash .gnu.hash) | 164 | *(.dynsym .dynstr .hash .gnu.hash) |
| 165 | *(.ARM.attributes) | ||
| 165 | } | 166 | } |
| 166 | 167 | ||
| 167 | . = KIMAGE_VADDR; | 168 | . = KIMAGE_VADDR; |
| @@ -162,6 +162,13 @@ static int copy_p4d(struct trans_pgd_info *info, pgd_t *dst_pgdp, · 161 unmodified lines | |||
| 162 | unsigned long next; | 162 | unsigned long next; |
| 163 | unsigned long addr = start; | 163 | unsigned long addr = start; |
| 164 | 164 | ||
| 165 | if (pgd_none(READ_ONCE(*dst_pgdp))) { | ||
| 166 | dst_p4dp = trans_alloc(info); | ||
| 167 | if (!dst_p4dp) | ||
| 168 | return -ENOMEM; | ||
| 169 | pgd_populate(NULL, dst_pgdp, dst_p4dp); | ||
| 170 | } | ||
| 171 | |||
| 165 | dst_p4dp = p4d_offset(dst_pgdp, start); | 172 | dst_p4dp = p4d_offset(dst_pgdp, start); |
| 166 | src_p4dp = p4d_offset(src_pgdp, start); | 173 | src_p4dp = p4d_offset(src_pgdp, start); |
| 167 | do { | 174 | do { |
| @@ -163,7 +163,7 @@ int __init acpi_gtdt_init(struct acpi_table_header *table, · 162 unmodified lines | |||
| 163 | { | 163 | { |
| 164 | void *platform_timer; | 164 | void *platform_timer; |
| 165 | struct acpi_table_gtdt *gtdt; | 165 | struct acpi_table_gtdt *gtdt; |
| 166 | int cnt = 0; | 166 | u32 cnt = 0; |
| 167 | 167 | ||
| 168 | gtdt = container_of(table, struct acpi_table_gtdt, header); | 168 | gtdt = container_of(table, struct acpi_table_gtdt, header); |
| 169 | acpi_gtdt_desc.gtdt = gtdt; | 169 | acpi_gtdt_desc.gtdt = gtdt; |
| @@ -188,13 +188,17 @@ int __init acpi_gtdt_init(struct acpi_table_header *table, · 18 unmodified lines | |||
| 188 | cnt++; | 188 | cnt++; |
| 189 | 189 | ||
| 190 | if (cnt != gtdt->platform_timer_count) { | 190 | if (cnt != gtdt->platform_timer_count) { |
| 191 | cnt = min(cnt, gtdt->platform_timer_count); | ||
| 192 | pr_err(FW_BUG "limiting Platform Timer count to %d\n", cnt); | ||
| 193 | } | ||
| 194 | |||
| 195 | if (!cnt) { | ||
| 191 | acpi_gtdt_desc.platform_timer = NULL; | 196 | acpi_gtdt_desc.platform_timer = NULL; |
| 192 | pr_err(FW_BUG "invalid timer data.\n"); | 197 | return 0; |
| 193 | return -EINVAL; | ||
| 194 | } | 198 | } |
| 195 | 199 | ||
| 196 | if (platform_timer_count) | 200 | if (platform_timer_count) |
| 197 | *platform_timer_count = gtdt->platform_timer_count; | 201 | *platform_timer_count = cnt; |
| 198 | 202 | ||
| 199 | return 0; | 203 | return 0; |
| 200 | } | 204 | } |