* [RFC PATCH v1 0/5] Initial BBML2 support for contpte_convert()
@ 2024-12-11 15:45 Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 1/5] arm64: Add TLB Conflict Abort Exception handler to KVM Mikołaj Lenczewski
` (4 more replies)
0 siblings, 5 replies; 12+ messages in thread
From: Mikołaj Lenczewski @ 2024-12-11 15:45 UTC (permalink / raw)
To: catalin.marinas, will, corbet, maz, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui
Cc: Mikołaj Lenczewski, linux-arm-kernel, liunx-doc,
linux-kernel, kvmarm
Hi All,
This patch series seeks to gather feedback on adding initial support
for level 2 of the Break-Before-Make arm64 architectural feature,
specifically to contpte_convert().
This support reorders a TLB invalidation in contpte_convert(), and
optionally elides said invalidation completely which leads to a 12%
improvement when executing a microbenchmark designed to force the
pathological path where contpte_convert() gets called. This
represents an 80% reduction in the cost of calling contpte_convert().
However, the elision of the invalidation is still pending review to
ensure it is architecturally valid. Without it, the reodering also
represents a performance improvement due to reducing thread contention,
as there is a smaller time window for racing threads to see an invalid
pagetable entry (especially if they already have a cached entry in their
TLB that they are working off of).
This series is based on v6.13-rc2 (fac04efc5c79).
Break-Before-Make Level 2
=========================
Break-Before-Make (BBM) sequences ensure a consistent view of the
page tables. They avoid TLB multi-hits and ensure atomicity and
ordering guarantees. BBM level 0 simply defines the current use
of page tables. When you want to change certain bits in a pte,
you need to:
- clear the pte
- dsb()
- issue a tlbi for the pte
- dsb()
- repaint the pte
- dsb()
When changing block size, or toggling the contiguous bit, we
currently use this BBM level 0 sequence. With BBM level 2 support,
however, we can relax the BBM sequence and benefit from a performance
improvement. The hardware would then either automatically handle the
TLB invalidations, or would take a TLB Conflict Abort Exception.
This exception can either be a stage 1 or stage 2 exception, depending
on whether stage 1 or stage 2 translations are in use. The architecture
currently mandates a worst-case invalidation of vmalle1 or vmalls12e1,
when stage 2 translation is not in-use and in-use respectively.
Outstanding Questions and Remaining TODOs
=========================================
Patch 4 moves the tlbi so that the window where the pte is invalid is
significantly smaller. This reduces the chances of racing threads
accessing the memory during the window and taking a fault. This is
confirmed to be architecturally sound.
Patch 5 removes the tlbi entirely. This has the benefit of
significantly reducing the cost of contpte_convert(). While testing
has demonstrated that this works as expected on Arm-designed CPUs, we
are still in the process of confirming whether it is architecturally
correct. I am requesting review while that process is on-going. Patch 5
would be dropped if it turns out to be architecturally unsound.
Another note is that the stage 2 TLB conflict handling is included as
patch 1 of this series. This patch could (and probably should) be sent
separately as it may be useful outside this series, but is included for
reference.
Thanks,
Miko
Mikołaj Lenczewski (5):
arm64: Add TLB Conflict Abort Exception handler to KVM
arm64: Add BBM Level 2 cpu feature
arm64: Add errata and workarounds for systems with broken BBML2
arm64/mm: Delay tlbi in contpte_convert() under BBML2
arm64/mm: Elide tlbi in contpte_convert() under BBML2
Documentation/arch/arm64/silicon-errata.rst | 32 ++++
arch/arm64/Kconfig | 164 ++++++++++++++++++++
arch/arm64/include/asm/cpufeature.h | 14 ++
arch/arm64/include/asm/esr.h | 8 +
arch/arm64/kernel/cpufeature.c | 37 +++++
arch/arm64/kvm/mmu.c | 6 +
arch/arm64/mm/contpte.c | 3 +-
arch/arm64/mm/fault.c | 27 +++-
arch/arm64/tools/cpucaps | 1 +
9 files changed, 290 insertions(+), 2 deletions(-)
--
2.45.2
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH v1 1/5] arm64: Add TLB Conflict Abort Exception handler to KVM
2024-12-11 15:45 [RFC PATCH v1 0/5] Initial BBML2 support for contpte_convert() Mikołaj Lenczewski
@ 2024-12-11 15:45 ` Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 2/5] arm64: Add BBM Level 2 cpu feature Mikołaj Lenczewski
` (3 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: Mikołaj Lenczewski @ 2024-12-11 15:45 UTC (permalink / raw)
To: catalin.marinas, will, corbet, maz, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui
Cc: Mikołaj Lenczewski, linux-arm-kernel, liunx-doc,
linux-kernel, kvmarm
Currently, KVM does not handle the case of a stage 2 TLB conflict abort
exception. The Arm ARM specifies that the worst-case handling of such an
exception requires a `tlbi vmalls12e1`. Perform such an invalidation
when this exception is encountered.
Signed-off-by: Mikołaj Lenczewski <miko.lenczewski@arm.com>
---
arch/arm64/include/asm/esr.h | 8 ++++++++
arch/arm64/kvm/mmu.c | 6 ++++++
2 files changed, 14 insertions(+)
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index d1b1a33f9a8b..8a66f81ca291 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -121,6 +121,7 @@
#define ESR_ELx_FSC_SEA_TTW(n) (0x14 + (n))
#define ESR_ELx_FSC_SECC (0x18)
#define ESR_ELx_FSC_SECC_TTW(n) (0x1c + (n))
+#define ESR_ELx_FSC_TLBABT (0x30)
/* Status codes for individual page table levels */
#define ESR_ELx_FSC_ACCESS_L(n) (ESR_ELx_FSC_ACCESS + (n))
@@ -464,6 +465,13 @@ static inline bool esr_fsc_is_access_flag_fault(unsigned long esr)
(esr == ESR_ELx_FSC_ACCESS_L(0));
}
+static inline bool esr_fsc_is_tlb_conflict_abort(unsigned long esr)
+{
+ esr = esr & ESR_ELx_FSC;
+
+ return esr == ESR_ELx_FSC_TLBABT;
+}
+
/* Indicate whether ESR.EC==0x1A is for an ERETAx instruction */
static inline bool esr_iss_is_eretax(unsigned long esr)
{
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index c9d46ad57e52..c8c6f5a97a1b 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1756,6 +1756,12 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
ipa = fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
+ if (esr_fsc_is_tlb_conflict_abort(esr)) {
+ // does a `tlbi vmalls12e1is`
+ __kvm_tlb_flush_vmid(&vcpu->kvm->arch.mmu);
+ return 1;
+ }
+
if (esr_fsc_is_translation_fault(esr)) {
/* Beyond sanitised PARange (which is the IPA limit) */
if (fault_ipa >= BIT_ULL(get_kvm_ipa_limit())) {
--
2.45.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC PATCH v1 2/5] arm64: Add BBM Level 2 cpu feature
2024-12-11 15:45 [RFC PATCH v1 0/5] Initial BBML2 support for contpte_convert() Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 1/5] arm64: Add TLB Conflict Abort Exception handler to KVM Mikołaj Lenczewski
@ 2024-12-11 15:45 ` Mikołaj Lenczewski
2024-12-11 21:02 ` Will Deacon
2024-12-11 15:45 ` [RFC PATCH v1 3/5] arm64: Add errata and workarounds for systems with broken BBML2 Mikołaj Lenczewski
` (2 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Mikołaj Lenczewski @ 2024-12-11 15:45 UTC (permalink / raw)
To: catalin.marinas, will, corbet, maz, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui
Cc: Mikołaj Lenczewski, linux-arm-kernel, liunx-doc,
linux-kernel, kvmarm
The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
and this commit adds a dedicated BBML2 cpufeature to test against
support for.
In supporting BBM level 2, we open ourselves up to potential TLB
Conflict Abort Exceptions during expected execution, instead of only
in exceptional circumstances. In the case of an abort, it is
implementation defined at what stage the abort is generated, and
the minimal set of required invalidations is also implementation
defined. The maximal set of invalidations is to do a `tlbi vmalle1`
or `tlbi vmalls12e1`, depending on the stage.
Such aborts should not occur on Arm hardware, and were not seen in
benchmarked systems, so unless performance concerns arise, implementing
the abort handlers with the worst-case invalidations seems like an
alright hack.
Signed-off-by: Mikołaj Lenczewski <miko.lenczewski@arm.com>
---
arch/arm64/include/asm/cpufeature.h | 14 ++++++++++++++
arch/arm64/kernel/cpufeature.c | 7 +++++++
arch/arm64/mm/fault.c | 27 ++++++++++++++++++++++++++-
arch/arm64/tools/cpucaps | 1 +
4 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 8b4e5a3cd24c..a9f2ac335392 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -866,6 +866,20 @@ static __always_inline bool system_supports_mpam_hcr(void)
return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
}
+static inline bool system_supports_bbml2(void)
+{
+ /* currently, BBM is only relied on by code touching the userspace page
+ * tables, and as such we are guaranteed that caps have been finalised.
+ *
+ * if later we want to use BBM for kernel mappings, particularly early
+ * in the kernel, this may return 0 even if BBML2 is actually supported,
+ * which means unnecessary break-before-make sequences, but is still
+ * correct
+ */
+
+ return alternative_has_cap_unlikely(ARM64_HAS_BBML2);
+}
+
int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 6ce71f444ed8..7cc94bd5da24 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2917,6 +2917,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.matches = has_cpuid_feature,
ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
},
+ {
+ .desc = "BBM Level 2 Support",
+ .capability = ARM64_HAS_BBML2,
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .matches = has_cpuid_feature,
+ ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, BBM, 2)
+ },
{
.desc = "52-bit Virtual Addressing for KVM (LPA2)",
.capability = ARM64_HAS_LPA2,
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index ef63651099a9..dc119358cbc1 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -844,6 +844,31 @@ static int do_tag_check_fault(unsigned long far, unsigned long esr,
return 0;
}
+static int do_conflict_abort(unsigned long far, unsigned long esr,
+ struct pt_regs *regs)
+{
+ if (!system_supports_bbml2())
+ return do_bad(far, esr, regs);
+
+ /* if we receive a TLB conflict abort, we know that there are multiple
+ * TLB entries that translate the same address range. the minimum set
+ * of invalidations to clear these entries is implementation defined.
+ * the maximum set is defined as either tlbi(vmalls12e1) or tlbi(alle1).
+ *
+ * if el2 is enabled and stage 2 translation enabled, this may be
+ * raised as a stage 2 abort. if el2 is enabled but stage 2 translation
+ * disabled, or if el2 is disabled, it will be raised as a stage 1
+ * abort.
+ *
+ * local_flush_tlb_all() does a tlbi(vmalle1), which is enough to
+ * handle a stage 1 abort.
+ */
+
+ local_flush_tlb_all();
+
+ return 0;
+}
+
static const struct fault_info fault_info[] = {
{ do_bad, SIGKILL, SI_KERNEL, "ttbr address size fault" },
{ do_bad, SIGKILL, SI_KERNEL, "level 1 address size fault" },
@@ -893,7 +918,7 @@ static const struct fault_info fault_info[] = {
{ do_bad, SIGKILL, SI_KERNEL, "unknown 45" },
{ do_bad, SIGKILL, SI_KERNEL, "unknown 46" },
{ do_bad, SIGKILL, SI_KERNEL, "unknown 47" },
- { do_bad, SIGKILL, SI_KERNEL, "TLB conflict abort" },
+ { do_conflict_abort, SIGKILL, SI_KERNEL, "TLB conflict abort" },
{ do_bad, SIGKILL, SI_KERNEL, "Unsupported atomic hardware update fault" },
{ do_bad, SIGKILL, SI_KERNEL, "unknown 50" },
{ do_bad, SIGKILL, SI_KERNEL, "unknown 51" },
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index eb17f59e543c..4ee0fbb7765b 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -26,6 +26,7 @@ HAS_ECV
HAS_ECV_CNTPOFF
HAS_EPAN
HAS_EVT
+HAS_BBML2
HAS_FPMR
HAS_FGT
HAS_FPSIMD
--
2.45.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC PATCH v1 3/5] arm64: Add errata and workarounds for systems with broken BBML2
2024-12-11 15:45 [RFC PATCH v1 0/5] Initial BBML2 support for contpte_convert() Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 1/5] arm64: Add TLB Conflict Abort Exception handler to KVM Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 2/5] arm64: Add BBM Level 2 cpu feature Mikołaj Lenczewski
@ 2024-12-11 15:45 ` Mikołaj Lenczewski
2024-12-11 16:52 ` Marc Zyngier
2024-12-11 15:45 ` [RFC PATCH v1 4/5] arm64/mm: Delay tlbi in contpte_convert() under BBML2 Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 5/5] arm64/mm: Elide " Mikołaj Lenczewski
4 siblings, 1 reply; 12+ messages in thread
From: Mikołaj Lenczewski @ 2024-12-11 15:45 UTC (permalink / raw)
To: catalin.marinas, will, corbet, maz, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui
Cc: Mikołaj Lenczewski, linux-arm-kernel, liunx-doc,
linux-kernel, kvmarm
There are systems which claim support for BBML2, but whose
implementation of this support is broken. Add a Kconfig erratum for each
of these systems, and a cpufeature workaround that forces the supported
BBM level on these systems to 0.
Signed-off-by: Mikołaj Lenczewski <miko.lenczewski@arm.com>
---
Documentation/arch/arm64/silicon-errata.rst | 32 ++++
arch/arm64/Kconfig | 164 ++++++++++++++++++++
arch/arm64/kernel/cpufeature.c | 32 +++-
3 files changed, 227 insertions(+), 1 deletion(-)
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index b42fea07c5ce..4b4c1dd9b671 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -126,16 +126,26 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A76 | #3324349 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-A76 | #3696297 | ARM64_ERRATUM_3696297 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A77 | #1491015 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A77 | #1508412 | ARM64_ERRATUM_1508412 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A77 | #3324348 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-A77 | #3696294 | ARM64_ERRATUM_3696294 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A78 | #3324344 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-A78 | #3696287 | ARM64_ERRATUM_3696287 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A78C | #3324346,3324347| ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-A78C | #3696291 | ARM64_ERRATUM_3696291 |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-A78C | #3696292 | ARM64_ERRATUM_3696292 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A710 | #2119858 | ARM64_ERRATUM_2119858 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A710 | #2054223 | ARM64_ERRATUM_2054223 |
@@ -144,6 +154,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A710 | #3324338 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-A710 | #3696244 | ARM64_ERRATUM_3696244 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A715 | #2645198 | ARM64_ERRATUM_2645198 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A715 | #3456084 | ARM64_ERRATUM_3194386 |
@@ -156,6 +168,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X1 | #3324344 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-X1 | #3696287 | ARM64_ERRATUM_3696287 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X1C | #3324346 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X2 | #2119858 | ARM64_ERRATUM_2119858 |
@@ -164,10 +178,18 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X2 | #3324338 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-X2 | #3696244 | ARM64_ERRATUM_3696244 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X3 | #3324335 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-X3 | #3696239 | ARM64_ERRATUM_3696239 |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-X4 | #3043263 | ARM64_ERRATUM_3043263 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X4 | #3194386 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-X925 | #3056274 | ARM64_ERRATUM_3056274 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X925 | #3324334 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N1 | #1188873,1418040| ARM64_ERRATUM_1418040 |
@@ -180,6 +202,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N1 | #3324349 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Neoverse-N1 | #3696297 | ARM64_ERRATUM_3696297 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N2 | #2139208 | ARM64_ERRATUM_2139208 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N2 | #2067961 | ARM64_ERRATUM_2067961 |
@@ -188,14 +212,22 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N2 | #3324339 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Neoverse-N2 | #3696250 | ARM64_ERRATUM_3696250 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N3 | #3456111 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-V1 | #1619801 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-V1 | #3324341 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Neoverse-V1 | #3696285 | ARM64_ERRATUM_3696285 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-V2 | #3324336 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Neoverse-V2 | #3696242 | ARM64_ERRATUM_3696242 |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM | Neoverse-V3 | #3053180 | ARM64_ERRATUM_3053180 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-V3 | #3312417 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | MMU-500 | #841119,826419 | N/A |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 100570a048c5..9ef8418e8410 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1127,6 +1127,170 @@ config ARM64_ERRATUM_3194386
If unsure, say Y.
+config ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ bool
+
+config ARM64_ERRATUM_3696250
+ bool "Neoverse-N2: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Neoverse-N2 cores (r0p0, r0p1, r0p2, r0p3) declare
+ break-before-make level 2 support, but changing the block size
+ without utilising a break-before-make sequence, or mis-programming
+ the contiguous hint bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3696244
+ bool "Cortex-A710/Cortex-X2: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Cortex-A710 and Cortex-X2 cores (r0p0, r1p0, r2p0, r2p1)
+ declare break-before-make level 2 support, but changing the block
+ size without utilising a break-before-make sequence, or
+ mis-programming the contiguous hint bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3696297
+ bool "Cortex-A76/Neoverse-N1: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ This option adds a workaround for ARM Cortex-A76/Neoverse-N1 erratum
+ 3696297.
+
+ Affected Cortex-A76 and Neoverse-N1 cores (r0p0, r1p0, r2p0, r3p0,
+ r3p1, r4p0, r4p1) declare break-before-make level 2 support, but
+ changing the block size without utilising a break-before-make sequence,
+ or mis-programming the contiguous hint bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3696294
+ bool "Cortex-A77: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ This option adds a workaround for ARM Cortex-A77 erratum 3696294.
+
+ Affected Cortex-A77 cores (r0p0, r1p0, r1p1) declare break-before-make
+ level 2 support, but changing the block size without utilising a
+ break-before-make sequence, or mis-programming the contiguous hint
+ bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3696239
+ bool "Cortex-X3: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Cortex-X3 cores (r0p0, r1p0, r1p1, r1p2) declare
+ break-before-make level 2 support, but changing the block size
+ without utilising a break-before-make sequence, or mis-programming
+ the contiguous hint bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3696242
+ bool "Neoverse-V2: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Neoverse-V2 cores (r0p0, r0p1, r0p2) declare
+ break-before-make level 2 support, but changing the block size
+ without utilising a break-before-make sequence, or mis-programming
+ the contiguous hint bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3696285
+ bool "Neoverse-V1: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Neoverse-V1 cores (r0p0, r1p0, r1p1, r1p2) declare
+ break-before-make level 2 support, but changing the block size
+ without utilising a break-before-make sequence, or mis-programming
+ the contiguous hint bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3696287
+ bool "Cortex-A78/Cortex-X1: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Cortex-A78 and Cortex-X1 cores (r0p0, r1p0, r1p1, r1p2)
+ declare break-before-make level 2 support, but changing the block
+ size without utilising a break-before-make sequence, or
+ mis-programming the contiguous hint bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3696291
+ bool "Cortex-A78C: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Cortex-A78C cores (r0p0, r0p1, r0p2) declare
+ break-before-make level 2 support, but changing the block size
+ without utilising a break-before-make sequence, or mis-programming
+ the contiguous hint bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3696292
+ bool "Cortex-A78C: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Cortex-A78C cores (r0p1, r0p2) declare break-before-make
+ level 2 support, but changing the block size without utilising a
+ break-before-make sequence, or mis-programming the contiguous hint
+ bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3056274
+ bool "Cortex-X925: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Cortex-X925 cores (r0p0, r0p1) declare break-before-make
+ level 2 support, but changing the block size without utilising a
+ break-before-make sequence, or mis-programming the contiguous hint
+ bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3043263
+ bool "Cortex-X4: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Cortex-X4 cores (r0p0, r0p1, r0p2) declare break-before-make
+ level 2 support, but changing the block size without utilising a
+ break-before-make sequence, or mis-programming the contiguous hint
+ bit can lead to a livelock.
+
+ If unsure, say Y.
+
+config ARM64_ERRATUM_3053180
+ bool "Neoverse-V3: workaround for broken BBM level 2 support"
+ default y
+ select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
+ help
+ Affected Neoverse-V3 cores (r0p0, r0p1) declare break-before-make
+ level 2 support, but changing the block size without utilising a
+ break-before-make sequence, or mis-programming the contiguous hint
+ bit can lead to a livelock.
+
+ If unsure, say Y.
+
config CAVIUM_ERRATUM_22375
bool "Cavium erratum 22375, 24313"
default y
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 7cc94bd5da24..e6c05b330e0f 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2167,6 +2167,36 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
}
+static bool has_bbml2(const struct arm64_cpu_capabilities *entry,
+ int scope)
+{
+ if (IS_ENABLED(CONFIG_ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT)) {
+ static const struct midr_range broken_bbml2_list[] = {
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A76),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_X3),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_X4),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_X925),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3),
+ {}
+ };
+
+ if (is_midr_in_range_list(read_cpuid_id(), broken_bbml2_list))
+ return false;
+ }
+
+ return has_cpuid_feature(entry, scope);
+}
+
#ifdef CONFIG_ARM64_PAN
static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
{
@@ -2921,7 +2951,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.desc = "BBM Level 2 Support",
.capability = ARM64_HAS_BBML2,
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
- .matches = has_cpuid_feature,
+ .matches = has_bbml2,
ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, BBM, 2)
},
{
--
2.45.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC PATCH v1 4/5] arm64/mm: Delay tlbi in contpte_convert() under BBML2
2024-12-11 15:45 [RFC PATCH v1 0/5] Initial BBML2 support for contpte_convert() Mikołaj Lenczewski
` (2 preceding siblings ...)
2024-12-11 15:45 ` [RFC PATCH v1 3/5] arm64: Add errata and workarounds for systems with broken BBML2 Mikołaj Lenczewski
@ 2024-12-11 15:45 ` Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 5/5] arm64/mm: Elide " Mikołaj Lenczewski
4 siblings, 0 replies; 12+ messages in thread
From: Mikołaj Lenczewski @ 2024-12-11 15:45 UTC (permalink / raw)
To: catalin.marinas, will, corbet, maz, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui
Cc: Mikołaj Lenczewski, linux-arm-kernel, liunx-doc,
linux-kernel, kvmarm
When converting a region via contpte_convert() to use mTHP, we have two
different goals. We have to mark each entry as contiguous, and we would
like to smear the dirty and young (access) bits across all entries in
the contiguous block. Currently, we do this by first accumulating the
dirty and young bits in the block, using an atomic
__ptep_get_and_clear() and the relevant pte_{dirty,young}() calls,
performing a tlbi, and finally smearing the correct bits across the
block using __set_ptes().
This approach works fine for BBM level 0, but with support for BBM level
2 we are allowed to reorder the tlbi to after setting the pagetable
entries. This reordering means that other threads will not see an
invalid pagetable entry, instead operating on stale data, until we have
performed our smearing and issued the invalidation. Avoiding this
invalid entry reduces faults in other threads, and thus improves
performance marginally (more so when there are more threads).
Signed-off-by: Mikołaj Lenczewski <miko.lenczewski@arm.com>
---
arch/arm64/mm/contpte.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
index 55107d27d3f8..fc927be800ee 100644
--- a/arch/arm64/mm/contpte.c
+++ b/arch/arm64/mm/contpte.c
@@ -68,9 +68,13 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
pte = pte_mkyoung(pte);
}
- __flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
+ if (!system_supports_bbml2())
+ __flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
+
+ if (system_supports_bbml2())
+ __flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
}
void __contpte_try_fold(struct mm_struct *mm, unsigned long addr,
--
2.45.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC PATCH v1 5/5] arm64/mm: Elide tlbi in contpte_convert() under BBML2
2024-12-11 15:45 [RFC PATCH v1 0/5] Initial BBML2 support for contpte_convert() Mikołaj Lenczewski
` (3 preceding siblings ...)
2024-12-11 15:45 ` [RFC PATCH v1 4/5] arm64/mm: Delay tlbi in contpte_convert() under BBML2 Mikołaj Lenczewski
@ 2024-12-11 15:45 ` Mikołaj Lenczewski
4 siblings, 0 replies; 12+ messages in thread
From: Mikołaj Lenczewski @ 2024-12-11 15:45 UTC (permalink / raw)
To: catalin.marinas, will, corbet, maz, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui
Cc: Mikołaj Lenczewski, linux-arm-kernel, liunx-doc,
linux-kernel, kvmarm
If we support BBM level 2, we can potentially avoid an intermediate
TLB invalidation, as hardware is capable of managing the TLB itself
in this situation. Hardware will either silently clear out the
offending entry, or will take a TLB Conflict Abort Exception.
Note that such aborts should not occur on Arm hardware and indeed
were not seen on any of the benchmarked systems.
Eliding the invalidation results in a 12% improvement on a
microbenchmark which targeted the worst case of contpte_convert(), which
represents an 80% reduction in the overhead of contpte_convert().
Note also that this patch is pending review to ensure that it is
architecturally valid, and we are working with Arm architects to
validate this patch.
Signed-off-by: Mikołaj Lenczewski <miko.lenczewski@arm.com>
---
arch/arm64/mm/contpte.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c
index fc927be800ee..009690770415 100644
--- a/arch/arm64/mm/contpte.c
+++ b/arch/arm64/mm/contpte.c
@@ -72,9 +72,6 @@ static void contpte_convert(struct mm_struct *mm, unsigned long addr,
__flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
__set_ptes(mm, start_addr, start_ptep, pte, CONT_PTES);
-
- if (system_supports_bbml2())
- __flush_tlb_range(&vma, start_addr, addr, PAGE_SIZE, true, 3);
}
void __contpte_try_fold(struct mm_struct *mm, unsigned long addr,
--
2.45.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [RFC PATCH v1 3/5] arm64: Add errata and workarounds for systems with broken BBML2
2024-12-11 15:45 ` [RFC PATCH v1 3/5] arm64: Add errata and workarounds for systems with broken BBML2 Mikołaj Lenczewski
@ 2024-12-11 16:52 ` Marc Zyngier
2024-12-13 16:21 ` Mikołaj Lenczewski
0 siblings, 1 reply; 12+ messages in thread
From: Marc Zyngier @ 2024-12-11 16:52 UTC (permalink / raw)
To: Mikołaj Lenczewski
Cc: catalin.marinas, will, corbet, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui, linux-arm-kernel, liunx-doc,
linux-kernel, kvmarm
On Wed, 11 Dec 2024 15:45:04 +0000,
Mikołaj Lenczewski <miko.lenczewski@arm.com> wrote:
>
> There are systems which claim support for BBML2, but whose
> implementation of this support is broken. Add a Kconfig erratum for each
> of these systems, and a cpufeature workaround that forces the supported
> BBM level on these systems to 0.
>
> Signed-off-by: Mikołaj Lenczewski <miko.lenczewski@arm.com>
> ---
> Documentation/arch/arm64/silicon-errata.rst | 32 ++++
> arch/arm64/Kconfig | 164 ++++++++++++++++++++
> arch/arm64/kernel/cpufeature.c | 32 +++-
> 3 files changed, 227 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 100570a048c5..9ef8418e8410 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -1127,6 +1127,170 @@ config ARM64_ERRATUM_3194386
>
> If unsure, say Y.
>
> +config ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
> + bool
> +
> +config ARM64_ERRATUM_3696250
> + bool "Neoverse-N2: workaround for broken BBM level 2 support"
> + default y
> + select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
> + help
> + Affected Neoverse-N2 cores (r0p0, r0p1, r0p2, r0p3) declare
So you list a number of affected revisions...
[...]
> +static bool has_bbml2(const struct arm64_cpu_capabilities *entry,
> + int scope)
> +{
> + if (IS_ENABLED(CONFIG_ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT)) {
> + static const struct midr_range broken_bbml2_list[] = {
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_A76),
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_X3),
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_X4),
> + MIDR_ALL_VERSIONS(MIDR_CORTEX_X925),
> + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
> + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
> + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1),
> + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
> + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3),
> + {}
... and yet you flag all versions as broken? So which one is it? If it
is really the case that all versions are broken, then the text should
be simplified. Otherwise, this should really list the broken versions.
The other thing is that I find it incredibly dangerous to rely on
some config option to disable a feature that will absolutely eat your
data if it is broken. I'd rather see the whole BBM-L2 being behind an
option, and unconditionally check for b0rken CPUs.
Specially when it looks like there isn't a single CPU on the planet
that implemented the feature correctly... :-/
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH v1 2/5] arm64: Add BBM Level 2 cpu feature
2024-12-11 15:45 ` [RFC PATCH v1 2/5] arm64: Add BBM Level 2 cpu feature Mikołaj Lenczewski
@ 2024-12-11 21:02 ` Will Deacon
2024-12-13 16:17 ` Mikołaj Lenczewski
0 siblings, 1 reply; 12+ messages in thread
From: Will Deacon @ 2024-12-11 21:02 UTC (permalink / raw)
To: Mikołaj Lenczewski
Cc: catalin.marinas, corbet, maz, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui, linux-arm-kernel, liunx-doc,
linux-kernel, kvmarm
On Wed, Dec 11, 2024 at 03:45:03PM +0000, Mikołaj Lenczewski wrote:
> The Break-Before-Make cpu feature supports multiple levels (levels 0-2),
> and this commit adds a dedicated BBML2 cpufeature to test against
> support for.
>
> In supporting BBM level 2, we open ourselves up to potential TLB
> Conflict Abort Exceptions during expected execution, instead of only
> in exceptional circumstances. In the case of an abort, it is
> implementation defined at what stage the abort is generated, and
> the minimal set of required invalidations is also implementation
> defined. The maximal set of invalidations is to do a `tlbi vmalle1`
> or `tlbi vmalls12e1`, depending on the stage.
>
> Such aborts should not occur on Arm hardware, and were not seen in
> benchmarked systems, so unless performance concerns arise, implementing
> the abort handlers with the worst-case invalidations seems like an
> alright hack.
>
> Signed-off-by: Mikołaj Lenczewski <miko.lenczewski@arm.com>
> ---
> arch/arm64/include/asm/cpufeature.h | 14 ++++++++++++++
> arch/arm64/kernel/cpufeature.c | 7 +++++++
> arch/arm64/mm/fault.c | 27 ++++++++++++++++++++++++++-
> arch/arm64/tools/cpucaps | 1 +
> 4 files changed, 48 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 8b4e5a3cd24c..a9f2ac335392 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -866,6 +866,20 @@ static __always_inline bool system_supports_mpam_hcr(void)
> return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
> }
>
> +static inline bool system_supports_bbml2(void)
> +{
> + /* currently, BBM is only relied on by code touching the userspace page
> + * tables, and as such we are guaranteed that caps have been finalised.
> + *
> + * if later we want to use BBM for kernel mappings, particularly early
> + * in the kernel, this may return 0 even if BBML2 is actually supported,
> + * which means unnecessary break-before-make sequences, but is still
> + * correct
> + */
> +
> + return alternative_has_cap_unlikely(ARM64_HAS_BBML2);
> +}
> +
> int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
> bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
>
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 6ce71f444ed8..7cc94bd5da24 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -2917,6 +2917,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
> .matches = has_cpuid_feature,
> ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
> },
> + {
> + .desc = "BBM Level 2 Support",
> + .capability = ARM64_HAS_BBML2,
> + .type = ARM64_CPUCAP_SYSTEM_FEATURE,
> + .matches = has_cpuid_feature,
> + ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, BBM, 2)
> + },
> {
> .desc = "52-bit Virtual Addressing for KVM (LPA2)",
> .capability = ARM64_HAS_LPA2,
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index ef63651099a9..dc119358cbc1 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -844,6 +844,31 @@ static int do_tag_check_fault(unsigned long far, unsigned long esr,
> return 0;
> }
>
> +static int do_conflict_abort(unsigned long far, unsigned long esr,
> + struct pt_regs *regs)
> +{
> + if (!system_supports_bbml2())
> + return do_bad(far, esr, regs);
> +
> + /* if we receive a TLB conflict abort, we know that there are multiple
> + * TLB entries that translate the same address range. the minimum set
> + * of invalidations to clear these entries is implementation defined.
> + * the maximum set is defined as either tlbi(vmalls12e1) or tlbi(alle1).
> + *
> + * if el2 is enabled and stage 2 translation enabled, this may be
> + * raised as a stage 2 abort. if el2 is enabled but stage 2 translation
> + * disabled, or if el2 is disabled, it will be raised as a stage 1
> + * abort.
> + *
> + * local_flush_tlb_all() does a tlbi(vmalle1), which is enough to
> + * handle a stage 1 abort.
> + */
> +
> + local_flush_tlb_all();
> +
> + return 0;
> +}
Can we actually guarantee that we make it this far without taking another
abort? Given that I'm yet to see one of these things in the wild, I'm
fairly opposed to pretending that we can handle them. We'd be much better
off only violating BBM on CPUs that are known to handle the conflict
gracefully. Judging by your later patch, this is practically keyed off
the MIDR _anyway_...
Will
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH v1 2/5] arm64: Add BBM Level 2 cpu feature
2024-12-11 21:02 ` Will Deacon
@ 2024-12-13 16:17 ` Mikołaj Lenczewski
2024-12-13 22:34 ` Yang Shi
0 siblings, 1 reply; 12+ messages in thread
From: Mikołaj Lenczewski @ 2024-12-13 16:17 UTC (permalink / raw)
To: Will Deacon
Cc: catalin.marinas, corbet, maz, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui, linux-arm-kernel, liunx-doc,
linux-kernel, kvmarm
> > +static int do_conflict_abort(unsigned long far, unsigned long esr,
> > + struct pt_regs *regs)
> > +{
> > + if (!system_supports_bbml2())
> > + return do_bad(far, esr, regs);
> > +
> > + /* if we receive a TLB conflict abort, we know that there are multiple
> > + * TLB entries that translate the same address range. the minimum set
> > + * of invalidations to clear these entries is implementation defined.
> > + * the maximum set is defined as either tlbi(vmalls12e1) or tlbi(alle1).
> > + *
> > + * if el2 is enabled and stage 2 translation enabled, this may be
> > + * raised as a stage 2 abort. if el2 is enabled but stage 2 translation
> > + * disabled, or if el2 is disabled, it will be raised as a stage 1
> > + * abort.
> > + *
> > + * local_flush_tlb_all() does a tlbi(vmalle1), which is enough to
> > + * handle a stage 1 abort.
> > + */
> > +
> > + local_flush_tlb_all();
> > +
> > + return 0;
> > +}
>
> Can we actually guarantee that we make it this far without taking another
> abort? Given that I'm yet to see one of these things in the wild, I'm
> fairly opposed to pretending that we can handle them. We'd be much better
> off only violating BBM on CPUs that are known to handle the conflict
> gracefully. Judging by your later patch, this is practically keyed off
> the MIDR _anyway_...
>
> Will
Thanks for reviewing. Apologies for the delay in responding, and for
spam (replied instead of group-replied).
There should not be an option to take another fault while performing the
handler, as long as the mappings covering the fault handler table or any
code in this path are not screwed with. This is discussed further in the
resent patch series [1].
The MIDR revisions will be fixed. I was confused as to which revisions
were affected on an earlier version of the series, and had missed
updating them. The kconfig workarounds should be correct in this regard.
[1]: https://lore.kernel.org/all/084c5ada-51af-4c1a-b50a-4401e62ddbd6@arm.com/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH v1 3/5] arm64: Add errata and workarounds for systems with broken BBML2
2024-12-11 16:52 ` Marc Zyngier
@ 2024-12-13 16:21 ` Mikołaj Lenczewski
0 siblings, 0 replies; 12+ messages in thread
From: Mikołaj Lenczewski @ 2024-12-13 16:21 UTC (permalink / raw)
To: Marc Zyngier
Cc: catalin.marinas, will, corbet, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui, linux-arm-kernel, linux-doc,
linux-kernel, kvmarm
On Wed, Dec 11, 2024 at 04:52:49PM +0000, Marc Zyngier wrote:
> On Wed, 11 Dec 2024 15:45:04 +0000,
> Mikołaj Lenczewski <miko.lenczewski@arm.com> wrote:
> >
> > There are systems which claim support for BBML2, but whose
> > implementation of this support is broken. Add a Kconfig erratum for each
> > of these systems, and a cpufeature workaround that forces the supported
> > BBM level on these systems to 0.
> >
> > Signed-off-by: Mikołaj Lenczewski <miko.lenczewski@arm.com>
> > ---
> > Documentation/arch/arm64/silicon-errata.rst | 32 ++++
> > arch/arm64/Kconfig | 164 ++++++++++++++++++++
> > arch/arm64/kernel/cpufeature.c | 32 +++-
> > 3 files changed, 227 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > index 100570a048c5..9ef8418e8410 100644
> > --- a/arch/arm64/Kconfig
> > +++ b/arch/arm64/Kconfig
> > @@ -1127,6 +1127,170 @@ config ARM64_ERRATUM_3194386
> >
> > If unsure, say Y.
> >
> > +config ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
> > + bool
> > +
> > +config ARM64_ERRATUM_3696250
> > + bool "Neoverse-N2: workaround for broken BBM level 2 support"
> > + default y
> > + select ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT
> > + help
> > + Affected Neoverse-N2 cores (r0p0, r0p1, r0p2, r0p3) declare
>
> So you list a number of affected revisions...
>
> [...]
>
> > +static bool has_bbml2(const struct arm64_cpu_capabilities *entry,
> > + int scope)
> > +{
> > + if (IS_ENABLED(CONFIG_ARM64_WORKAROUND_BROKEN_BBML2_SUPPORT)) {
> > + static const struct midr_range broken_bbml2_list[] = {
> > + MIDR_ALL_VERSIONS(MIDR_CORTEX_A76),
> > + MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
> > + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
> > + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
> > + MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
> > + MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
> > + MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
> > + MIDR_ALL_VERSIONS(MIDR_CORTEX_X3),
> > + MIDR_ALL_VERSIONS(MIDR_CORTEX_X4),
> > + MIDR_ALL_VERSIONS(MIDR_CORTEX_X925),
> > + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
> > + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
> > + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1),
> > + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
> > + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3),
> > + {}
>
> ... and yet you flag all versions as broken? So which one is it? If it
> is really the case that all versions are broken, then the text should
> be simplified. Otherwise, this should really list the broken versions.
>
> The other thing is that I find it incredibly dangerous to rely on
> some config option to disable a feature that will absolutely eat your
> data if it is broken. I'd rather see the whole BBM-L2 being behind an
> option, and unconditionally check for b0rken CPUs.
>
> Specially when it looks like there isn't a single CPU on the planet
> that implemented the feature correctly... :-/
>
> Thanks,
>
> M.
>
> --
> Without deviation from the norm, progress is not possible.
Thanks for reviewing. Apologies for the delay in responding, and for
spam (replied instead of group-replied).
The workaround kconfig entries should be correct here. The MIDR
revisions will be fixed in the next respin.
I agree that having a BBML2 option and unconditionally guarding against
broken cpus is better, will make that change.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH v1 2/5] arm64: Add BBM Level 2 cpu feature
2024-12-13 16:17 ` Mikołaj Lenczewski
@ 2024-12-13 22:34 ` Yang Shi
2024-12-19 16:25 ` Will Deacon
0 siblings, 1 reply; 12+ messages in thread
From: Yang Shi @ 2024-12-13 22:34 UTC (permalink / raw)
To: Mikołaj Lenczewski, Will Deacon
Cc: catalin.marinas, corbet, maz, oliver.upton, joey.gouly,
suzuki.poulose, yuzenghui, linux-arm-kernel, liunx-doc,
linux-kernel, kvmarm
On 12/13/24 8:17 AM, Mikołaj Lenczewski wrote:
>>> +static int do_conflict_abort(unsigned long far, unsigned long esr,
>>> + struct pt_regs *regs)
>>> +{
>>> + if (!system_supports_bbml2())
>>> + return do_bad(far, esr, regs);
>>> +
>>> + /* if we receive a TLB conflict abort, we know that there are multiple
>>> + * TLB entries that translate the same address range. the minimum set
>>> + * of invalidations to clear these entries is implementation defined.
>>> + * the maximum set is defined as either tlbi(vmalls12e1) or tlbi(alle1).
>>> + *
>>> + * if el2 is enabled and stage 2 translation enabled, this may be
>>> + * raised as a stage 2 abort. if el2 is enabled but stage 2 translation
>>> + * disabled, or if el2 is disabled, it will be raised as a stage 1
>>> + * abort.
>>> + *
>>> + * local_flush_tlb_all() does a tlbi(vmalle1), which is enough to
>>> + * handle a stage 1 abort.
>>> + */
>>> +
>>> + local_flush_tlb_all();
>>> +
>>> + return 0;
>>> +}
>> Can we actually guarantee that we make it this far without taking another
>> abort? Given that I'm yet to see one of these things in the wild, I'm
>> fairly opposed to pretending that we can handle them. We'd be much better
>> off only violating BBM on CPUs that are known to handle the conflict
>> gracefully. Judging by your later patch, this is practically keyed off
>> the MIDR _anyway_...
>>
>> Will
Hi Mikołaj,
> Thanks for reviewing. Apologies for the delay in responding, and for
> spam (replied instead of group-replied).
>
> There should not be an option to take another fault while performing the
> handler, as long as the mappings covering the fault handler table or any
> code in this path are not screwed with. This is discussed further in the
> resent patch series [1].
Will lead me to this thread when we discussed about my series
(https://lore.kernel.org/lkml/20241211223034.GA17836@willie-the-truck/#t).
My series tried to use large mapping for kernel linear mapping when
rodata=full. The common part of the both series is BBM lv2 support. My
series depends on BBM lv2 to change page table block size when changing
permission for kernel linear mapping.
Handling TLB conflict should be ok for your usecase since the conflict
should just happen in user address space. But it may be not fine for my
usecase. At least the TLB conflict handler needs to depend on
CONFIG_VMAP_STACK otherwise the kernel stack pointer points to kernel
linear address space. I'm not quite sure whether there is any other
corner case which can trigger recursive abort in the path or not, maybe
bad stack handler? So Will suggested MIDR based lookup. IIUC, he
suggested just enable BBM lv2 support on the CPUs which can handle TLB
conflict gracefully. This should make our lives easier. But the downside
is maybe fewer CPUs can actually advertise BBM lv2 support.
Thanks,
Yang
> The MIDR revisions will be fixed. I was confused as to which revisions
> were affected on an earlier version of the series, and had missed
> updating them. The kconfig workarounds should be correct in this regard.
>
> [1]:https://lore.kernel.org/all/084c5ada-51af-4c1a-b50a-4401e62ddbd6@arm.com/
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH v1 2/5] arm64: Add BBM Level 2 cpu feature
2024-12-13 22:34 ` Yang Shi
@ 2024-12-19 16:25 ` Will Deacon
0 siblings, 0 replies; 12+ messages in thread
From: Will Deacon @ 2024-12-19 16:25 UTC (permalink / raw)
To: Yang Shi
Cc: Mikołaj Lenczewski, catalin.marinas, corbet, maz,
oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
linux-arm-kernel, liunx-doc, linux-kernel, kvmarm
On Fri, Dec 13, 2024 at 02:34:57PM -0800, Yang Shi wrote:
> On 12/13/24 8:17 AM, Mikołaj Lenczewski wrote:
> > > > +static int do_conflict_abort(unsigned long far, unsigned long esr,
> > > > + struct pt_regs *regs)
> > > > +{
> > > > + if (!system_supports_bbml2())
> > > > + return do_bad(far, esr, regs);
> > > > +
> > > > + /* if we receive a TLB conflict abort, we know that there are multiple
> > > > + * TLB entries that translate the same address range. the minimum set
> > > > + * of invalidations to clear these entries is implementation defined.
> > > > + * the maximum set is defined as either tlbi(vmalls12e1) or tlbi(alle1).
> > > > + *
> > > > + * if el2 is enabled and stage 2 translation enabled, this may be
> > > > + * raised as a stage 2 abort. if el2 is enabled but stage 2 translation
> > > > + * disabled, or if el2 is disabled, it will be raised as a stage 1
> > > > + * abort.
> > > > + *
> > > > + * local_flush_tlb_all() does a tlbi(vmalle1), which is enough to
> > > > + * handle a stage 1 abort.
> > > > + */
> > > > +
> > > > + local_flush_tlb_all();
> > > > +
> > > > + return 0;
> > > > +}
> > > Can we actually guarantee that we make it this far without taking another
> > > abort? Given that I'm yet to see one of these things in the wild, I'm
> > > fairly opposed to pretending that we can handle them. We'd be much better
> > > off only violating BBM on CPUs that are known to handle the conflict
> > > gracefully. Judging by your later patch, this is practically keyed off
> > > the MIDR _anyway_...
> > >
> > > Will
>
> Hi Mikołaj,
>
> > Thanks for reviewing. Apologies for the delay in responding, and for
> > spam (replied instead of group-replied).
> >
> > There should not be an option to take another fault while performing the
> > handler, as long as the mappings covering the fault handler table or any
> > code in this path are not screwed with. This is discussed further in the
> > resent patch series [1].
>
> Will lead me to this thread when we discussed about my series
> (https://lore.kernel.org/lkml/20241211223034.GA17836@willie-the-truck/#t).
> My series tried to use large mapping for kernel linear mapping when
> rodata=full. The common part of the both series is BBM lv2 support. My
> series depends on BBM lv2 to change page table block size when changing
> permission for kernel linear mapping.
>
> Handling TLB conflict should be ok for your usecase since the conflict
> should just happen in user address space. But it may be not fine for my
> usecase. At least the TLB conflict handler needs to depend on
> CONFIG_VMAP_STACK otherwise the kernel stack pointer points to kernel linear
> address space. I'm not quite sure whether there is any other corner case
> which can trigger recursive abort in the path or not, maybe bad stack
> handler? So Will suggested MIDR based lookup. IIUC, he suggested just enable
> BBM lv2 support on the CPUs which can handle TLB conflict gracefully. This
> should make our lives easier. But the downside is maybe fewer CPUs can
> actually advertise BBM lv2 support.
Since most of them seem to be broken anyway, I still think this (having
an allowlist and not handling the conflict abort in the kernel) is the
right approach.
Will
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-12-19 16:27 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-11 15:45 [RFC PATCH v1 0/5] Initial BBML2 support for contpte_convert() Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 1/5] arm64: Add TLB Conflict Abort Exception handler to KVM Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 2/5] arm64: Add BBM Level 2 cpu feature Mikołaj Lenczewski
2024-12-11 21:02 ` Will Deacon
2024-12-13 16:17 ` Mikołaj Lenczewski
2024-12-13 22:34 ` Yang Shi
2024-12-19 16:25 ` Will Deacon
2024-12-11 15:45 ` [RFC PATCH v1 3/5] arm64: Add errata and workarounds for systems with broken BBML2 Mikołaj Lenczewski
2024-12-11 16:52 ` Marc Zyngier
2024-12-13 16:21 ` Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 4/5] arm64/mm: Delay tlbi in contpte_convert() under BBML2 Mikołaj Lenczewski
2024-12-11 15:45 ` [RFC PATCH v1 5/5] arm64/mm: Elide " Mikołaj Lenczewski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).