summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorD Scott Phillips <scott@os.amperecomputing.com>2026-07-14 16:11:58 -0700
committerMarc Zyngier <maz@kernel.org>2026-07-21 11:19:00 +0100
commit8a570b19b4b16a8a3b5ffa2b332bd5613110b2d8 (patch)
treeef4c5462bcead568f99bd60a9253b2aa2dfadff2
parent1590cf0329716306e948a8fc29f1d3ee87d3989f (diff)
KVM: arm64: vgic: Avoid double-deactivate of IRQs in the nested context
In the nested state, the physical interrupt has already been deactivated through the HW bit in the LR. The extra deactivation would be harmless but can hit an errata case on AmpereOne, so avoid it here. On AmpereOne, deactivating a physical interrupt through ICC_DIR_EL1 or ICC_EOIR1_EL1 (depending on EOImode) which is not active, but is the highest priority pending interrupt causes the cpu to lose the interrupt pending state and also prevents the delivery of future interrupts. Fixes: 6dd333c8942b2 ("KVM: arm64: GICv3: nv: Plug L1 LR sync into deactivation primitive") Signed-off-by: D Scott Phillips <scott@os.amperecomputing.com> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/linux-arm-kernel/20260710222128.416581-1-scott@os.amperecomputing.com/ Link: https://patch.msgid.link/20260714231158.496808-1-scott@os.amperecomputing.com Signed-off-by: Marc Zyngier <maz@kernel.org>
-rw-r--r--Documentation/arch/arm64/silicon-errata.rst4
-rw-r--r--arch/arm64/kvm/vgic/vgic-v3.c8
2 files changed, 11 insertions, 1 deletions
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index 014aa1c215a1..88b4aa45a206 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -55,10 +55,14 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| Ampere | AmpereOne | AC03_CPU_38 | AMPERE_ERRATUM_AC03_CPU_38 |
+----------------+-----------------+-----------------+-----------------------------+
+| Ampere | AmpereOne | AC03_CPU_57 | N/A |
++----------------+-----------------+-----------------+-----------------------------+
| Ampere | AmpereOne AC04 | AC04_CPU_10 | AMPERE_ERRATUM_AC03_CPU_38 |
+----------------+-----------------+-----------------+-----------------------------+
| Ampere | AmpereOne AC04 | AC04_CPU_23 | AMPERE_ERRATUM_AC04_CPU_23 |
+----------------+-----------------+-----------------+-----------------------------+
+| Ampere | AmpereOne AC04 | AC04_CPU_29 | N/A |
++----------------+-----------------+-----------------+-----------------------------+
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A510 | #2457168 | ARM64_ERRATUM_2457168 |
+----------------+-----------------+-----------------+-----------------------------+
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index 9e841e7afd4a..7aa417440f6a 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -275,7 +275,13 @@ void vgic_v3_deactivate(struct kvm_vcpu *vcpu, u64 val)
lr = vgic_v3_compute_lr(vcpu, irq) & ~ICH_LR_ACTIVE_BIT;
}
- if (lr & ICH_LR_HW)
+ /*
+ * In the nested state, the irq has already been deactivated via the HW
+ * bit in the LR. Deactivating again would be harmless except AmpereOne
+ * errata AC03_CPU_57, AC04_CPU_29 could cause irq delivery to break if
+ * the deactivation hits the highest priority pending irq.
+ */
+ if ((lr & ICH_LR_HW) && !vgic_state_is_nested(vcpu))
vgic_v3_deactivate_phys(FIELD_GET(ICH_LR_PHYS_ID_MASK, lr));
vgic_v3_fold_lr(vcpu, lr);