aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--virt/kvm/arm/arch_timer.c19
-rw-r--r--virt/kvm/arm/vgic.c43
2 files changed, 30 insertions, 32 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 48c6e1ac6827..b9d3a32cbc04 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -137,6 +137,8 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
137void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) 137void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
138{ 138{
139 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; 139 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
140 bool phys_active;
141 int ret;
140 142
141 /* 143 /*
142 * We're about to run this vcpu again, so there is no need to 144 * We're about to run this vcpu again, so there is no need to
@@ -151,6 +153,23 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
151 */ 153 */
152 if (kvm_timer_should_fire(vcpu)) 154 if (kvm_timer_should_fire(vcpu))
153 kvm_timer_inject_irq(vcpu); 155 kvm_timer_inject_irq(vcpu);
156
157 /*
158 * We keep track of whether the edge-triggered interrupt has been
159 * signalled to the vgic/guest, and if so, we mask the interrupt and
160 * the physical distributor to prevent the timer from raising a
161 * physical interrupt whenever we run a guest, preventing forward
162 * VCPU progress.
163 */
164 if (kvm_vgic_get_phys_irq_active(timer->map))
165 phys_active = true;
166 else
167 phys_active = false;
168
169 ret = irq_set_irqchip_state(timer->map->irq,
170 IRQCHIP_STATE_ACTIVE,
171 phys_active);
172 WARN_ON(ret);
154} 173}
155 174
156/** 175/**
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 596455a394af..ea21bc273542 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1092,6 +1092,15 @@ static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu)
1092 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 1092 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
1093 struct vgic_lr vlr = vgic_get_lr(vcpu, lr_nr); 1093 struct vgic_lr vlr = vgic_get_lr(vcpu, lr_nr);
1094 1094
1095 /*
1096 * We must transfer the pending state back to the distributor before
1097 * retiring the LR, otherwise we may loose edge-triggered interrupts.
1098 */
1099 if (vlr.state & LR_STATE_PENDING) {
1100 vgic_dist_irq_set_pending(vcpu, irq);
1101 vlr.hwirq = 0;
1102 }
1103
1095 vlr.state = 0; 1104 vlr.state = 0;
1096 vgic_set_lr(vcpu, lr_nr, vlr); 1105 vgic_set_lr(vcpu, lr_nr, vlr);
1097 clear_bit(lr_nr, vgic_cpu->lr_used); 1106 clear_bit(lr_nr, vgic_cpu->lr_used);
@@ -1241,7 +1250,7 @@ static void __kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
1241 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 1250 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
1242 struct vgic_dist *dist = &vcpu->kvm->arch.vgic; 1251 struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
1243 unsigned long *pa_percpu, *pa_shared; 1252 unsigned long *pa_percpu, *pa_shared;
1244 int i, vcpu_id, lr, ret; 1253 int i, vcpu_id;
1245 int overflow = 0; 1254 int overflow = 0;
1246 int nr_shared = vgic_nr_shared_irqs(dist); 1255 int nr_shared = vgic_nr_shared_irqs(dist);
1247 1256
@@ -1296,31 +1305,6 @@ epilog:
1296 */ 1305 */
1297 clear_bit(vcpu_id, dist->irq_pending_on_cpu); 1306 clear_bit(vcpu_id, dist->irq_pending_on_cpu);
1298 } 1307 }
1299
1300 for (lr = 0; lr < vgic->nr_lr; lr++) {
1301 struct vgic_lr vlr;
1302
1303 if (!test_bit(lr, vgic_cpu->lr_used))
1304 continue;
1305
1306 vlr = vgic_get_lr(vcpu, lr);
1307
1308 /*
1309 * If we have a mapping, and the virtual interrupt is
1310 * presented to the guest (as pending or active), then we must
1311 * set the state to active in the physical world. See
1312 * Documentation/virtual/kvm/arm/vgic-mapped-irqs.txt.
1313 */
1314 if (vlr.state & LR_HW) {
1315 struct irq_phys_map *map;
1316 map = vgic_irq_map_search(vcpu, vlr.irq);
1317
1318 ret = irq_set_irqchip_state(map->irq,
1319 IRQCHIP_STATE_ACTIVE,
1320 true);
1321 WARN_ON(ret);
1322 }
1323 }
1324} 1308}
1325 1309
1326static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) 1310static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
@@ -1430,13 +1414,8 @@ static int vgic_sync_hwirq(struct kvm_vcpu *vcpu, struct vgic_lr vlr)
1430 1414
1431 WARN_ON(ret); 1415 WARN_ON(ret);
1432 1416
1433 if (map->active) { 1417 if (map->active)
1434 ret = irq_set_irqchip_state(map->irq,
1435 IRQCHIP_STATE_ACTIVE,
1436 false);
1437 WARN_ON(ret);
1438 return 0; 1418 return 0;
1439 }
1440 1419
1441 return 1; 1420 return 1;
1442} 1421}