diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2015-11-24 13:34:40 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-11-24 13:34:40 -0500 |
commit | 8bd142c01648cdb33e9bcafa0448ba2c20ed814c (patch) | |
tree | 9197c60d3f9d4036f38f281a183e94750ceea1d7 /virt/kvm | |
parent | d792abacaf1a1a8dfea353fab699b97fa6251c2a (diff) | |
parent | fbb4574ce9a37e15a9872860bf202f2be5bdf6c4 (diff) |
Merge tag 'kvm-arm-for-v4.4-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into kvm-master
KVM/ARM Fixes for v4.4-rc3.
Includes some timer fixes, properly unmapping PTEs, an errata fix, and two
tweaks to the EL2 panic code.
Diffstat (limited to 'virt/kvm')
-rw-r--r-- | virt/kvm/arm/arch_timer.c | 28 | ||||
-rw-r--r-- | virt/kvm/arm/vgic.c | 50 |
2 files changed, 41 insertions, 37 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 21a0ab2d8919..69bca185c471 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c | |||
@@ -221,17 +221,23 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) | |||
221 | kvm_timer_update_state(vcpu); | 221 | kvm_timer_update_state(vcpu); |
222 | 222 | ||
223 | /* | 223 | /* |
224 | * If we enter the guest with the virtual input level to the VGIC | 224 | * If we enter the guest with the virtual input level to the VGIC |
225 | * asserted, then we have already told the VGIC what we need to, and | 225 | * asserted, then we have already told the VGIC what we need to, and |
226 | * we don't need to exit from the guest until the guest deactivates | 226 | * we don't need to exit from the guest until the guest deactivates |
227 | * the already injected interrupt, so therefore we should set the | 227 | * the already injected interrupt, so therefore we should set the |
228 | * hardware active state to prevent unnecessary exits from the guest. | 228 | * hardware active state to prevent unnecessary exits from the guest. |
229 | * | 229 | * |
230 | * Conversely, if the virtual input level is deasserted, then always | 230 | * Also, if we enter the guest with the virtual timer interrupt active, |
231 | * clear the hardware active state to ensure that hardware interrupts | 231 | * then it must be active on the physical distributor, because we set |
232 | * from the timer triggers a guest exit. | 232 | * the HW bit and the guest must be able to deactivate the virtual and |
233 | */ | 233 | * physical interrupt at the same time. |
234 | if (timer->irq.level) | 234 | * |
235 | * Conversely, if the virtual input level is deasserted and the virtual | ||
236 | * interrupt is not active, then always clear the hardware active state | ||
237 | * to ensure that hardware interrupts from the timer triggers a guest | ||
238 | * exit. | ||
239 | */ | ||
240 | if (timer->irq.level || kvm_vgic_map_is_active(vcpu, timer->map)) | ||
235 | phys_active = true; | 241 | phys_active = true; |
236 | else | 242 | else |
237 | phys_active = false; | 243 | phys_active = false; |
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 533538385d5d..65461f821a75 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
@@ -1096,6 +1096,27 @@ static void vgic_retire_lr(int lr_nr, struct kvm_vcpu *vcpu) | |||
1096 | vgic_set_lr(vcpu, lr_nr, vlr); | 1096 | vgic_set_lr(vcpu, lr_nr, vlr); |
1097 | } | 1097 | } |
1098 | 1098 | ||
1099 | static bool dist_active_irq(struct kvm_vcpu *vcpu) | ||
1100 | { | ||
1101 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; | ||
1102 | |||
1103 | return test_bit(vcpu->vcpu_id, dist->irq_active_on_cpu); | ||
1104 | } | ||
1105 | |||
1106 | bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map) | ||
1107 | { | ||
1108 | int i; | ||
1109 | |||
1110 | for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) { | ||
1111 | struct vgic_lr vlr = vgic_get_lr(vcpu, i); | ||
1112 | |||
1113 | if (vlr.irq == map->virt_irq && vlr.state & LR_STATE_ACTIVE) | ||
1114 | return true; | ||
1115 | } | ||
1116 | |||
1117 | return dist_active_irq(vcpu); | ||
1118 | } | ||
1119 | |||
1099 | /* | 1120 | /* |
1100 | * An interrupt may have been disabled after being made pending on the | 1121 | * An interrupt may have been disabled after being made pending on the |
1101 | * CPU interface (the classic case is a timer running while we're | 1122 | * CPU interface (the classic case is a timer running while we're |
@@ -1248,7 +1269,7 @@ static void __kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu) | |||
1248 | * may have been serviced from another vcpu. In all cases, | 1269 | * may have been serviced from another vcpu. In all cases, |
1249 | * move along. | 1270 | * move along. |
1250 | */ | 1271 | */ |
1251 | if (!kvm_vgic_vcpu_pending_irq(vcpu) && !kvm_vgic_vcpu_active_irq(vcpu)) | 1272 | if (!kvm_vgic_vcpu_pending_irq(vcpu) && !dist_active_irq(vcpu)) |
1252 | goto epilog; | 1273 | goto epilog; |
1253 | 1274 | ||
1254 | /* SGIs */ | 1275 | /* SGIs */ |
@@ -1396,25 +1417,13 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) | |||
1396 | static bool vgic_sync_hwirq(struct kvm_vcpu *vcpu, int lr, struct vgic_lr vlr) | 1417 | static bool vgic_sync_hwirq(struct kvm_vcpu *vcpu, int lr, struct vgic_lr vlr) |
1397 | { | 1418 | { |
1398 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; | 1419 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; |
1399 | struct irq_phys_map *map; | ||
1400 | bool phys_active; | ||
1401 | bool level_pending; | 1420 | bool level_pending; |
1402 | int ret; | ||
1403 | 1421 | ||
1404 | if (!(vlr.state & LR_HW)) | 1422 | if (!(vlr.state & LR_HW)) |
1405 | return false; | 1423 | return false; |
1406 | 1424 | ||
1407 | map = vgic_irq_map_search(vcpu, vlr.irq); | 1425 | if (vlr.state & LR_STATE_ACTIVE) |
1408 | BUG_ON(!map); | 1426 | return false; |
1409 | |||
1410 | ret = irq_get_irqchip_state(map->irq, | ||
1411 | IRQCHIP_STATE_ACTIVE, | ||
1412 | &phys_active); | ||
1413 | |||
1414 | WARN_ON(ret); | ||
1415 | |||
1416 | if (phys_active) | ||
1417 | return 0; | ||
1418 | 1427 | ||
1419 | spin_lock(&dist->lock); | 1428 | spin_lock(&dist->lock); |
1420 | level_pending = process_queued_irq(vcpu, lr, vlr); | 1429 | level_pending = process_queued_irq(vcpu, lr, vlr); |
@@ -1479,17 +1488,6 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu) | |||
1479 | return test_bit(vcpu->vcpu_id, dist->irq_pending_on_cpu); | 1488 | return test_bit(vcpu->vcpu_id, dist->irq_pending_on_cpu); |
1480 | } | 1489 | } |
1481 | 1490 | ||
1482 | int kvm_vgic_vcpu_active_irq(struct kvm_vcpu *vcpu) | ||
1483 | { | ||
1484 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; | ||
1485 | |||
1486 | if (!irqchip_in_kernel(vcpu->kvm)) | ||
1487 | return 0; | ||
1488 | |||
1489 | return test_bit(vcpu->vcpu_id, dist->irq_active_on_cpu); | ||
1490 | } | ||
1491 | |||
1492 | |||
1493 | void vgic_kick_vcpus(struct kvm *kvm) | 1491 | void vgic_kick_vcpus(struct kvm *kvm) |
1494 | { | 1492 | { |
1495 | struct kvm_vcpu *vcpu; | 1493 | struct kvm_vcpu *vcpu; |