diff options
-rw-r--r-- | virt/kvm/arm/arch_timer.c | 19 | ||||
-rw-r--r-- | virt/kvm/arm/vgic.c | 43 |
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) | |||
137 | void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) | 137 | void 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 | ||
1326 | static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) | 1310 | static 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 | } |