Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1676774 > unrolled thread

[PATCH v2 00/52] irqchip: KVM: Add support for GICv4

Started byMarc Zyngier <marc.zyngier@arm.com>
First post2017-06-28 17:10 +0200
Last post2017-07-01 17:00 +0200
Articles 8 on this page of 48 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 00/52] irqchip: KVM: Add support for GICv4 Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 07/52] irqchip/gic-v3-its: Implement irq_set_irqchip_state for pending state Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 39/52] KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq bypass Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 51/52] KVM: arm/arm64: GICv4: Use pending_last as a scheduling hint Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 30/52] irqchip/gic-v4: Add VPE command interface Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 48/52] KVM: arm/arm64: GICv4: Add doorbell interrupt handling Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 28/52] irqchip/gic-v3-its: Set implementation defined bit to enable VLPIs Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 43/52] KVM: arm/arm64: GICv4: Handle CLEAR applied to a VLPI Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 44/52] KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 41/52] KVM: arm/arm64: GICv4: Unmap VLPI when freeing an LPI Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 50/52] KVM: arm/arm64: GICv4: Enable virtual cpuif if VLPIs can be delivered Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 49/52] KVM: arm/arm64: GICv4: Hook vPE scheduling into vgic flush/sync Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 37/52] KVM: arm/arm64: GICv4: Add init and teardown of the vPE irq domain Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 52/52] KVM: arm/arm64: GICv4: Enable VLPI support Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 35/52] KVM: arm/arm64: vgic: Move kvm_vgic_destroy call around Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 08/52] irqchip/gic-v3-its: Split out property table allocation Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:10 +0200
    [PATCH v2 47/52] KVM: arm/arm64: GICv4: Propagate VLPI properties at map time Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 19/52] irqchip/gic-v3-its: Add VPE domain infrastructure Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 15/52] irqchip/gic-v3-its: Add GICv4 ITS command definitions Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 42/52] KVM: arm/arm64: GICv4: Handle MOVI applied to a VLPI Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 38/52] KVM: arm/arm64: GICv4: Wire init/teardown of per-VM support Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 32/52] irqchip/gic-v4: Add some basic documentation Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 24/52] irqchip/gic-v3-its: Add VPE invalidation hook Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 33/52] irqchip/gic-v4: Enable low-level GICv4 operations Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 29/52] irqchip/gic-v4: Add per-VM VPE domain creation Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 22/52] irqchip/gic-v3-its: Add VPENDBASER/VPROPBASER accessors Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 13/52] irqchip/gic-v3-its: Generalize LPI configuration Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 40/52] KVM: arm/arm64: GICv4: Handle INT command applied to a VLPI Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 23/52] irqchip/gic-v3-its: Add VPE scheduling Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 17/52] irqchip/gic-v3-its: Add VLPI map/unmap operations Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 46/52] KVM: arm/arm64: GICv4: Handle INVALL applied to a vPE Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 12/52] irqchip/gic-v3-its: Generalize device table allocation Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 09/52] irqchip/gic-v3-its: Allow use of indirect VCPU tables Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 14/52] irqchip/gic-v4: Add management structure definitions Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 11/52] irqchip/gic-v3-its: Rework LPI freeing Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 31/52] irqchip/gic-v4: Add VLPI configuration interface Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 21/52] irqchip/gic-v3-its: Add VPE irq domain [de]activation Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 25/52] irqchip/gic-v3-its: Add VPE affinity changes Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 18/52] irqchip/gic-v3-its: Add VLPI configuration handling Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 16/52] irqchip/gic-v3-its: Add VLPI configuration hook Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 20/52] irqchip/gic-v3-its: Add VPE irq domain allocation/teardown Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 36/52] KVM: arm/arm64: vITS: Add MSI translation helpers Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:20 +0200
    [PATCH v2 10/52] irqchip/gic-v3-its: Split out pending table allocation Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:30 +0200
    [PATCH v2 02/52] irqchip/gic-v3: Add redistributor iterator Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:30 +0200
    [PATCH v2 06/52] irqchip/gic-v3-its: Macro-ize its_send_single_command Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:30 +0200
    [PATCH v2 04/52] irqchip/gic-v3-its: Move LPI definitions around Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:30 +0200
    [PATCH v2 05/52] irqchip/gic-v3-its: Add probing for VLPI properties Marc Zyngier <marc.zyngier@arm.com> - 2017-06-28 17:30 +0200
    RE: [PATCH v2 00/52] irqchip: KVM: Add support for GICv4 "Shanker Donthineni" <shankerd@codeaurora.org> - 2017-07-01 17:00 +0200

Page 3 of 3 — ← Prev page 1 2 [3]


#1676828 — [PATCH v2 20/52] irqchip/gic-v3-its: Add VPE irq domain allocation/teardown

FromMarc Zyngier <marc.zyngier@arm.com>
Date2017-06-28 17:20 +0200
Subject[PATCH v2 20/52] irqchip/gic-v3-its: Add VPE irq domain allocation/teardown
Message-ID<tXmV6-8uj-79@gated-at.bofh.it>
In reply to#1676774
When creating a VM, the low level GICv4 code is responsible for:
- allocating each VPE a unique VPEID
- allocating a doorbell interrupt for each VPE
- allocating the pending tables for each VPE
- allocating the property table for the VM

This of course has to be reversed when the VM is brought down.

All of this is wired into the irq domain alloc/free methods.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 169 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 0fd799c88d18..58f3b19ec462 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -150,6 +150,7 @@ static struct irq_domain *its_parent;
 #define ITS_LIST_MAX		16
 
 static unsigned long its_list_map;
+static DEFINE_IDA(its_vpeid_ida);
 
 #define gic_data_rdist()		(raw_cpu_ptr(gic_rdists->rdist))
 #define gic_data_rdist_rd_base()	(gic_data_rdist()->rd_base)
@@ -1247,6 +1248,11 @@ static struct page *its_allocate_prop_table(gfp_t gfp_flags)
 	return prop_page;
 }
 
+static void its_free_prop_table(struct page *prop_page)
+{
+	free_pages((unsigned long)page_address(prop_page),
+		   get_order(LPI_PROPBASE_SZ));
+}
 
 static int __init its_alloc_lpi_tables(void)
 {
@@ -1548,6 +1554,12 @@ static struct page *its_allocate_pending_table(gfp_t gfp_flags)
 	return pend_page;
 }
 
+static void its_free_pending_table(struct page *pt)
+{
+	free_pages((unsigned long)page_address(pt),
+		   get_order(max(LPI_PENDBASE_SZ, SZ_64K)));
+}
+
 static void its_cpu_init_lpis(void)
 {
 	void __iomem *rbase = gic_data_rdist_rd_base();
@@ -1770,6 +1782,34 @@ static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
 	return its_alloc_table_entry(baser, dev_id);
 }
 
+static bool its_alloc_vpe_table(u32 vpe_id)
+{
+	struct its_node *its;
+
+	/*
+	 * Make sure the L2 tables are allocated on *all* v4 ITSs. We
+	 * could try and only do it on ITSs corresponding to devices
+	 * that have interrupts targeted at this VPE, but the
+	 * complexity becomes crazy (and you have tons of memory
+	 * anyway, right?).
+	 */
+	list_for_each_entry(its, &its_nodes, entry) {
+		struct its_baser *baser;
+
+		if (!its->is_v4)
+			continue;
+
+		baser = its_get_baser(its, GITS_BASER_TYPE_VCPU);
+		if (!baser)
+			return false;
+
+		if (!its_alloc_table_entry(baser, vpe_id))
+			return false;
+	}
+
+	return true;
+}
+
 static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 					    int nvecs)
 {
@@ -2027,7 +2067,136 @@ static struct irq_chip its_vpe_irq_chip = {
 	.name			= "GICv4-vpe",
 };
 
+static int its_vpe_id_alloc(void)
+{
+	return ida_simple_get(&its_vpeid_ida, 0, 1 << 16, GFP_KERNEL);
+}
+
+static void its_vpe_id_free(u16 id)
+{
+	ida_simple_remove(&its_vpeid_ida, id);
+}
+
+static int its_vpe_init(struct its_vpe *vpe)
+{
+	struct page *vpt_page;
+	int vpe_id;
+
+	/* Allocate vpe_id */
+	vpe_id = its_vpe_id_alloc();
+	if (vpe_id < 0)
+		return vpe_id;
+
+	/* Allocate VPT */
+	vpt_page = its_allocate_pending_table(GFP_KERNEL);
+	if (!vpt_page) {
+		its_vpe_id_free(vpe_id);
+		return -ENOMEM;
+	}
+
+	if (!its_alloc_vpe_table(vpe_id)) {
+		its_vpe_id_free(vpe_id);
+		its_free_pending_table(vpe->vpt_page);
+		return -ENOMEM;
+	}
+
+	vpe->vpe_id = vpe_id;
+	vpe->vpt_page = vpt_page;
+
+	return 0;
+}
+
+static void its_vpe_teardown(struct its_vpe *vpe)
+{
+	its_vpe_id_free(vpe->vpe_id);
+	its_free_pending_table(vpe->vpt_page);
+}
+
+static void its_vpe_irq_domain_free(struct irq_domain *domain,
+				    unsigned int virq,
+				    unsigned int nr_irqs)
+{
+	struct its_vm *vm = domain->host_data;
+	int i;
+
+	irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+
+	for (i = 0; i < nr_irqs; i++) {
+		struct irq_data *data = irq_domain_get_irq_data(domain,
+								virq + i);
+		struct its_vpe *vpe = irq_data_get_irq_chip_data(data);
+
+		BUG_ON(vm != vpe->its_vm);
+
+		clear_bit(data->hwirq, vm->db_bitmap);
+		its_vpe_teardown(vpe);
+		irq_domain_reset_irq_data(data);
+	}
+
+	if (bitmap_empty(vm->db_bitmap, vm->nr_db_lpis)) {
+		its_lpi_free_chunks(vm->db_bitmap, vm->db_lpi_base, vm->nr_db_lpis);
+		its_free_prop_table(vm->vprop_page);
+	}
+}
+
+static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+				    unsigned int nr_irqs, void *args)
+{
+	struct its_vm *vm = args;
+	unsigned long *bitmap;
+	struct page *vprop_page;
+	int base, nr_ids, i, err = 0;
+
+	BUG_ON(!vm);
+
+	bitmap = its_lpi_alloc_chunks(nr_irqs, &base, &nr_ids);
+	if (!bitmap)
+		return -ENOMEM;
+
+	if (nr_ids < nr_irqs) {
+		its_lpi_free_chunks(bitmap, base, nr_ids);
+		return -ENOMEM;
+	}
+
+	vprop_page = its_allocate_prop_table(GFP_KERNEL);
+	if (!vprop_page) {
+		its_lpi_free_chunks(bitmap, base, nr_ids);
+		return -ENOMEM;
+	}
+
+	vm->db_bitmap = bitmap;
+	vm->db_lpi_base = base;
+	vm->nr_db_lpis = nr_ids;
+	vm->vprop_page = vprop_page;
+
+	for (i = 0; i < nr_irqs; i++) {
+		vm->vpes[i]->vpe_db_lpi = base + i;
+		err = its_vpe_init(vm->vpes[i]);
+		if (err)
+			break;
+		err = its_irq_gic_domain_alloc(domain, virq + i,
+					       vm->vpes[i]->vpe_db_lpi);
+		if (err)
+			break;
+		irq_domain_set_hwirq_and_chip(domain, virq + i, i,
+					      &its_vpe_irq_chip, vm->vpes[i]);
+		set_bit(i, bitmap);
+	}
+
+	if (err) {
+		if (i > 0)
+			its_vpe_irq_domain_free(domain, virq, i - 1);
+
+		its_lpi_free_chunks(bitmap, base, nr_ids);
+		its_free_prop_table(vprop_page);
+	}
+
+	return err;
+}
+
 static const struct irq_domain_ops its_vpe_domain_ops = {
+	.alloc			= its_vpe_irq_domain_alloc,
+	.free			= its_vpe_irq_domain_free,
 };
 
 static int its_force_quiescent(void __iomem *base)
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1676829 — [PATCH v2 36/52] KVM: arm/arm64: vITS: Add MSI translation helpers

FromMarc Zyngier <marc.zyngier@arm.com>
Date2017-06-28 17:20 +0200
Subject[PATCH v2 36/52] KVM: arm/arm64: vITS: Add MSI translation helpers
Message-ID<tXmV6-8uj-75@gated-at.bofh.it>
In reply to#1676774
The whole MSI injection process is fairly monolithic. An MSI write
gets turned into an injected LPI in one swift go. But this is actually
a more fine-grained process:

- First, a virtual ITS gets selected using the doorbell address
- Then the DevID/EventID pair gets translated into an LPI
- Finally the LPI is injected

Since the GICv4 code needs the first two steps in order to match
an IRQ routing entry to an LPI, let's expose them as helpers,
and refactor the existing code to use them

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 93 +++++++++++++++++++++++++-------------------
 virt/kvm/arm/vgic/vgic.h     |  4 ++
 2 files changed, 57 insertions(+), 40 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 2dff288b3a66..5fbcf9ea8886 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -504,15 +504,8 @@ static unsigned long vgic_mmio_read_its_idregs(struct kvm *kvm,
 	return 0;
 }
 
-/*
- * Find the target VCPU and the LPI number for a given devid/eventid pair
- * and make this IRQ pending, possibly injecting it.
- * Must be called with the its_lock mutex held.
- * Returns 0 on success, a positive error value for any ITS mapping
- * related errors and negative error values for generic errors.
- */
-static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
-				u32 devid, u32 eventid)
+int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
+			 u32 devid, u32 eventid, struct vgic_irq **irq)
 {
 	struct kvm_vcpu *vcpu;
 	struct its_ite *ite;
@@ -531,26 +524,60 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
 	if (!vcpu->arch.vgic_cpu.lpis_enabled)
 		return -EBUSY;
 
-	spin_lock(&ite->irq->irq_lock);
-	ite->irq->pending_latch = true;
-	vgic_queue_irq_unlock(kvm, ite->irq);
-
+	*irq = ite->irq;
 	return 0;
 }
 
-static struct vgic_io_device *vgic_get_its_iodev(struct kvm_io_device *dev)
+struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi)
 {
+	u64 address;
+	struct kvm_io_device *kvm_io_dev;
 	struct vgic_io_device *iodev;
 
-	if (dev->ops != &kvm_io_gic_ops)
-		return NULL;
+	if (!vgic_has_its(kvm))
+		return ERR_PTR(-ENODEV);
 
-	iodev = container_of(dev, struct vgic_io_device, dev);
+	if (!(msi->flags & KVM_MSI_VALID_DEVID))
+		return ERR_PTR(-EINVAL);
+
+	address = (u64)msi->address_hi << 32 | msi->address_lo;
+
+	kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, address);
+	if (!kvm_io_dev)
+		return ERR_PTR(-EINVAL);
 
+	if (kvm_io_dev->ops != &kvm_io_gic_ops)
+		return ERR_PTR(-EINVAL);
+
+	iodev = container_of(kvm_io_dev, struct vgic_io_device, dev);
 	if (iodev->iodev_type != IODEV_ITS)
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
-	return iodev;
+	return iodev->its;
+}
+
+/*
+ * Find the target VCPU and the LPI number for a given devid/eventid pair
+ * and make this IRQ pending, possibly injecting it.
+ * Must be called with the its_lock mutex held.
+ * Returns 0 on success, a positive error value for any ITS mapping
+ * related errors and negative error values for generic errors.
+ */
+static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
+				u32 devid, u32 eventid)
+{
+	struct vgic_irq *irq = NULL;
+	int err;
+
+	err = vgic_its_resolve_lpi(kvm, its, devid, eventid, &irq);
+	if (err)
+		return err;
+
+	spin_lock(&irq->irq_lock);
+	irq->pending_latch = true;
+	vgic_queue_irq_unlock(kvm, irq);
+
+	return 0;
 }
 
 /*
@@ -561,30 +588,16 @@ static struct vgic_io_device *vgic_get_its_iodev(struct kvm_io_device *dev)
  */
 int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
 {
-	u64 address;
-	struct kvm_io_device *kvm_io_dev;
-	struct vgic_io_device *iodev;
+	struct vgic_its *its;
 	int ret;
 
-	if (!vgic_has_its(kvm))
-		return -ENODEV;
-
-	if (!(msi->flags & KVM_MSI_VALID_DEVID))
-		return -EINVAL;
-
-	address = (u64)msi->address_hi << 32 | msi->address_lo;
-
-	kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, address);
-	if (!kvm_io_dev)
-		return -EINVAL;
+	its = vgic_msi_to_its(kvm, msi);
+	if (IS_ERR(its))
+		return PTR_ERR(its);
 
-	iodev = vgic_get_its_iodev(kvm_io_dev);
-	if (!iodev)
-		return -EINVAL;
-
-	mutex_lock(&iodev->its->its_lock);
-	ret = vgic_its_trigger_msi(kvm, iodev->its, msi->devid, msi->data);
-	mutex_unlock(&iodev->its->its_lock);
+	mutex_lock(&its->its_lock);
+	ret = vgic_its_trigger_msi(kvm, its, msi->devid, msi->data);
+	mutex_unlock(&its->its_lock);
 
 	if (ret < 0)
 		return ret;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index da254ae29aec..3002b72d938b 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -225,4 +225,8 @@ int vgic_debug_destroy(struct kvm *kvm);
 bool lock_all_vcpus(struct kvm *kvm);
 void unlock_all_vcpus(struct kvm *kvm);
 
+int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
+			 u32 devid, u32 eventid, struct vgic_irq **irq);
+struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
+
 #endif
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1676830 — [PATCH v2 10/52] irqchip/gic-v3-its: Split out pending table allocation

FromMarc Zyngier <marc.zyngier@arm.com>
Date2017-06-28 17:30 +0200
Subject[PATCH v2 10/52] irqchip/gic-v3-its: Split out pending table allocation
Message-ID<tXn4K-6m-1@gated-at.bofh.it>
In reply to#1676774
Just as for the property table, let's move the pending table
allocation to a separate function.

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 27f57c528026..d6f9ccb36f4d 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1199,6 +1199,24 @@ static int its_alloc_collections(struct its_node *its)
 	return 0;
 }
 
+static struct page *its_allocate_pending_table(gfp_t gfp_flags)
+{
+	struct page *pend_page;
+	/*
+	 * The pending pages have to be at least 64kB aligned,
+	 * hence the 'max(LPI_PENDBASE_SZ, SZ_64K)' below.
+	 */
+	pend_page = alloc_pages(gfp_flags | __GFP_ZERO,
+				get_order(max(LPI_PENDBASE_SZ, SZ_64K)));
+	if (!pend_page)
+		return NULL;
+
+	/* Make sure the GIC will observe the zero-ed page */
+	gic_flush_dcache_to_poc(page_address(pend_page), LPI_PENDBASE_SZ);
+
+	return pend_page;
+}
+
 static void its_cpu_init_lpis(void)
 {
 	void __iomem *rbase = gic_data_rdist_rd_base();
@@ -1209,21 +1227,14 @@ static void its_cpu_init_lpis(void)
 	pend_page = gic_data_rdist()->pend_page;
 	if (!pend_page) {
 		phys_addr_t paddr;
-		/*
-		 * The pending pages have to be at least 64kB aligned,
-		 * hence the 'max(LPI_PENDBASE_SZ, SZ_64K)' below.
-		 */
-		pend_page = alloc_pages(GFP_NOWAIT | __GFP_ZERO,
-					get_order(max(LPI_PENDBASE_SZ, SZ_64K)));
+
+		pend_page = its_allocate_pending_table(GFP_NOWAIT);
 		if (!pend_page) {
 			pr_err("Failed to allocate PENDBASE for CPU%d\n",
 			       smp_processor_id());
 			return;
 		}
 
-		/* Make sure the GIC will observe the zero-ed page */
-		gic_flush_dcache_to_poc(page_address(pend_page), LPI_PENDBASE_SZ);
-
 		paddr = page_to_phys(pend_page);
 		pr_info("CPU%d: using LPI pending table @%pa\n",
 			smp_processor_id(), &paddr);
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1676831 — [PATCH v2 02/52] irqchip/gic-v3: Add redistributor iterator

FromMarc Zyngier <marc.zyngier@arm.com>
Date2017-06-28 17:30 +0200
Subject[PATCH v2 02/52] irqchip/gic-v3: Add redistributor iterator
Message-ID<tXn4K-6m-3@gated-at.bofh.it>
In reply to#1676774
In order to discover the VLPI properties, we need to iterate over
the redistributor regions. As we already have code that does this,
let's factor it out and make it slightly more generic.

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3.c | 69 ++++++++++++++++++++++++++++++--------------
 1 file changed, 47 insertions(+), 22 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index c132f29322cc..bc58a4339a97 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -421,24 +421,14 @@ static void __init gic_dist_init(void)
 		gic_write_irouter(affinity, base + GICD_IROUTER + i * 8);
 }
 
-static int gic_populate_rdist(void)
+static int gic_iterate_rdists(int (*fn)(struct redist_region *, void __iomem *))
 {
-	unsigned long mpidr = cpu_logical_map(smp_processor_id());
-	u64 typer;
-	u32 aff;
+	int ret = -ENODEV;
 	int i;
 
-	/*
-	 * Convert affinity to a 32bit value that can be matched to
-	 * GICR_TYPER bits [63:32].
-	 */
-	aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
-	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
-	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
-	       MPIDR_AFFINITY_LEVEL(mpidr, 0));
-
 	for (i = 0; i < gic_data.nr_redist_regions; i++) {
 		void __iomem *ptr = gic_data.redist_regions[i].redist_base;
+		u64 typer;
 		u32 reg;
 
 		reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK;
@@ -450,15 +440,9 @@ static int gic_populate_rdist(void)
 
 		do {
 			typer = gic_read_typer(ptr + GICR_TYPER);
-			if ((typer >> 32) == aff) {
-				u64 offset = ptr - gic_data.redist_regions[i].redist_base;
-				gic_data_rdist_rd_base() = ptr;
-				gic_data_rdist()->phys_base = gic_data.redist_regions[i].phys_base + offset;
-				pr_info("CPU%d: found redistributor %lx region %d:%pa\n",
-					smp_processor_id(), mpidr, i,
-					&gic_data_rdist()->phys_base);
+			ret = fn(gic_data.redist_regions + i, ptr);
+			if (!ret)
 				return 0;
-			}
 
 			if (gic_data.redist_regions[i].single_redist)
 				break;
@@ -473,9 +457,50 @@ static int gic_populate_rdist(void)
 		} while (!(typer & GICR_TYPER_LAST));
 	}
 
+	return ret ? -ENODEV : 0;
+}
+
+static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr)
+{
+	unsigned long mpidr = cpu_logical_map(smp_processor_id());
+	u64 typer;
+	u32 aff;
+
+	/*
+	 * Convert affinity to a 32bit value that can be matched to
+	 * GICR_TYPER bits [63:32].
+	 */
+	aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 0));
+
+	typer = gic_read_typer(ptr + GICR_TYPER);
+	if ((typer >> 32) == aff) {
+		u64 offset = ptr - region->redist_base;
+		gic_data_rdist_rd_base() = ptr;
+		gic_data_rdist()->phys_base = region->phys_base + offset;
+
+		pr_info("CPU%d: found redistributor %lx region %d:%pa\n",
+			smp_processor_id(), mpidr,
+			(int)(region - gic_data.redist_regions),
+			&gic_data_rdist()->phys_base);
+		return 0;
+	}
+
+	/* Try next one */
+	return 1;
+}
+
+static int gic_populate_rdist(void)
+{
+	if (gic_iterate_rdists(__gic_populate_rdist) == 0)
+		return 0;
+
 	/* We couldn't even deal with ourselves... */
 	WARN(true, "CPU%d: mpidr %lx has no re-distributor!\n",
-	     smp_processor_id(), mpidr);
+	     smp_processor_id(),
+	     (unsigned long)cpu_logical_map(smp_processor_id()));
 	return -ENODEV;
 }
 
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1676832 — [PATCH v2 06/52] irqchip/gic-v3-its: Macro-ize its_send_single_command

FromMarc Zyngier <marc.zyngier@arm.com>
Date2017-06-28 17:30 +0200
Subject[PATCH v2 06/52] irqchip/gic-v3-its: Macro-ize its_send_single_command
Message-ID<tXn4K-6m-5@gated-at.bofh.it>
In reply to#1676774
Most ITS commands do operate on a collection object, and require
a SYNC command to be performed on that collection in order to
guarantee the execution of the first command.

With GICv4 ITS, another set of commands perform similar operations
on a VPE object, and a VSYNC operations must be executed to guarantee
their execution.

Given the similarities (post a command, perform a synchronization
operation on a sync object), it makes sense to reuse the same
mechanism for both class of commands.

Let's start with turning its_send_single_command into a huge macro
that performs the bulk of the work, and a set of helpers that
make this macro usable for the GICv3 ITS commands.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 84 ++++++++++++++++++++++------------------
 1 file changed, 47 insertions(+), 37 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 006a5259609d..bbf7bb89aa62 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -490,43 +490,53 @@ static void its_wait_for_range_completion(struct its_node *its,
 	}
 }
 
-static void its_send_single_command(struct its_node *its,
-				    its_cmd_builder_t builder,
-				    struct its_cmd_desc *desc)
-{
-	struct its_cmd_block *cmd, *sync_cmd, *next_cmd;
-	struct its_collection *sync_col;
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&its->lock, flags);
-
-	cmd = its_allocate_entry(its);
-	if (!cmd) {		/* We're soooooo screewed... */
-		pr_err_ratelimited("ITS can't allocate, dropping command\n");
-		raw_spin_unlock_irqrestore(&its->lock, flags);
-		return;
-	}
-	sync_col = builder(cmd, desc);
-	its_flush_cmd(its, cmd);
-
-	if (sync_col) {
-		sync_cmd = its_allocate_entry(its);
-		if (!sync_cmd) {
-			pr_err_ratelimited("ITS can't SYNC, skipping\n");
-			goto post;
-		}
-		its_encode_cmd(sync_cmd, GITS_CMD_SYNC);
-		its_encode_target(sync_cmd, sync_col->target_address);
-		its_fixup_cmd(sync_cmd);
-		its_flush_cmd(its, sync_cmd);
-	}
-
-post:
-	next_cmd = its_post_commands(its);
-	raw_spin_unlock_irqrestore(&its->lock, flags);
-
-	its_wait_for_range_completion(its, cmd, next_cmd);
-}
+/* Warning, macro hell follows */
+#define BUILD_SINGLE_CMD_FUNC(name, buildtype, synctype, buildfn)	\
+void name(struct its_node *its,						\
+	  buildtype builder,						\
+	  struct its_cmd_desc *desc)					\
+{									\
+	struct its_cmd_block *cmd, *sync_cmd, *next_cmd;		\
+	synctype *sync_obj;						\
+	unsigned long flags;						\
+									\
+	raw_spin_lock_irqsave(&its->lock, flags);			\
+									\
+	cmd = its_allocate_entry(its);					\
+	if (!cmd) {		/* We're soooooo screewed... */		\
+		raw_spin_unlock_irqrestore(&its->lock, flags);		\
+		return;							\
+	}								\
+	sync_obj = builder(cmd, desc);					\
+	its_flush_cmd(its, cmd);					\
+									\
+	if (sync_obj) {							\
+		sync_cmd = its_allocate_entry(its);			\
+		if (!sync_cmd)						\
+			goto post;					\
+									\
+		buildfn(sync_cmd, sync_obj);				\
+		its_flush_cmd(its, sync_cmd);				\
+	}								\
+									\
+post:									\
+	next_cmd = its_post_commands(its);				\
+	raw_spin_unlock_irqrestore(&its->lock, flags);			\
+									\
+	its_wait_for_range_completion(its, cmd, next_cmd);		\
+}
+
+static void its_build_sync_cmd(struct its_cmd_block *sync_cmd,
+			       struct its_collection *sync_col)
+{
+	its_encode_cmd(sync_cmd, GITS_CMD_SYNC);
+	its_encode_target(sync_cmd, sync_col->target_address);
+
+	its_fixup_cmd(sync_cmd);
+}
+
+static BUILD_SINGLE_CMD_FUNC(its_send_single_command, its_cmd_builder_t,
+			     struct its_collection, its_build_sync_cmd)
 
 static void its_send_inv(struct its_device *dev, u32 event_id)
 {
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1676835 — [PATCH v2 04/52] irqchip/gic-v3-its: Move LPI definitions around

FromMarc Zyngier <marc.zyngier@arm.com>
Date2017-06-28 17:30 +0200
Subject[PATCH v2 04/52] irqchip/gic-v3-its: Move LPI definitions around
Message-ID<tXn4K-6m-21@gated-at.bofh.it>
In reply to#1676774
The various LPI definitions are in the middle of the code, and
would be better placed at the beginning, given that we're going
to use some of them much earlier.

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 45ea193325d2..335bd21c6f41 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -49,6 +49,21 @@
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING	(1 << 0)
 
 /*
+ * We allocate 64kB for PROPBASE. That gives us at most 64K LPIs to
+ * deal with (one configuration byte per interrupt). PENDBASE has to
+ * be 64kB aligned (one bit per LPI, plus 8192 bits for SPI/PPI/SGI).
+ */
+#define LPI_PROPBASE_SZ		SZ_64K
+#define LPI_PENDBASE_SZ		(LPI_PROPBASE_SZ / 8 + SZ_1K)
+
+/*
+ * This is how many bits of ID we need, including the useless ones.
+ */
+#define LPI_NRBITS		ilog2(LPI_PROPBASE_SZ + SZ_8K)
+
+#define LPI_PROP_DEFAULT_PRIO	0xa0
+
+/*
  * Collection structure - just an ID, and a redistributor address to
  * ping. We use one per CPU as a bag of interrupts assigned to this
  * CPU.
@@ -785,20 +800,8 @@ static void its_lpi_free(struct event_lpi_map *map)
 	kfree(map->col_map);
 }
 
-/*
- * We allocate 64kB for PROPBASE. That gives us at most 64K LPIs to
- * deal with (one configuration byte per interrupt). PENDBASE has to
- * be 64kB aligned (one bit per LPI, plus 8192 bits for SPI/PPI/SGI).
- */
-#define LPI_PROPBASE_SZ		SZ_64K
-#define LPI_PENDBASE_SZ		(LPI_PROPBASE_SZ / 8 + SZ_1K)
 
-/*
- * This is how many bits of ID we need, including the useless ones.
- */
-#define LPI_NRBITS		ilog2(LPI_PROPBASE_SZ + SZ_8K)
 
-#define LPI_PROP_DEFAULT_PRIO	0xa0
 
 static int __init its_alloc_lpi_tables(void)
 {
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1676836 — [PATCH v2 05/52] irqchip/gic-v3-its: Add probing for VLPI properties

FromMarc Zyngier <marc.zyngier@arm.com>
Date2017-06-28 17:30 +0200
Subject[PATCH v2 05/52] irqchip/gic-v3-its: Add probing for VLPI properties
Message-ID<tXn4K-6m-19@gated-at.bofh.it>
In reply to#1676774
Add the probing code for the ITS VLPI support. This includes
configuring the ITS number if not supporting the single VMOVP
command feature.

Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c   | 68 +++++++++++++++++++++++++++++++++++---
 include/linux/irqchip/arm-gic-v3.h |  5 +++
 2 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 335bd21c6f41..006a5259609d 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -103,6 +103,7 @@ struct its_node {
 	u32			ite_size;
 	u32			device_ids;
 	int			numa_node;
+	bool			is_v4;
 };
 
 #define ITS_ITT_ALIGN		SZ_256
@@ -135,6 +136,14 @@ static DEFINE_SPINLOCK(its_lock);
 static struct rdists *gic_rdists;
 static struct irq_domain *its_parent;
 
+/*
+ * We have a maximum number of 16 ITSs in the whole system if we're
+ * using the ITSList mechanism
+ */
+#define ITS_LIST_MAX		16
+
+static unsigned long its_list_map;
+
 #define gic_data_rdist()		(raw_cpu_ptr(gic_rdists->rdist))
 #define gic_data_rdist_rd_base()	(gic_data_rdist()->rd_base)
 
@@ -1673,13 +1682,51 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
 	return 0;
 }
 
+static int __init its_compute_its_list_map(struct resource *res,
+					   void __iomem *its_base)
+{
+	int its_number;
+	u32 ctlr;
+
+	/*
+	 * This is assumed to be done early enough that we're
+	 * guaranteed to be single-threaded, hence no
+	 * locking. Should this change, we should address
+	 * this.
+	 */
+	its_number = find_first_zero_bit(&its_list_map, ITS_LIST_MAX);
+	if (its_number >= ITS_LIST_MAX) {
+		pr_err("ITS@%pa: No ITSList entry available!\n",
+		       &res->start);
+		return -EINVAL;
+	}
+
+	ctlr = readl_relaxed(its_base + GITS_CTLR);
+	ctlr &= ~GITS_CTLR_ITS_NUMBER;
+	ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT;
+	writel_relaxed(ctlr, its_base + GITS_CTLR);
+	ctlr = readl_relaxed(its_base + GITS_CTLR);
+	if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) {
+		its_number = ctlr & GITS_CTLR_ITS_NUMBER;
+		its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT;
+	}
+
+	if (test_and_set_bit(its_number, &its_list_map)) {
+		pr_err("ITS@%pa: Duplicate ITSList entry %d\n",
+		       &res->start, its_number);
+		return -EINVAL;
+	}
+
+	return its_number;
+}
+
 static int __init its_probe_one(struct resource *res,
 				struct fwnode_handle *handle, int numa_node)
 {
 	struct its_node *its;
 	void __iomem *its_base;
-	u32 val;
-	u64 baser, tmp;
+	u32 val, ctlr;
+	u64 baser, tmp, typer;
 	int err;
 
 	its_base = ioremap(res->start, resource_size(res));
@@ -1712,9 +1759,21 @@ static int __init its_probe_one(struct resource *res,
 	raw_spin_lock_init(&its->lock);
 	INIT_LIST_HEAD(&its->entry);
 	INIT_LIST_HEAD(&its->its_device_list);
+	typer = gic_read_typer(its_base + GITS_TYPER);
 	its->base = its_base;
 	its->phys_base = res->start;
-	its->ite_size = ((gic_read_typer(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
+	its->ite_size = GITS_TYPER_ITT_ENTRY_SIZE(typer);
+	its->is_v4 = !!(typer & GITS_TYPER_VLPIS);
+	if (its->is_v4 && !(typer & GITS_TYPER_VMOVP)) {
+		err = its_compute_its_list_map(res, its_base);
+		if (err < 0)
+			goto out_free_its;
+
+		pr_info("ITS@%pa: Using ITS number %d\n", &res->start, err);
+	} else {
+		pr_info("ITS@%pa: Single VMOVP capable\n", &res->start);
+	}
+
 	its->numa_node = numa_node;
 
 	its->cmd_base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
@@ -1761,7 +1820,8 @@ static int __init its_probe_one(struct resource *res,
 	}
 
 	gits_write_cwriter(0, its->base + GITS_CWRITER);
-	writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
+	ctlr = readl_relaxed(its->base + GITS_CTLR);
+	writel_relaxed(ctlr | GITS_CTLR_ENABLE, its->base + GITS_CTLR);
 
 	err = its_init_domain(handle, its);
 	if (err)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 20a553423ac7..af8c55105fc2 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -235,15 +235,20 @@
 #define GITS_TRANSLATER			0x10040
 
 #define GITS_CTLR_ENABLE		(1U << 0)
+#define	GITS_CTLR_ITS_NUMBER_SHIFT	4
+#define	GITS_CTLR_ITS_NUMBER		(0xFU << GITS_CTLR_ITS_NUMBER_SHIFT)
 #define GITS_CTLR_QUIESCENT		(1U << 31)
 
 #define GITS_TYPER_PLPIS		(1UL << 0)
+#define GITS_TYPER_VLPIS		(1UL << 1)
 #define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
+#define GITS_TYPER_ITT_ENTRY_SIZE(r)	((((r) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
 #define GITS_TYPER_IDBITS_SHIFT		8
 #define GITS_TYPER_DEVBITS_SHIFT	13
 #define GITS_TYPER_DEVBITS(r)		((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
 #define GITS_TYPER_PTA			(1UL << 19)
 #define GITS_TYPER_HWCOLLCNT_SHIFT	24
+#define GITS_TYPER_VMOVP		(1ULL << 37)
 
 #define GITS_IIDR_REV_SHIFT		12
 #define GITS_IIDR_REV_MASK		(0xf << GITS_IIDR_REV_SHIFT)
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1679372

From"Shanker Donthineni" <shankerd@codeaurora.org>
Date2017-07-01 17:00 +0200
Message-ID<tYs2l-4ug-5@gated-at.bofh.it>
In reply to#1676774
Hi Marc,

I've verified the basic GICv4 functionality with v2 series + Eric's IRQ
bypass patches on QDF2400 platform with a minor change in vgic-init.c
successfully.  Nice, I don't  see any deadlock or catastrophic issues
running on QCOM hardware. You can add my tested-by, I'll provide comments
after reviewing giant v2 series.

Tested-by: Shanker Donthineni <shankerd@codeaurora.org>

-----Original Message-----
From: linux-arm-kernel [mailto:linux-arm-kernel-bounces@lists.infradead.org]
On Behalf Of Marc Zyngier
Sent: Wednesday, June 28, 2017 10:03 AM
To: linux-kernel@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
kvmarm@lists.cs.columbia.edu
Cc: Mark Rutland <mark.rutland@arm.com>; Jason Cooper
<jason@lakedaemon.net>; Eric Auger <eric.auger@redhat.com>; Christoffer Dall
<christoffer.dall@linaro.org>; Thomas Gleixner <tglx@linutronix.de>; Shanker
Donthineni <shankerd@codeaurora.org>
Subject: [PATCH v2 00/52] irqchip: KVM: Add support for GICv4

Yes, it's been a long time coming, but I really wasn't looking forward to
picking this up again. Anyway...

This (monster of a) series implements full support for GICv4, bringing
direct injection of MSIs to KVM on arm and arm64, assuming you have the
right hardware (which is quite unlikely).

To get an idea of the design, I'd recommend you start with patch #32, which
tries to shed some light on the approach that I've taken. And before that,
please digest some of the GICv3/GICv4 architecture documentation[1] (less
than 800 pages!). Once you feel reasonably insane, you'll be in the right
mood to read the code.

The structure of the series is fairly simple. The initial 34 patches add
some generic support for GICv4, while the rest of the code plugs KVM into
it. This series relies on Eric Auger's irq-bypass series[2], which is a
prerequisite for this work.

The stack has been *very lightly* tested on an arm64 model, with a PCI
virtio block device passed from the host to a guest (using kvmtool and
Jean-Philippe Brucker's excellent VFIO support patches[3]). As it has never
seen any HW, I expect things to be subtly broken, so go forward and test if
you can, though I'm mostly interested in people reviewing the code at the
moment.

I've pushed out a branch based on 4.12-rc6 containing the dependencies (as
well as a couple of debug patches):

git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git
kvm-arm64/gicv4-kvm

* From v1:
  - The bulk of the 30-something initial patches have seen countless
    bugs being fixed, and some key data structures have been subtly
    tweaked (or killed altogether). They are still quite similar to
    what I had in v1 though.
  - The whole KVM code is brand new and as I said above, only lightly
    tested.
  - Collected a bunch a R-bs from Thomas and Eric (many thanks, guys).

[1]
https://static.docs.arm.com/ihi0069/c/IHI0069C_gic_architecture_specificatio
n.pdf
[2] http://www.spinics.net/lists/kvm/msg151463.html
[3] http://www.spinics.net/lists/kvm/msg151823.html

Marc Zyngier (52):
  genirq: Let irq_set_vcpu_affinity() iterate over hierarchy
  irqchip/gic-v3: Add redistributor iterator
  irqchip/gic-v3: Add VLPI/DirectLPI discovery
  irqchip/gic-v3-its: Move LPI definitions around
  irqchip/gic-v3-its: Add probing for VLPI properties
  irqchip/gic-v3-its: Macro-ize its_send_single_command
  irqchip/gic-v3-its: Implement irq_set_irqchip_state for pending state
  irqchip/gic-v3-its: Split out property table allocation
  irqchip/gic-v3-its: Allow use of indirect VCPU tables
  irqchip/gic-v3-its: Split out pending table allocation
  irqchip/gic-v3-its: Rework LPI freeing
  irqchip/gic-v3-its: Generalize device table allocation
  irqchip/gic-v3-its: Generalize LPI configuration
  irqchip/gic-v4: Add management structure definitions
  irqchip/gic-v3-its: Add GICv4 ITS command definitions
  irqchip/gic-v3-its: Add VLPI configuration hook
  irqchip/gic-v3-its: Add VLPI map/unmap operations
  irqchip/gic-v3-its: Add VLPI configuration handling
  irqchip/gic-v3-its: Add VPE domain infrastructure
  irqchip/gic-v3-its: Add VPE irq domain allocation/teardown
  irqchip/gic-v3-its: Add VPE irq domain [de]activation
  irqchip/gic-v3-its: Add VPENDBASER/VPROPBASER accessors
  irqchip/gic-v3-its: Add VPE scheduling
  irqchip/gic-v3-its: Add VPE invalidation hook
  irqchip/gic-v3-its: Add VPE affinity changes
  irqchip/gic-v3-its: Add VPE interrupt masking
  irqchip/gic-v3-its: Support VPE doorbell invalidation even when
    !DirectLPI
  irqchip/gic-v3-its: Set implementation defined bit to enable VLPIs
  irqchip/gic-v4: Add per-VM VPE domain creation
  irqchip/gic-v4: Add VPE command interface
  irqchip/gic-v4: Add VLPI configuration interface
  irqchip/gic-v4: Add some basic documentation
  irqchip/gic-v4: Enable low-level GICv4 operations
  irqchip/gic-v3: Advertise GICv4 support to KVM
  KVM: arm/arm64: vgic: Move kvm_vgic_destroy call around
  KVM: arm/arm64: vITS: Add MSI translation helpers
  KVM: arm/arm64: GICv4: Add init and teardown of the vPE irq domain
  KVM: arm/arm64: GICv4: Wire init/teardown of per-VM support
  KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq
    bypass
  KVM: arm/arm64: GICv4: Handle INT command applied to a VLPI
  KVM: arm/arm64: GICv4: Unmap VLPI when freeing an LPI
  KVM: arm/arm64: GICv4: Handle MOVI applied to a VLPI
  KVM: arm/arm64: GICv4: Handle CLEAR applied to a VLPI
  KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE
  KVM: arm/arm64: GICv4: Propagate property updates to VLPIs
  KVM: arm/arm64: GICv4: Handle INVALL applied to a vPE
  KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
  KVM: arm/arm64: GICv4: Add doorbell interrupt handling
  KVM: arm/arm64: GICv4: Hook vPE scheduling into vgic flush/sync
  KVM: arm/arm64: GICv4: Enable virtual cpuif if VLPIs can be delivered
  KVM: arm/arm64: GICv4: Use pending_last as a scheduling hint
  KVM: arm/arm64: GICv4: Enable VLPI support

 arch/arm/include/asm/arch_gicv3.h      |   33 +
 arch/arm/kvm/Makefile                  |    1 +
 arch/arm64/include/asm/arch_gicv3.h    |    6 +
 arch/arm64/kvm/Makefile                |    1 +
 drivers/irqchip/Makefile               |    2 +-
 drivers/irqchip/irq-gic-v3-its.c       | 1288
+++++++++++++++++++++++++++++---
 drivers/irqchip/irq-gic-v3.c           |   93 ++-
 drivers/irqchip/irq-gic-v4.c           |  209 ++++++
 include/kvm/arm_vgic.h                 |   19 +
 include/linux/irqchip/arm-gic-common.h |    2 +
 include/linux/irqchip/arm-gic-v3.h     |   84 +++
 include/linux/irqchip/arm-gic-v4.h     |  102 +++
 kernel/irq/manage.c                    |   14 +-
 virt/kvm/arm/arm.c                     |   31 +-
 virt/kvm/arm/hyp/vgic-v3-sr.c          |    9 +-
 virt/kvm/arm/vgic/vgic-init.c          |   11 +-
 virt/kvm/arm/vgic/vgic-its.c           |  165 ++--
 virt/kvm/arm/vgic/vgic-v3.c            |    6 +
 virt/kvm/arm/vgic/vgic-v4.c            |  210 ++++++
 virt/kvm/arm/vgic/vgic.c               |    7 +
 virt/kvm/arm/vgic/vgic.h               |   10 +
 21 files changed, 2103 insertions(+), 200 deletions(-)  create mode 100644
drivers/irqchip/irq-gic-v4.c  create mode 100644
include/linux/irqchip/arm-gic-v4.h
 create mode 100644 virt/kvm/arm/vgic/vgic-v4.c

--
2.11.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

[toc] | [prev] | [standalone]


Page 3 of 3 — ← Prev page 1 2 [3]

Back to top | Article view | linux.kernel


csiph-web