From: Marc Zyngier <maz@kernel.org>
To: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
kvm@vger.kernel.org
Cc: Joey Gouly <joey.gouly@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Oliver Upton <oupton@kernel.org>,
Zenghui Yu <yuzenghui@huawei.com>,
Christoffer Dall <christoffer.dall@arm.com>,
Volodymyr Babchuk <Volodymyr_Babchuk@epam.com>,
Yao Yuan <yaoyuan@linux.alibaba.com>
Subject: [PATCH v2 05/45] KVM: arm64: GICv3: Detect and work around the lack of ICV_DIR_EL1 trapping
Date: Sun, 9 Nov 2025 17:15:39 +0000 [thread overview]
Message-ID: <20251109171619.1507205-6-maz@kernel.org> (raw)
In-Reply-To: <20251109171619.1507205-1-maz@kernel.org>
A long time ago, an unsuspecting architect forgot to add a trap
bit for ICV_DIR_EL1 in ICH_HCR_EL2. Which was unfortunate, but
what's a bit of spec between friends? Thankfully, this was fixed
in a later revision, and ARM "deprecates" the lack of trapping
ability.
Unfortuantely, a few (billion) CPUs went out with that defect,
anything ARMv8.0 from ARM, give or take. And on these CPUs,
you can't trap DIR on its own, full stop.
As the next best thing, we can trap everything in the common group,
which is a tad expensive, but hey ho, that's what you get. You can
otherwise recycle the HW in the neaby bin.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/include/asm/virt.h | 7 ++++-
arch/arm64/kernel/cpufeature.c | 52 ++++++++++++++++++++++++++++++++++
arch/arm64/kernel/hyp-stub.S | 5 ++++
arch/arm64/kvm/vgic/vgic-v3.c | 3 ++
arch/arm64/tools/cpucaps | 1 +
5 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index aa280f356b96a..8eb63d3294974 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -40,8 +40,13 @@
*/
#define HVC_FINALISE_EL2 3
+/*
+ * HVC_GET_ICH_VTR_EL2 - Retrieve the ICH_VTR_EL2 value
+ */
+#define HVC_GET_ICH_VTR_EL2 4
+
/* Max number of HYP stub hypercalls */
-#define HVC_STUB_HCALL_NR 4
+#define HVC_STUB_HCALL_NR 5
/* Error returned when an invalid stub number is passed into x0 */
#define HVC_STUB_ERR 0xbadca11
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 5ed401ff79e3e..5de51cb1b8fe2 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2303,6 +2303,49 @@ static bool has_gic_prio_relaxed_sync(const struct arm64_cpu_capabilities *entry
}
#endif
+static bool can_trap_icv_dir_el1(const struct arm64_cpu_capabilities *entry,
+ int scope)
+{
+ static const struct midr_range has_vgic_v3[] = {
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_PRO),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_PRO),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_MAX),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_MAX),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_PRO),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_PRO),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_MAX),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_MAX),
+ {},
+ };
+ struct arm_smccc_res res = {};
+
+ BUILD_BUG_ON(ARM64_HAS_ICH_HCR_EL2_TDIR <= ARM64_HAS_GICV3_CPUIF);
+ BUILD_BUG_ON(ARM64_HAS_ICH_HCR_EL2_TDIR <= ARM64_HAS_GICV5_LEGACY);
+ if (!cpus_have_cap(ARM64_HAS_GICV3_CPUIF) &&
+ !is_midr_in_range_list(has_vgic_v3))
+ return false;
+
+ if (!is_hyp_mode_available())
+ return false;
+
+ if (cpus_have_cap(ARM64_HAS_GICV5_LEGACY))
+ return true;
+
+ if (is_kernel_in_hyp_mode())
+ res.a1 = read_sysreg_s(SYS_ICH_VTR_EL2);
+ else
+ arm_smccc_1_1_hvc(HVC_GET_ICH_VTR_EL2, &res);
+
+ if (res.a0 == HVC_STUB_ERR)
+ return false;
+
+ return res.a1 & ICH_VTR_EL2_TDS;
+}
+
#ifdef CONFIG_ARM64_BTI
static void bti_enable(const struct arm64_cpu_capabilities *__unused)
{
@@ -2814,6 +2857,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.matches = has_gic_prio_relaxed_sync,
},
#endif
+ {
+ /*
+ * Depends on having GICv3
+ */
+ .desc = "ICV_DIR_EL1 trapping",
+ .capability = ARM64_HAS_ICH_HCR_EL2_TDIR,
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .matches = can_trap_icv_dir_el1,
+ },
#ifdef CONFIG_ARM64_E0PD
{
.desc = "E0PD",
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index 36e2d26b54f5c..085bc9972f6bb 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -54,6 +54,11 @@ SYM_CODE_START_LOCAL(elx_sync)
1: cmp x0, #HVC_FINALISE_EL2
b.eq __finalise_el2
+ cmp x0, #HVC_GET_ICH_VTR_EL2
+ b.ne 2f
+ mrs_s x1, SYS_ICH_VTR_EL2
+ b 9f
+
2: cmp x0, #HVC_SOFT_RESTART
b.ne 3f
mov x0, x2
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index 236d0beef561d..473252c98367b 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -648,6 +648,9 @@ void noinstr kvm_compute_ich_hcr_trap_bits(struct alt_instr *alt,
dir_trap = true;
}
+ if (!cpus_have_cap(ARM64_HAS_ICH_HCR_EL2_TDIR))
+ common_trap = true;
+
if (group0_trap)
hcr |= ICH_HCR_EL2_TALL0;
if (group1_trap)
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 1b32c1232d28d..116d1a7b688cb 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -40,6 +40,7 @@ HAS_GICV5_CPUIF
HAS_GICV5_LEGACY
HAS_GIC_PRIO_MASKING
HAS_GIC_PRIO_RELAXED_SYNC
+HAS_ICH_HCR_EL2_TDIR
HAS_HCR_NV1
HAS_HCX
HAS_LDAPR
--
2.47.3
next prev parent reply other threads:[~2025-11-09 17:17 UTC|newest]
Thread overview: 83+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-09 17:15 [PATCH v2 00/45] KVM: arm64: Add LR overflow infrastructure Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 01/45] irqchip/gic: Add missing GICH_HCR control bits Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 02/45] irqchip/gic: Expose CPU interface VA to KVM Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 03/45] irqchip/apple-aic: Spit out ICH_MISR_EL2 value on spurious vGIC MI Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 04/45] KVM: arm64: Turn vgic-v3 errata traps into a patched-in constant Marc Zyngier
2025-11-10 10:40 ` Suzuki K Poulose
2025-11-10 11:47 ` Marc Zyngier
2025-11-11 23:53 ` Oliver Upton
2025-11-13 9:52 ` Marek Szyprowski
2025-11-13 10:56 ` Marc Zyngier
2025-11-13 11:04 ` Marek Szyprowski
2025-11-13 11:23 ` Joey Gouly
2025-11-13 11:42 ` Marc Zyngier
2025-11-13 10:59 ` Marc Zyngier
2025-11-13 11:20 ` Marek Szyprowski
2025-11-13 18:01 ` Mark Brown
2025-11-14 9:37 ` Marc Zyngier
2025-11-09 17:15 ` Marc Zyngier [this message]
2025-11-13 14:33 ` [PATCH v2 05/45] KVM: arm64: GICv3: Detect and work around the lack of ICV_DIR_EL1 trapping Mark Brown
2025-11-13 18:15 ` Marc Zyngier
2025-11-13 19:06 ` Mark Brown
2025-11-13 20:10 ` Marc Zyngier
2025-11-13 21:59 ` Oliver Upton
2025-11-09 17:15 ` [PATCH v2 06/45] KVM: arm64: Repack struct vgic_irq fields Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 07/45] KVM: arm64: Add tracking of vgic_irq being present in a LR Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 08/45] KVM: arm64: Add LR overflow handling documentation Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 09/45] KVM: arm64: GICv3: Drop LPI active state when folding LRs Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 10/45] KVM: arm64: GICv3: Preserve EOIcount on exit Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 11/45] KVM: arm64: GICv3: Decouple ICH_HCR_EL2 programming from LRs Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 12/45] KVM: arm64: GICv3: Extract LR folding primitive Marc Zyngier
2025-11-10 9:01 ` Yao Yuan
2025-11-10 9:18 ` Marc Zyngier
2025-11-10 9:48 ` Yao Yuan
2025-11-09 17:15 ` [PATCH v2 13/45] KVM: arm64: GICv3: Extract LR computing primitive Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 14/45] KVM: arm64: GICv2: Preserve EOIcount on exit Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 15/45] KVM: arm64: GICv2: Decouple GICH_HCR programming from LRs being loaded Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 16/45] KVM: arm64: GICv2: Extract LR folding primitive Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 17/45] KVM: arm64: GICv2: Extract LR computing primitive Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 18/45] KVM: arm64: Compute vgic state irrespective of the number of interrupts Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 19/45] KVM: arm64: Eagerly save VMCR on exit Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 20/45] KVM: arm64: Revamp vgic maintenance interrupt configuration Marc Zyngier
2025-11-12 0:08 ` Oliver Upton
2025-11-12 8:33 ` Marc Zyngier
2025-11-12 8:45 ` Oliver Upton
2025-11-12 9:56 ` Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 21/45] KVM: arm64: Turn kvm_vgic_vcpu_enable() into kvm_vgic_vcpu_reset() Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 22/45] KVM: arm64: Make vgic_target_oracle() globally available Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 23/45] KVM: arm64: Invert ap_list sorting to push active interrupts out Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 24/45] KVM: arm64: Move undeliverable interrupts to the end of ap_list Marc Zyngier
2025-11-09 17:15 ` [PATCH v2 25/45] KVM: arm64: Use MI to detect groups being enabled/disabled Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 26/45] KVM: arm64: GICv3: Handle LR overflow when EOImode==0 Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 27/45] KVM: arm64: GICv3: Handle deactivation via ICV_DIR_EL1 traps Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 28/45] KVM: arm64: GICv3: Add GICv2 SGI handling to deactivation primitive Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 29/45] KVM: arm64: GICv3: Set ICH_HCR_EL2.TDIR when interrupts overflow LR capacity Marc Zyngier
2025-11-14 14:20 ` Fuad Tabba
2025-11-14 15:02 ` Marc Zyngier
2025-11-14 15:53 ` Fuad Tabba
2025-11-14 17:41 ` Marc Zyngier
2025-11-17 8:22 ` Fuad Tabba
2025-11-17 11:56 ` Marc Zyngier
2025-11-24 11:52 ` Mark Brown
2025-11-24 13:06 ` Marc Zyngier
2025-11-24 13:23 ` Mark Brown
2025-11-24 13:40 ` Marc Zyngier
2025-11-24 14:12 ` Marc Zyngier
2025-11-24 15:06 ` Mark Brown
2025-11-09 17:16 ` [PATCH v2 30/45] KVM: arm64: GICv3: Add SPI tracking to handle asymmetric deactivation Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 31/45] KVM: arm64: GICv3: Handle in-LR deactivation when possible Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 32/45] KVM: arm64: GICv3: Avoid broadcast kick on CPUs lacking TDIR Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 33/45] KVM: arm64: GICv2: Handle LR overflow when EOImode==0 Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 34/45] KVM: arm64: GICv2: Handle deactivation via GICV_DIR traps Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 35/45] KVM: arm64: GICv2: Always trap GICV_DIR register Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 36/45] KVM: arm64: selftests: gic_v3: Add irq group setting helper Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 37/45] KVM: arm64: selftests: gic_v3: Disable Group-0 interrupts by default Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 38/45] KVM: arm64: selftests: vgic_irq: Fix GUEST_ASSERT_IAR_EMPTY() helper Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 39/45] KVM: arm64: selftests: vgic_irq: Change configuration before enabling interrupt Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 40/45] KVM: arm64: selftests: vgic_irq: Exclude timer-controlled interrupts Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 41/45] KVM: arm64: selftests: vgic_irq: Remove LR-bound limitation Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 42/45] KVM: arm64: selftests: vgic_irq: Perform EOImode==1 deactivation in ack order Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 43/45] KVM: arm64: selftests: vgic_irq: Add asymmetric SPI deaectivation test Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 44/45] KVM: arm64: selftests: vgic_irq: Add Group-0 enable test Marc Zyngier
2025-11-09 17:16 ` [PATCH v2 45/45] KVM: arm64: selftests: vgic_irq: Add timer deactivation test Marc Zyngier
2025-11-12 9:13 ` [PATCH v2 00/45] KVM: arm64: Add LR overflow infrastructure Oliver Upton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251109171619.1507205-6-maz@kernel.org \
--to=maz@kernel.org \
--cc=Volodymyr_Babchuk@epam.com \
--cc=christoffer.dall@arm.com \
--cc=joey.gouly@arm.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=oupton@kernel.org \
--cc=suzuki.poulose@arm.com \
--cc=yaoyuan@linux.alibaba.com \
--cc=yuzenghui@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).