summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2018-03-09 09:59:40 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2018-03-26 05:54:23 -0400
commit67b5b673ad4d469186edddecfe59909a9fd4b643 (patch)
tree0fa4a9317d42a103930ef436963256d312ad5935 /virt
parentf9f5dc19509bbef6f5e675346f1a7d7b846bdb12 (diff)
KVM: arm/arm64: vgic: Disallow Active+Pending for level interrupts
It was recently reported that VFIO mediated devices, and anything that VFIO exposes as level interrupts, do no strictly follow the expected logic of such interrupts as it only lowers the input line when the guest has EOId the interrupt at the GIC level, rather than when it Acked the interrupt at the device level. THe GIC's Active+Pending state is fundamentally incompatible with this behaviour, as it prevents KVM from observing the EOI, and in turn results in VFIO never dropping the line. This results in an interrupt storm in the guest, which it really never expected. As we cannot really change VFIO to follow the strict rules of level signalling, let's forbid the A+P state altogether, as it is in the end only an optimization. It ensures that we will transition via an invalid state, which we can use to notify VFIO of the EOI. Reviewed-by: Eric Auger <eric.auger@redhat.com> Tested-by: Eric Auger <eric.auger@redhat.com> Tested-by: Shunyong Yang <shunyong.yang@hxt-semitech.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic/vgic-v2.c54
-rw-r--r--virt/kvm/arm/vgic/vgic-v3.c54
2 files changed, 60 insertions, 48 deletions
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 8327ea932aea..45aa433f018f 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -105,12 +105,9 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
105 105
106 /* 106 /*
107 * Clear soft pending state when level irqs have been acked. 107 * Clear soft pending state when level irqs have been acked.
108 * Always regenerate the pending state.
109 */ 108 */
110 if (irq->config == VGIC_CONFIG_LEVEL) { 109 if (irq->config == VGIC_CONFIG_LEVEL && !(val & GICH_LR_STATE))
111 if (!(val & GICH_LR_PENDING_BIT)) 110 irq->pending_latch = false;
112 irq->pending_latch = false;
113 }
114 111
115 /* 112 /*
116 * Level-triggered mapped IRQs are special because we only 113 * Level-triggered mapped IRQs are special because we only
@@ -153,8 +150,35 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
153void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr) 150void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
154{ 151{
155 u32 val = irq->intid; 152 u32 val = irq->intid;
153 bool allow_pending = true;
154
155 if (irq->active)
156 val |= GICH_LR_ACTIVE_BIT;
157
158 if (irq->hw) {
159 val |= GICH_LR_HW;
160 val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
161 /*
162 * Never set pending+active on a HW interrupt, as the
163 * pending state is kept at the physical distributor
164 * level.
165 */
166 if (irq->active)
167 allow_pending = false;
168 } else {
169 if (irq->config == VGIC_CONFIG_LEVEL) {
170 val |= GICH_LR_EOI;
156 171
157 if (irq_is_pending(irq)) { 172 /*
173 * Software resampling doesn't work very well
174 * if we allow P+A, so let's not do that.
175 */
176 if (irq->active)
177 allow_pending = false;
178 }
179 }
180
181 if (allow_pending && irq_is_pending(irq)) {
158 val |= GICH_LR_PENDING_BIT; 182 val |= GICH_LR_PENDING_BIT;
159 183
160 if (irq->config == VGIC_CONFIG_EDGE) 184 if (irq->config == VGIC_CONFIG_EDGE)
@@ -171,24 +195,6 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
171 } 195 }
172 } 196 }
173 197
174 if (irq->active)
175 val |= GICH_LR_ACTIVE_BIT;
176
177 if (irq->hw) {
178 val |= GICH_LR_HW;
179 val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
180 /*
181 * Never set pending+active on a HW interrupt, as the
182 * pending state is kept at the physical distributor
183 * level.
184 */
185 if (irq->active && irq_is_pending(irq))
186 val &= ~GICH_LR_PENDING_BIT;
187 } else {
188 if (irq->config == VGIC_CONFIG_LEVEL)
189 val |= GICH_LR_EOI;
190 }
191
192 /* 198 /*
193 * Level-triggered mapped IRQs are special because we only observe 199 * Level-triggered mapped IRQs are special because we only observe
194 * rising edges as input to the VGIC. We therefore lower the line 200 * rising edges as input to the VGIC. We therefore lower the line
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index e17f61a434fa..8195f52ae6f0 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -97,12 +97,9 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
97 97
98 /* 98 /*
99 * Clear soft pending state when level irqs have been acked. 99 * Clear soft pending state when level irqs have been acked.
100 * Always regenerate the pending state.
101 */ 100 */
102 if (irq->config == VGIC_CONFIG_LEVEL) { 101 if (irq->config == VGIC_CONFIG_LEVEL && !(val & ICH_LR_STATE))
103 if (!(val & ICH_LR_PENDING_BIT)) 102 irq->pending_latch = false;
104 irq->pending_latch = false;
105 }
106 103
107 /* 104 /*
108 * Level-triggered mapped IRQs are special because we only 105 * Level-triggered mapped IRQs are special because we only
@@ -136,8 +133,35 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
136{ 133{
137 u32 model = vcpu->kvm->arch.vgic.vgic_model; 134 u32 model = vcpu->kvm->arch.vgic.vgic_model;
138 u64 val = irq->intid; 135 u64 val = irq->intid;
136 bool allow_pending = true;
137
138 if (irq->active)
139 val |= ICH_LR_ACTIVE_BIT;
140
141 if (irq->hw) {
142 val |= ICH_LR_HW;
143 val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
144 /*
145 * Never set pending+active on a HW interrupt, as the
146 * pending state is kept at the physical distributor
147 * level.
148 */
149 if (irq->active)
150 allow_pending = false;
151 } else {
152 if (irq->config == VGIC_CONFIG_LEVEL) {
153 val |= ICH_LR_EOI;
139 154
140 if (irq_is_pending(irq)) { 155 /*
156 * Software resampling doesn't work very well
157 * if we allow P+A, so let's not do that.
158 */
159 if (irq->active)
160 allow_pending = false;
161 }
162 }
163
164 if (allow_pending && irq_is_pending(irq)) {
141 val |= ICH_LR_PENDING_BIT; 165 val |= ICH_LR_PENDING_BIT;
142 166
143 if (irq->config == VGIC_CONFIG_EDGE) 167 if (irq->config == VGIC_CONFIG_EDGE)
@@ -155,24 +179,6 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
155 } 179 }
156 } 180 }
157 181
158 if (irq->active)
159 val |= ICH_LR_ACTIVE_BIT;
160
161 if (irq->hw) {
162 val |= ICH_LR_HW;
163 val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
164 /*
165 * Never set pending+active on a HW interrupt, as the
166 * pending state is kept at the physical distributor
167 * level.
168 */
169 if (irq->active && irq_is_pending(irq))
170 val &= ~ICH_LR_PENDING_BIT;
171 } else {
172 if (irq->config == VGIC_CONFIG_LEVEL)
173 val |= ICH_LR_EOI;
174 }
175
176 /* 182 /*
177 * Level-triggered mapped IRQs are special because we only observe 183 * Level-triggered mapped IRQs are special because we only observe
178 * rising edges as input to the VGIC. We therefore lower the line 184 * rising edges as input to the VGIC. We therefore lower the line