diff options
author | Rob Herring <robh@kernel.org> | 2015-10-22 09:22:09 -0500 |
---|---|---|
committer | Rob Herring <robh@kernel.org> | 2015-10-22 09:22:09 -0500 |
commit | f92ce7618f0cb0ced87ea1cfe994d2e8473c61b4 (patch) | |
tree | 8589e85799e0de7b1cdf0b4e8f08397eeeb72a74 /virt/kvm/arm | |
parent | 307751ee3212df0d047b0e1a93ce21f2e511d1a1 (diff) | |
parent | eb3fcf007fffe5830d815e713591f3e858f2a365 (diff) |
Merge branch 'dt-doc-cleanup' into for-next
Diffstat (limited to 'virt/kvm/arm')
-rw-r--r-- | virt/kvm/arm/arch_timer.c | 8 | ||||
-rw-r--r-- | virt/kvm/arm/vgic-v3.c | 2 | ||||
-rw-r--r-- | virt/kvm/arm/vgic.c | 42 |
3 files changed, 35 insertions, 17 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 76e38d231e99..48c6e1ac6827 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -200,6 +200,14 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, timer->irq = irq; /* + * The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8 + * and to 0 for ARMv7. We provide an implementation that always + * resets the timer to be disabled and unmasked and is compliant with + * the ARMv7 architecture. + */ + timer->cntv_ctl = 0; + + /* * Tell the VGIC that the virtual interrupt is tied to a * physical interrupt. We do that once per VCPU. */ diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c index afbf925b00f4..7dd5d62f10a1 100644 --- a/virt/kvm/arm/vgic-v3.c +++ b/virt/kvm/arm/vgic-v3.c @@ -288,7 +288,7 @@ int vgic_v3_probe(struct device_node *vgic_node, vgic->vctrl_base = NULL; vgic->type = VGIC_V3; - vgic->max_gic_vcpus = KVM_MAX_VCPUS; + vgic->max_gic_vcpus = VGIC_V3_MAX_CPUS; kvm_info("%s@%llx IRQ%d\n", vgic_node->name, vcpu_res.start, vgic->maint_irq); diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 9eb489a2c94c..6bd1c9bf7ae7 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -1144,26 +1144,11 @@ static void vgic_queue_irq_to_lr(struct kvm_vcpu *vcpu, int irq, struct irq_phys_map *map; map = vgic_irq_map_search(vcpu, irq); - /* - * If we have a mapping, and the virtual interrupt is - * being injected, then we must set the state to - * active in the physical world. Otherwise the - * physical interrupt will fire and the guest will - * exit before processing the virtual interrupt. - */ if (map) { - int ret; - - BUG_ON(!map->active); vlr.hwirq = map->phys_irq; vlr.state |= LR_HW; vlr.state &= ~LR_EOI_INT; - ret = irq_set_irqchip_state(map->irq, - IRQCHIP_STATE_ACTIVE, - true); - WARN_ON(ret); - /* * Make sure we're not going to sample this * again, as a HW-backed interrupt cannot be @@ -1255,7 +1240,7 @@ static void __kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu) struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; struct vgic_dist *dist = &vcpu->kvm->arch.vgic; unsigned long *pa_percpu, *pa_shared; - int i, vcpu_id; + int i, vcpu_id, lr, ret; int overflow = 0; int nr_shared = vgic_nr_shared_irqs(dist); @@ -1310,6 +1295,31 @@ epilog: */ clear_bit(vcpu_id, dist->irq_pending_on_cpu); } + + for (lr = 0; lr < vgic->nr_lr; lr++) { + struct vgic_lr vlr; + + if (!test_bit(lr, vgic_cpu->lr_used)) + continue; + + vlr = vgic_get_lr(vcpu, lr); + + /* + * If we have a mapping, and the virtual interrupt is + * presented to the guest (as pending or active), then we must + * set the state to active in the physical world. See + * Documentation/virtual/kvm/arm/vgic-mapped-irqs.txt. + */ + if (vlr.state & LR_HW) { + struct irq_phys_map *map; + map = vgic_irq_map_search(vcpu, vlr.irq); + + ret = irq_set_irqchip_state(map->irq, + IRQCHIP_STATE_ACTIVE, + true); + WARN_ON(ret); + } + } } static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) |