summaryrefslogtreecommitdiffstats
path: root/virt/kvm/arm
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2019-08-09 10:53:50 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2019-08-09 10:53:50 -0400
commita738b5e75b4c13be3485c82eb62c30047aa9f164 (patch)
treef47fca53ee79938be283e13cf5d48def68f9dad2 /virt/kvm/arm
parent0e1c438c44dd9cde56effb44c5f1cfeda72e108d (diff)
parent16e604a437c89751dc626c9e90cf88ba93c5be64 (diff)
Merge tag 'kvmarm-fixes-for-5.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm fixes for 5.3, take #2 - Fix our system register reset so that we stop writing non-sensical values to them, and track which registers get reset instead. - Sync VMCR back from the GIC on WFI so that KVM has an exact vue of PMR. - Reevaluate state of HW-mapped, level triggered interrupts on enable.
Diffstat (limited to 'virt/kvm/arm')
-rw-r--r--virt/kvm/arm/arm.c11
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio.c16
-rw-r--r--virt/kvm/arm/vgic/vgic-v2.c9
-rw-r--r--virt/kvm/arm/vgic/vgic-v3.c7
-rw-r--r--virt/kvm/arm/vgic/vgic.c11
-rw-r--r--virt/kvm/arm/vgic/vgic.h2
6 files changed, 54 insertions, 2 deletions
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 3f7bea930acf..35a069815baf 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -318,6 +318,17 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
318 318
319void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) 319void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
320{ 320{
321 /*
322 * If we're about to block (most likely because we've just hit a
323 * WFI), we need to sync back the state of the GIC CPU interface
324 * so that we have the lastest PMR and group enables. This ensures
325 * that kvm_arch_vcpu_runnable has up-to-date data to decide
326 * whether we have pending interrupts.
327 */
328 preempt_disable();
329 kvm_vgic_vmcr_sync(vcpu);
330 preempt_enable();
331
321 kvm_vgic_v4_enable_doorbell(vcpu); 332 kvm_vgic_v4_enable_doorbell(vcpu);
322} 333}
323 334
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 3ba7278fb533..44efc2ff863f 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -113,6 +113,22 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
113 struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); 113 struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
114 114
115 raw_spin_lock_irqsave(&irq->irq_lock, flags); 115 raw_spin_lock_irqsave(&irq->irq_lock, flags);
116 if (vgic_irq_is_mapped_level(irq)) {
117 bool was_high = irq->line_level;
118
119 /*
120 * We need to update the state of the interrupt because
121 * the guest might have changed the state of the device
122 * while the interrupt was disabled at the VGIC level.
123 */
124 irq->line_level = vgic_get_phys_line_level(irq);
125 /*
126 * Deactivate the physical interrupt so the GIC will let
127 * us know when it is asserted again.
128 */
129 if (!irq->active && was_high && !irq->line_level)
130 vgic_irq_set_phys_active(irq, false);
131 }
116 irq->enabled = true; 132 irq->enabled = true;
117 vgic_queue_irq_unlock(vcpu->kvm, irq, flags); 133 vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
118 134
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 6dd5ad706c92..96aab77d0471 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -484,10 +484,17 @@ void vgic_v2_load(struct kvm_vcpu *vcpu)
484 kvm_vgic_global_state.vctrl_base + GICH_APR); 484 kvm_vgic_global_state.vctrl_base + GICH_APR);
485} 485}
486 486
487void vgic_v2_put(struct kvm_vcpu *vcpu) 487void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu)
488{ 488{
489 struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2; 489 struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
490 490
491 cpu_if->vgic_vmcr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VMCR); 491 cpu_if->vgic_vmcr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VMCR);
492}
493
494void vgic_v2_put(struct kvm_vcpu *vcpu)
495{
496 struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
497
498 vgic_v2_vmcr_sync(vcpu);
492 cpu_if->vgic_apr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_APR); 499 cpu_if->vgic_apr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_APR);
493} 500}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index c2c9ce009f63..0c653a1e5215 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -662,12 +662,17 @@ void vgic_v3_load(struct kvm_vcpu *vcpu)
662 __vgic_v3_activate_traps(vcpu); 662 __vgic_v3_activate_traps(vcpu);
663} 663}
664 664
665void vgic_v3_put(struct kvm_vcpu *vcpu) 665void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu)
666{ 666{
667 struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3; 667 struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
668 668
669 if (likely(cpu_if->vgic_sre)) 669 if (likely(cpu_if->vgic_sre))
670 cpu_if->vgic_vmcr = kvm_call_hyp_ret(__vgic_v3_read_vmcr); 670 cpu_if->vgic_vmcr = kvm_call_hyp_ret(__vgic_v3_read_vmcr);
671}
672
673void vgic_v3_put(struct kvm_vcpu *vcpu)
674{
675 vgic_v3_vmcr_sync(vcpu);
671 676
672 kvm_call_hyp(__vgic_v3_save_aprs, vcpu); 677 kvm_call_hyp(__vgic_v3_save_aprs, vcpu);
673 678
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 04786c8ec77e..13d4b38a94ec 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -919,6 +919,17 @@ void kvm_vgic_put(struct kvm_vcpu *vcpu)
919 vgic_v3_put(vcpu); 919 vgic_v3_put(vcpu);
920} 920}
921 921
922void kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu)
923{
924 if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
925 return;
926
927 if (kvm_vgic_global_state.type == VGIC_V2)
928 vgic_v2_vmcr_sync(vcpu);
929 else
930 vgic_v3_vmcr_sync(vcpu);
931}
932
922int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu) 933int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
923{ 934{
924 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 935 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 3b7525deec80..797e05004d80 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -193,6 +193,7 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
193void vgic_v2_init_lrs(void); 193void vgic_v2_init_lrs(void);
194void vgic_v2_load(struct kvm_vcpu *vcpu); 194void vgic_v2_load(struct kvm_vcpu *vcpu);
195void vgic_v2_put(struct kvm_vcpu *vcpu); 195void vgic_v2_put(struct kvm_vcpu *vcpu);
196void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu);
196 197
197void vgic_v2_save_state(struct kvm_vcpu *vcpu); 198void vgic_v2_save_state(struct kvm_vcpu *vcpu);
198void vgic_v2_restore_state(struct kvm_vcpu *vcpu); 199void vgic_v2_restore_state(struct kvm_vcpu *vcpu);
@@ -223,6 +224,7 @@ bool vgic_v3_check_base(struct kvm *kvm);
223 224
224void vgic_v3_load(struct kvm_vcpu *vcpu); 225void vgic_v3_load(struct kvm_vcpu *vcpu);
225void vgic_v3_put(struct kvm_vcpu *vcpu); 226void vgic_v3_put(struct kvm_vcpu *vcpu);
227void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu);
226 228
227bool vgic_has_its(struct kvm *kvm); 229bool vgic_has_its(struct kvm *kvm);
228int kvm_vgic_register_its_device(void); 230int kvm_vgic_register_its_device(void);