summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2025-11-20 17:25:06 +0000
committerOliver Upton <oupton@kernel.org>2025-11-24 14:29:12 -0800
commita00c88ac1f90992e618cf4737e2d1c551c13aed6 (patch)
tree84ba4b7b017d67725663d02935f5710e4f9ae93a
parent5ceb3dac80229684c8e57993f12106cbad23f7ac (diff)
KVM: arm64: GICv2: Decouple GICH_HCR programming from LRs being loaded
Not programming GICH_HCR while no LRs are populated is a bit of an issue, as we otherwise don't see any maintenance interrupt when the guest interacts with the LRs. Decouple the two and always program the control register, even when we don't have to touch the LRs. This is very similar to what we are already doing for GICv3. Tested-by: Fuad Tabba <tabba@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Tested-by: Mark Brown <broonie@kernel.org> Link: https://msgid.link/20251120172540.2267180-17-maz@kernel.org Signed-off-by: Oliver Upton <oupton@kernel.org>
-rw-r--r--arch/arm64/kvm/vgic/vgic-v2.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/arch/arm64/kvm/vgic/vgic-v2.c b/arch/arm64/kvm/vgic/vgic-v2.c
index 5cfbe5898342..a0d803c5b08a 100644
--- a/arch/arm64/kvm/vgic/vgic-v2.c
+++ b/arch/arm64/kvm/vgic/vgic-v2.c
@@ -430,22 +430,25 @@ static void save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
void vgic_v2_save_state(struct kvm_vcpu *vcpu)
{
+ struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
void __iomem *base = kvm_vgic_global_state.vctrl_base;
u64 used_lrs = vcpu->arch.vgic_cpu.vgic_v2.used_lrs;
if (!base)
return;
- if (used_lrs) {
- if (vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr & GICH_HCR_LRENPIE) {
- u32 val = readl_relaxed(base + GICH_HCR);
- vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr &= ~GICH_HCR_EOICOUNT;
- vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr |= val & GICH_HCR_EOICOUNT;
- }
+ if (used_lrs)
save_lrs(vcpu, base);
- writel_relaxed(0, base + GICH_HCR);
+
+ if (cpu_if->vgic_hcr & GICH_HCR_LRENPIE) {
+ u32 val = readl_relaxed(base + GICH_HCR);
+
+ cpu_if->vgic_hcr &= ~GICH_HCR_EOICOUNT;
+ cpu_if->vgic_hcr |= val & GICH_HCR_EOICOUNT;
}
+
+ writel_relaxed(0, base + GICH_HCR);
}
void vgic_v2_restore_state(struct kvm_vcpu *vcpu)
@@ -458,13 +461,10 @@ void vgic_v2_restore_state(struct kvm_vcpu *vcpu)
if (!base)
return;
- if (used_lrs) {
- writel_relaxed(cpu_if->vgic_hcr, base + GICH_HCR);
- for (i = 0; i < used_lrs; i++) {
- writel_relaxed(cpu_if->vgic_lr[i],
- base + GICH_LR0 + (i * 4));
- }
- }
+ writel_relaxed(cpu_if->vgic_hcr, base + GICH_HCR);
+
+ for (i = 0; i < used_lrs; i++)
+ writel_relaxed(cpu_if->vgic_lr[i], base + GICH_LR0 + (i * 4));
}
void vgic_v2_load(struct kvm_vcpu *vcpu)