aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2017-10-27 10:28:50 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2017-11-10 03:43:26 -0500
commit6277579778d63125671509e2502597fdf6a56c00 (patch)
tree76377e42055fd37f3e3f26a1a331add0f7797cb2
parentdf9ba95993b9d59e077aa4613f7a4edd20a4064c (diff)
KVM: arm/arm64: GICv4: Hook vPE scheduling into vgic flush/sync
The redistributor needs to be told which vPE is about to be run, and tells us whether there is any pending VLPI on exit. Let's add the scheduling calls to the vgic flush/sync functions, allowing the VLPIs to be delivered to the guest. Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
-rw-r--r--virt/kvm/arm/vgic/vgic-v4.c39
-rw-r--r--virt/kvm/arm/vgic/vgic.c4
-rw-r--r--virt/kvm/arm/vgic/vgic.h2
3 files changed, 45 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index 1375a53054b9..c9cec01008c2 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -131,6 +131,45 @@ void vgic_v4_teardown(struct kvm *kvm)
131 its_vm->vpes = NULL; 131 its_vm->vpes = NULL;
132} 132}
133 133
134int vgic_v4_sync_hwstate(struct kvm_vcpu *vcpu)
135{
136 if (!vgic_supports_direct_msis(vcpu->kvm))
137 return 0;
138
139 return its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, false);
140}
141
142int vgic_v4_flush_hwstate(struct kvm_vcpu *vcpu)
143{
144 int irq = vcpu->arch.vgic_cpu.vgic_v3.its_vpe.irq;
145 int err;
146
147 if (!vgic_supports_direct_msis(vcpu->kvm))
148 return 0;
149
150 /*
151 * Before making the VPE resident, make sure the redistributor
152 * corresponding to our current CPU expects us here. See the
153 * doc in drivers/irqchip/irq-gic-v4.c to understand how this
154 * turns into a VMOVP command at the ITS level.
155 */
156 err = irq_set_affinity(irq, cpumask_of(smp_processor_id()));
157 if (err)
158 return err;
159
160 err = its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, true);
161 if (err)
162 return err;
163
164 /*
165 * Now that the VPE is resident, let's get rid of a potential
166 * doorbell interrupt that would still be pending.
167 */
168 err = irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, false);
169
170 return err;
171}
172
134static struct vgic_its *vgic_get_its(struct kvm *kvm, 173static struct vgic_its *vgic_get_its(struct kvm *kvm,
135 struct kvm_kernel_irq_routing_entry *irq_entry) 174 struct kvm_kernel_irq_routing_entry *irq_entry)
136{ 175{
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index d29e91215366..b168a328a9e0 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -718,6 +718,8 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
718{ 718{
719 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 719 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
720 720
721 WARN_ON(vgic_v4_sync_hwstate(vcpu));
722
721 /* An empty ap_list_head implies used_lrs == 0 */ 723 /* An empty ap_list_head implies used_lrs == 0 */
722 if (list_empty(&vcpu->arch.vgic_cpu.ap_list_head)) 724 if (list_empty(&vcpu->arch.vgic_cpu.ap_list_head))
723 return; 725 return;
@@ -730,6 +732,8 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
730/* Flush our emulation state into the GIC hardware before entering the guest. */ 732/* Flush our emulation state into the GIC hardware before entering the guest. */
731void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu) 733void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
732{ 734{
735 WARN_ON(vgic_v4_flush_hwstate(vcpu));
736
733 /* 737 /*
734 * If there are no virtual interrupts active or pending for this 738 * If there are no virtual interrupts active or pending for this
735 * VCPU, then there is no work to do and we can bail out without 739 * VCPU, then there is no work to do and we can bail out without
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index bf03a9648fbb..efbcf8f96f9c 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -244,5 +244,7 @@ struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
244bool vgic_supports_direct_msis(struct kvm *kvm); 244bool vgic_supports_direct_msis(struct kvm *kvm);
245int vgic_v4_init(struct kvm *kvm); 245int vgic_v4_init(struct kvm *kvm);
246void vgic_v4_teardown(struct kvm *kvm); 246void vgic_v4_teardown(struct kvm *kvm);
247int vgic_v4_sync_hwstate(struct kvm_vcpu *vcpu);
248int vgic_v4_flush_hwstate(struct kvm_vcpu *vcpu);
247 249
248#endif 250#endif