Skip to content

Commit 3134cc8

Browse files
author
Marc Zyngier
committed
KVM: arm64: vgic: Resample HW pending state on deactivation
When a mapped level interrupt (a timer, for example) is deactivated by the guest, the corresponding host interrupt is equally deactivated. However, the fate of the pending state still needs to be dealt with in SW. This is specially true when the interrupt was in the active+pending state in the virtual distributor at the point where the guest was entered. On exit, the pending state is potentially stale (the guest may have put the interrupt in a non-pending state). If we don't do anything, the interrupt will be spuriously injected in the guest. Although this shouldn't have any ill effect (spurious interrupts are always possible), we can improve the emulation by detecting the deactivation-while-pending case and resample the interrupt. While we're at it, move the logic into a common helper that can be shared between the two GIC implementations. Fixes: e40cc57 ("KVM: arm/arm64: vgic: Support level-triggered mapped interrupts") Reported-by: Raghavendra Rao Ananta <[email protected]> Tested-by: Raghavendra Rao Ananta <[email protected]> Reviewed-by: Oliver Upton <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected]
1 parent b9a5194 commit 3134cc8

File tree

4 files changed

+50
-62
lines changed

4 files changed

+50
-62
lines changed

arch/arm64/kvm/vgic/vgic-v2.c

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
6060
u32 val = cpuif->vgic_lr[lr];
6161
u32 cpuid, intid = val & GICH_LR_VIRTUALID;
6262
struct vgic_irq *irq;
63+
bool deactivated;
6364

6465
/* Extract the source vCPU id from the LR */
6566
cpuid = val & GICH_LR_PHYSID_CPUID;
@@ -75,7 +76,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
7576

7677
raw_spin_lock(&irq->irq_lock);
7778

78-
/* Always preserve the active bit */
79+
/* Always preserve the active bit, note deactivation */
80+
deactivated = irq->active && !(val & GICH_LR_ACTIVE_BIT);
7981
irq->active = !!(val & GICH_LR_ACTIVE_BIT);
8082

8183
if (irq->active && vgic_irq_is_sgi(intid))
@@ -96,36 +98,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
9698
if (irq->config == VGIC_CONFIG_LEVEL && !(val & GICH_LR_STATE))
9799
irq->pending_latch = false;
98100

99-
/*
100-
* Level-triggered mapped IRQs are special because we only
101-
* observe rising edges as input to the VGIC.
102-
*
103-
* If the guest never acked the interrupt we have to sample
104-
* the physical line and set the line level, because the
105-
* device state could have changed or we simply need to
106-
* process the still pending interrupt later.
107-
*
108-
* If this causes us to lower the level, we have to also clear
109-
* the physical active state, since we will otherwise never be
110-
* told when the interrupt becomes asserted again.
111-
*
112-
* Another case is when the interrupt requires a helping hand
113-
* on deactivation (no HW deactivation, for example).
114-
*/
115-
if (vgic_irq_is_mapped_level(irq)) {
116-
bool resample = false;
117-
118-
if (val & GICH_LR_PENDING_BIT) {
119-
irq->line_level = vgic_get_phys_line_level(irq);
120-
resample = !irq->line_level;
121-
} else if (vgic_irq_needs_resampling(irq) &&
122-
!(irq->active || irq->pending_latch)) {
123-
resample = true;
124-
}
125-
126-
if (resample)
127-
vgic_irq_set_phys_active(irq, false);
128-
}
101+
/* Handle resampling for mapped interrupts if required */
102+
vgic_irq_handle_resampling(irq, deactivated, val & GICH_LR_PENDING_BIT);
129103

130104
raw_spin_unlock(&irq->irq_lock);
131105
vgic_put_irq(vcpu->kvm, irq);

arch/arm64/kvm/vgic/vgic-v3.c

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
4646
u32 intid, cpuid;
4747
struct vgic_irq *irq;
4848
bool is_v2_sgi = false;
49+
bool deactivated;
4950

5051
cpuid = val & GICH_LR_PHYSID_CPUID;
5152
cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
@@ -68,7 +69,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
6869

6970
raw_spin_lock(&irq->irq_lock);
7071

71-
/* Always preserve the active bit */
72+
/* Always preserve the active bit, note deactivation */
73+
deactivated = irq->active && !(val & ICH_LR_ACTIVE_BIT);
7274
irq->active = !!(val & ICH_LR_ACTIVE_BIT);
7375

7476
if (irq->active && is_v2_sgi)
@@ -89,36 +91,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
8991
if (irq->config == VGIC_CONFIG_LEVEL && !(val & ICH_LR_STATE))
9092
irq->pending_latch = false;
9193

92-
/*
93-
* Level-triggered mapped IRQs are special because we only
94-
* observe rising edges as input to the VGIC.
95-
*
96-
* If the guest never acked the interrupt we have to sample
97-
* the physical line and set the line level, because the
98-
* device state could have changed or we simply need to
99-
* process the still pending interrupt later.
100-
*
101-
* If this causes us to lower the level, we have to also clear
102-
* the physical active state, since we will otherwise never be
103-
* told when the interrupt becomes asserted again.
104-
*
105-
* Another case is when the interrupt requires a helping hand
106-
* on deactivation (no HW deactivation, for example).
107-
*/
108-
if (vgic_irq_is_mapped_level(irq)) {
109-
bool resample = false;
110-
111-
if (val & ICH_LR_PENDING_BIT) {
112-
irq->line_level = vgic_get_phys_line_level(irq);
113-
resample = !irq->line_level;
114-
} else if (vgic_irq_needs_resampling(irq) &&
115-
!(irq->active || irq->pending_latch)) {
116-
resample = true;
117-
}
118-
119-
if (resample)
120-
vgic_irq_set_phys_active(irq, false);
121-
}
94+
/* Handle resampling for mapped interrupts if required */
95+
vgic_irq_handle_resampling(irq, deactivated, val & ICH_LR_PENDING_BIT);
12296

12397
raw_spin_unlock(&irq->irq_lock);
12498
vgic_put_irq(vcpu->kvm, irq);

arch/arm64/kvm/vgic/vgic.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,3 +1021,41 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
10211021

10221022
return map_is_active;
10231023
}
1024+
1025+
/*
1026+
* Level-triggered mapped IRQs are special because we only observe rising
1027+
* edges as input to the VGIC.
1028+
*
1029+
* If the guest never acked the interrupt we have to sample the physical
1030+
* line and set the line level, because the device state could have changed
1031+
* or we simply need to process the still pending interrupt later.
1032+
*
1033+
* We could also have entered the guest with the interrupt active+pending.
1034+
* On the next exit, we need to re-evaluate the pending state, as it could
1035+
* otherwise result in a spurious interrupt by injecting a now potentially
1036+
* stale pending state.
1037+
*
1038+
* If this causes us to lower the level, we have to also clear the physical
1039+
* active state, since we will otherwise never be told when the interrupt
1040+
* becomes asserted again.
1041+
*
1042+
* Another case is when the interrupt requires a helping hand on
1043+
* deactivation (no HW deactivation, for example).
1044+
*/
1045+
void vgic_irq_handle_resampling(struct vgic_irq *irq,
1046+
bool lr_deactivated, bool lr_pending)
1047+
{
1048+
if (vgic_irq_is_mapped_level(irq)) {
1049+
bool resample = false;
1050+
1051+
if (unlikely(vgic_irq_needs_resampling(irq))) {
1052+
resample = !(irq->active || irq->pending_latch);
1053+
} else if (lr_pending || (lr_deactivated && irq->line_level)) {
1054+
irq->line_level = vgic_get_phys_line_level(irq);
1055+
resample = !irq->line_level;
1056+
}
1057+
1058+
if (resample)
1059+
vgic_irq_set_phys_active(irq, false);
1060+
}
1061+
}

arch/arm64/kvm/vgic/vgic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ void vgic_irq_set_phys_active(struct vgic_irq *irq, bool active);
169169
bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
170170
unsigned long flags);
171171
void vgic_kick_vcpus(struct kvm *kvm);
172+
void vgic_irq_handle_resampling(struct vgic_irq *irq,
173+
bool lr_deactivated, bool lr_pending);
172174

173175
int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
174176
phys_addr_t addr, phys_addr_t alignment);

0 commit comments

Comments
 (0)