KVM: arm64: vgic-its: Read config and pending bit in add_lpi()
authorEric Auger <eric.auger@redhat.com>
Thu, 4 May 2017 09:36:32 +0000 (11:36 +0200)
committerChristoffer Dall <cdall@linaro.org>
Mon, 8 May 2017 12:36:17 +0000 (14:36 +0200)
When creating the lpi we now ask the redistributor what is the state
of the LPI (priority, enabled, pending).

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
virt/kvm/arm/vgic/vgic-its.c

index 3601790d841e006d486a801fd54e027ddee66762..ffd0a801aeb593527c463a7276ab7bdfeba96a35 100644 (file)
@@ -36,6 +36,8 @@
 static int vgic_its_save_tables_v0(struct vgic_its *its);
 static int vgic_its_restore_tables_v0(struct vgic_its *its);
 static int vgic_its_commit_v0(struct vgic_its *its);
+static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
+                            struct kvm_vcpu *filter_vcpu);
 
 /*
  * Creates a new (reference to a) struct vgic_irq for a given LPI.
@@ -44,10 +46,12 @@ static int vgic_its_commit_v0(struct vgic_its *its);
  * If this is a "new" LPI, we allocate and initialize a new struct vgic_irq.
  * This function returns a pointer to the _unlocked_ structure.
  */
-static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid)
+static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
+                                    struct kvm_vcpu *vcpu)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
        struct vgic_irq *irq = vgic_get_irq(kvm, NULL, intid), *oldirq;
+       int ret;
 
        /* In this case there is no put, since we keep the reference. */
        if (irq)
@@ -64,6 +68,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid)
        irq->config = VGIC_CONFIG_EDGE;
        kref_init(&irq->refcount);
        irq->intid = intid;
+       irq->target_vcpu = vcpu;
 
        spin_lock(&dist->lpi_list_lock);
 
@@ -95,6 +100,19 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid)
 out_unlock:
        spin_unlock(&dist->lpi_list_lock);
 
+       /*
+        * We "cache" the configuration table entries in our struct vgic_irq's.
+        * However we only have those structs for mapped IRQs, so we read in
+        * the respective config data from memory here upon mapping the LPI.
+        */
+       ret = update_lpi_config(kvm, irq, NULL);
+       if (ret)
+               return ERR_PTR(ret);
+
+       ret = vgic_v3_lpi_sync_pending_status(kvm, irq);
+       if (ret)
+               return ERR_PTR(ret);
+
        return irq;
 }
 
@@ -795,6 +813,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
        u32 event_id = its_cmd_get_id(its_cmd);
        u32 coll_id = its_cmd_get_collection(its_cmd);
        struct its_ite *ite;
+       struct kvm_vcpu *vcpu = NULL;
        struct its_device *device;
        struct its_collection *collection, *new_coll = NULL;
        int lpi_nr;
@@ -840,7 +859,10 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
        ite->collection = collection;
        ite->lpi = lpi_nr;
 
-       irq = vgic_add_lpi(kvm, lpi_nr);
+       if (its_is_collection_mapped(collection))
+               vcpu = kvm_get_vcpu(kvm, collection->target_addr);
+
+       irq = vgic_add_lpi(kvm, lpi_nr, vcpu);
        if (IS_ERR(irq)) {
                if (new_coll)
                        vgic_its_free_collection(its, coll_id);
@@ -849,15 +871,6 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
        }
        ite->irq = irq;
 
-       update_affinity_ite(kvm, ite);
-
-       /*
-        * We "cache" the configuration table entries in out struct vgic_irq's.
-        * However we only have those structs for mapped IRQs, so we read in
-        * the respective config data from memory here upon mapping the LPI.
-        */
-       update_lpi_config(kvm, ite->irq, NULL);
-
        return 0;
 }