Skip to content

Commit ca71228

Browse files
author
Marc Zyngier
committed
arm64: KVM: Always set ICH_HCR_EL2.EN if GICv4 is enabled
The normal interrupt flow is not to enable the vgic when no virtual interrupt is to be injected (i.e. the LRs are empty). But when a guest is likely to use GICv4 for LPIs, we absolutely need to switch it on at all times. Otherwise, VLPIs only get delivered when there is something in the LRs, which doesn't happen very often. Reported-by: Nianyao Tang <[email protected]> Tested-by: Shameerali Kolothum Thodi <[email protected]> Signed-off-by: Marc Zyngier <[email protected]>
1 parent ebff0b0 commit ca71228

File tree

2 files changed

+12
-6
lines changed

2 files changed

+12
-6
lines changed

virt/kvm/arm/hyp/vgic-v3-sr.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
222222
}
223223
}
224224

225-
if (used_lrs) {
225+
if (used_lrs || cpu_if->its_vpe.its_vm) {
226226
int i;
227227
u32 elrsr;
228228

@@ -247,7 +247,7 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
247247
u64 used_lrs = vcpu->arch.vgic_cpu.used_lrs;
248248
int i;
249249

250-
if (used_lrs) {
250+
if (used_lrs || cpu_if->its_vpe.its_vm) {
251251
write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
252252

253253
for (i = 0; i < used_lrs; i++)

virt/kvm/arm/vgic/vgic.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -867,15 +867,21 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
867867
* either observe the new interrupt before or after doing this check,
868868
* and introducing additional synchronization mechanism doesn't change
869869
* this.
870+
*
871+
* Note that we still need to go through the whole thing if anything
872+
* can be directly injected (GICv4).
870873
*/
871-
if (list_empty(&vcpu->arch.vgic_cpu.ap_list_head))
874+
if (list_empty(&vcpu->arch.vgic_cpu.ap_list_head) &&
875+
!vgic_supports_direct_msis(vcpu->kvm))
872876
return;
873877

874878
DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
875879

876-
raw_spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
877-
vgic_flush_lr_state(vcpu);
878-
raw_spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
880+
if (!list_empty(&vcpu->arch.vgic_cpu.ap_list_head)) {
881+
raw_spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
882+
vgic_flush_lr_state(vcpu);
883+
raw_spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
884+
}
879885

880886
if (can_access_vgic_from_kernel())
881887
vgic_restore_state(vcpu);

0 commit comments

Comments
 (0)