summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/arch/arm64/silicon-errata.rst2
-rw-r--r--arch/arm64/Kconfig30
-rw-r--r--arch/arm64/kernel/cpu_errata.c24
-rw-r--r--arch/arm64/kernel/cpufeature.c2
-rw-r--r--arch/arm64/kernel/signal.c34
-rw-r--r--arch/arm64/kernel/topology.c22
-rw-r--r--arch/arm64/mm/mmu.c2
-rw-r--r--arch/arm64/tools/cpucaps2
8 files changed, 84 insertions, 34 deletions
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index ac3248b9f..99a1eb4b8 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -174,6 +174,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A725 | #3456106 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-A725 | #3821522 | ARM64_ERRATUM_3821522 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X1 | #1502854 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X1 | #3324344 | ARM64_ERRATUM_3194386 |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b5a51b0ef..cab741a69 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1040,9 +1040,17 @@ config ARM64_ERRATUM_1902691
If unsure, say Y.
+config ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT
+ bool
+ # Targeting errata affecting AMEVCNTR01, the AMU constant counter.
+ # On affected CPUs the counter may not increment at the expected rate,
+ # making it unreliable. As a result, AMU users should treat it as
+ # unavailable rather than relying on misleading counter values.
+
config ARM64_ERRATUM_2457168
bool "Cortex-A510: 2457168: workaround for AMEVCNTR01 incrementing incorrectly"
depends on ARM64_AMU_EXTN
+ select ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT
default y
help
This option adds the workaround for ARM Cortex-A510 erratum 2457168.
@@ -1073,6 +1081,28 @@ config ARM64_ERRATUM_2645198
If unsure, say Y.
+config ARM64_ERRATUM_3821522
+ bool "Cortex-A725: 3821522: workaround for possible CNT_CYCLES increment error due to WFE/WFI"
+ depends on ARM64_AMU_EXTN
+ select ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT
+ default y
+ help
+ This option adds the workaround for ARM Cortex-A725 erratum 3821522.
+
+ On affected A725 cores, the CNT_CYCLES event may incur a significant
+ increment error when entering and subsequently exiting WFx.
+ As a result, the CNT_CYCLES may diverge from the system counter
+ frequency at which it is expected to increment.
+ This renders the AMU counter AMEVCNTR01, that implements CNT_CYCLES,
+ being unreliable and unsuitable for use.
+
+ Since there is no hardware workaround, reads of the affected CNT_CYCLES
+ counter return 0 in the relevant paths. This causes users of the counter
+ to treat it as unavailable and is functionally equivalent to firmware
+ disabling the affected counter.
+
+ If unsure, say Y.
+
config ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
bool
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 8ec47d89b..e0c094025 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -384,6 +384,20 @@ static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
};
#endif
+#ifdef CONFIG_ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT
+static const struct midr_range workaround_amu_constcnt_list[] = {
+#ifdef CONFIG_ARM64_ERRATUM_2457168
+ /* Cortex-A510 r0p0-r1p1 */
+ MIDR_RANGE(MIDR_CORTEX_A510, 0, 0, 1, 1),
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_3821522
+ /* Cortex-A725 r0p0 - r0p2 */
+ MIDR_RANGE(MIDR_CORTEX_A725, 0, 0, 0, 2),
+#endif
+ {}
+};
+#endif /* CONFIG_ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT */
+
#ifdef CONFIG_CAVIUM_ERRATUM_23154
static const struct midr_range cavium_erratum_23154_cpus[] = {
MIDR_ALL_VERSIONS(MIDR_THUNDERX),
@@ -919,14 +933,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A510, 0, 0, 2)
},
#endif
-#ifdef CONFIG_ARM64_ERRATUM_2457168
+#ifdef CONFIG_ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT
{
- .desc = "ARM erratum 2457168",
- .capability = ARM64_WORKAROUND_2457168,
+ .desc = "Broken AMU AMEVCNTR01 (const counter)",
+ .capability = ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT,
.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
-
- /* Cortex-A510 r0p0-r1p1 */
- CAP_MIDR_RANGE(MIDR_CORTEX_A510, 0, 0, 1, 1)
+ CAP_MIDR_RANGE_LIST(workaround_amu_constcnt_list)
},
#endif
#ifdef CONFIG_ARM64_ERRATUM_2038923
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 32102c391..3ae3ad1a1 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2089,7 +2089,7 @@ static void cpu_amu_enable(struct arm64_cpu_capabilities const *cap)
cpumask_set_cpu(smp_processor_id(), &amu_cpus);
/* 0 reference values signal broken/disabled counters */
- if (!this_cpu_has_cap(ARM64_WORKAROUND_2457168))
+ if (!this_cpu_has_cap(ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT))
update_freq_counters_refs();
}
}
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 38e6fa204..6a06a4e35 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -433,6 +433,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
unsigned int vl, vq;
struct user_fpsimd_state fpsimd;
u16 user_vl, flags;
+ bool fpsimd_only;
bool sm;
if (user->sve_size < sizeof(*user->sve))
@@ -443,19 +444,33 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
if (err)
return err;
+ fpsimd_only = (user->sve_size == sizeof(*user->sve));
sm = flags & SVE_SIG_FLAG_SM;
+
if (sm) {
if (!system_supports_sme())
return -EINVAL;
+ /*
+ * Streaming SVE state is always preserved with an SVE payload.
+ * Only accept streaming state which has an SVE payload.
+ */
+ if (fpsimd_only)
+ return -EINVAL;
+
vl = task_get_sme_vl(current);
} else {
/*
- * A SME only system use SVE for streaming mode so can
- * have a SVE formatted context with a zero VL and no
- * payload data.
+ * Non-streaming SVE state may be preserved without an SVE
+ * payload, in which case all state is saved in the FPSIMD
+ * context.
+ *
+ * On SME-only systems, non-streaming (FPSIMD-only) state is
+ * always preserved without an SVE payload, and with VL==0. On
+ * such systems, only accept non-streaming state without an SVE
+ * payload.
*/
- if (!system_supports_sve() && !system_supports_sme())
+ if (!system_supports_sve() && !fpsimd_only)
return -EINVAL;
vl = task_get_sve_vl(current);
@@ -464,16 +479,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
if (user_vl != vl)
return -EINVAL;
- /*
- * Non-streaming SVE state may be preserved without an SVE payload, in
- * which case the SVE context only has a header with VL==0, and all
- * state can be restored from the FPSIMD context.
- *
- * Streaming SVE state is always preserved with an SVE payload. For
- * consistency and robustness, reject restoring streaming SVE state
- * without an SVE payload.
- */
- if (!sm && user->sve_size == sizeof(*user->sve))
+ if (fpsimd_only)
return restore_fpsimd_context(user);
vq = sve_vq_from_vl(vl);
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index d28438f8b..806373aac 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -186,7 +186,6 @@ int arch_freq_get_on_cpu(int cpu)
struct amu_cntr_sample *amu_sample;
unsigned int start_cpu = cpu;
unsigned long last_update;
- unsigned int freq = 0;
u64 scale;
if (!amu_fie_cpu_supported(cpu) || !arch_scale_freq_ref(cpu))
@@ -245,9 +244,8 @@ int arch_freq_get_on_cpu(int cpu)
* (see amu_scale_freq_tick for details)
*/
scale = arch_scale_freq_capacity(cpu);
- freq = scale * arch_scale_freq_ref(cpu);
- freq >>= SCHED_CAPACITY_SHIFT;
- return freq;
+
+ return (scale * arch_scale_freq_ref(cpu)) >> SCHED_CAPACITY_SHIFT;
}
static void amu_fie_setup(const struct cpumask *cpus)
@@ -397,12 +395,13 @@ static void cpu_read_corecnt(void *val)
static void cpu_read_constcnt(void *val)
{
/*
- * Return 0 if the current CPU is affected by erratum 2457168. A value
- * of 0 is also returned if the current CPU does not support AMUs or if
- * the counter is disabled. A return value of 0 at counter read is
- * properly handled as an error case by the users of the counter.
+ * Return 0 if the current CPU is affected by a HW erratum.
+ * A value of 0 is also returned if the current CPU does not
+ * support AMUs or if the counter is disabled. A return
+ * value of 0 at counter read is properly handled as an error
+ * case by the users of the counter.
*/
- *(u64 *)val = this_cpu_has_cap(ARM64_WORKAROUND_2457168) ?
+ *(u64 *)val = this_cpu_has_cap(ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT) ?
0UL : read_constcnt();
}
@@ -463,8 +462,9 @@ static void amu_read_core_const_ctrs(void *val)
/*
* cpu_read_constcnt() incurs slight latency due to the
- * ARM64_WORKAROUND_2457168 check. Read it first to minimize
- * the sampling skew between the const and core counters.
+ * ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT check.
+ * Read it first to minimize the sampling skew between the const
+ * and core counters.
*/
cpu_read_constcnt(&ctrs->constcnt);
cpu_read_corecnt(&ctrs->corecnt);
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 79d90226f..d4384131e 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -2295,7 +2295,7 @@ pte_t modify_prot_start_ptes(struct vm_area_struct *vma, unsigned long addr,
* in cases where cpu is affected with errata #2645198.
*/
if (pte_accessible(vma->vm_mm, pte) && pte_user_exec(pte))
- __flush_tlb_range(vma, addr, nr * PAGE_SIZE,
+ __flush_tlb_range(vma, addr, addr + nr * PAGE_SIZE,
PAGE_SIZE, 3, TLBF_NOWALKCACHE);
}
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 2775ba335..58b6c084f 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -105,7 +105,6 @@ WORKAROUND_1902691
WORKAROUND_2038923
WORKAROUND_2064142
WORKAROUND_2077057
-WORKAROUND_2457168
WORKAROUND_2645198
WORKAROUND_2658417
WORKAROUND_4193714
@@ -132,3 +131,4 @@ WORKAROUND_REPEAT_TLBI_SYNC
WORKAROUND_SPECULATIVE_AT
WORKAROUND_SPECULATIVE_SSBS
WORKAROUND_SPECULATIVE_UNPRIV_LOAD
+WORKAROUND_BROKEN_AMU_CONSTCNT