[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC PATCH v3 12/18] xen/arm: ITS: Add GICR register emulation



From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>

Emulate LPI related changes to GICR registers

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>
---
 xen/arch/arm/gic-v3.c             |   15 ++++++++
 xen/arch/arm/gic.c                |   10 ++++++
 xen/arch/arm/vgic-v3.c            |   69 ++++++++++++++++++++++++++++++-------
 xen/include/asm-arm/domain.h      |    1 +
 xen/include/asm-arm/gic-its.h     |    1 +
 xen/include/asm-arm/gic.h         |    9 +++++
 xen/include/asm-arm/gic_v3_defs.h |    1 +
 7 files changed, 94 insertions(+), 12 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 556b291..737646c 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -683,6 +683,11 @@ static int __init gicv3_populate_rdist(void)
     return -ENODEV;
 }
 
+static int gicv3_dist_supports_lpis(void)
+{
+    return readl_relaxed(GICD + GICD_TYPER) & GICD_TYPER_LPIS_SUPPORTED;
+}
+
 static int __cpuinit gicv3_cpu_init(void)
 {
     int i;
@@ -1304,10 +1309,20 @@ static int __init gicv3_init(void)
            gicv3.rdist_regions[0].size, gicv3.rdist_regions[0].map_base,
            gicv3_info.maintenance_irq);
 
+    reg = readl_relaxed(GICD + GICD_TYPER);
+
+    gicv3.rdist_data.id_bits = ((reg >> 19) & 0x1f) + 1;
+    gicv3_info.nr_id_bits = gicv3.rdist_data.id_bits;
+
     spin_lock_init(&gicv3.lock);
 
     spin_lock(&gicv3.lock);
 
+    if ( gicv3_dist_supports_lpis() )
+        gicv3_info.lpi_supported = 1;
+    else
+        gicv3_info.lpi_supported = 0;
+
     gicv3_dist_init();
     res = gicv3_cpu_init();
     gicv3_hyp_init();
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index c41e82e..cfc9c42 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -67,6 +67,16 @@ unsigned int gic_number_lines(void)
     return gic_hw_ops->info->nr_lines;
 }
 
+unsigned int gic_nr_id_bits(void)
+{
+    return gic_hw_ops->info->nr_id_bits;
+}
+
+bool_t gic_lpi_supported(void)
+{
+    return gic_hw_ops->info->lpi_supported;
+}
+
 void gic_save_state(struct vcpu *v)
 {
     ASSERT(!local_irq_is_enabled());
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 4af5a84..44922fb 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -30,6 +30,7 @@
 #include <asm/mmio.h>
 #include <asm/gic_v3_defs.h>
 #include <asm/gic.h>
+#include <asm/gic-its.h>
 #include <asm/vgic.h>
 
 /* GICD_PIDRn register values for ARM implementations */
@@ -93,8 +94,15 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
mmio_info_t *info,
     switch ( gicr_reg )
     {
     case GICR_CTLR:
-        /* We have not implemented LPI's, read zero */
-        goto read_as_zero_32;
+        /*
+         * Enable LPI's for ITS. Direct injection of LPI
+         * by writing to GICR_{SET,CLR}LPIR are not supported
+         */
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        vgic_lock(v);
+        *r = v->domain->arch.vgic.gicr_ctlr;
+        vgic_unlock(v);
+        return 1;
     case GICR_IIDR:
         if ( dabt.size != DABT_WORD ) goto bad_width;
         *r = GICV3_GICR_IIDR_VAL;
@@ -106,6 +114,10 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
mmio_info_t *info,
                MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 2) << 48 |
                MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 1) << 40 |
                MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 0) << 32);
+        /* Set LPI support */
+        aff |= (GICR_TYPER_DISTRIBUTED_IMP | GICR_TYPER_PLPIS);
+        /* GITS_TYPER.PTA is  0. Provice vcpu number as ta */
+        aff |= (v->vcpu_id << GICR_TYPER_PROCESSOR_SHIFT);
         *r = aff;
 
         if ( v->arch.vgic.flags & VGIC_V3_RDIST_LAST )
@@ -125,11 +137,13 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
mmio_info_t *info,
         /* WO. Read as zero */
         goto read_as_zero_64;
     case GICR_PROPBASER:
-        /* LPI's not implemented */
-        goto read_as_zero_64;
+        if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+        /* Remove shareability attribute we don't want dom to flush */
+        *r = v->domain->arch.vits->propbase;
+        return 1;
     case GICR_PENDBASER:
-        /* LPI's not implemented */
-        goto read_as_zero_64;
+        if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+        *r = v->domain->arch.vits->pendbase[v->vcpu_id];
     case GICR_INVLPIR:
         /* WO. Read as zero */
         goto read_as_zero_64;
@@ -203,8 +217,15 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, 
mmio_info_t *info,
     switch ( gicr_reg )
     {
     case GICR_CTLR:
-        /* LPI's not implemented */
-        goto write_ignore_32;
+        /*
+         * Enable LPI's for ITS. Direct injection of LPI
+         * by writing to GICR_{SET,CLR}LPIR are not supported
+         */
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        vgic_lock(v);
+        v->domain->arch.vgic.gicr_ctlr = (*r) & GICR_CTL_ENABLE;
+        vgic_unlock(v);
+        return 1;
     case GICR_IIDR:
         /* RO */
         goto write_ignore_32;
@@ -224,11 +245,27 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, 
mmio_info_t *info,
         /* LPI is not implemented */
         goto write_ignore_64;
     case GICR_PROPBASER:
-        /* LPI is not implemented */
-        goto write_ignore_64;
+        if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+        vgic_lock(v);
+        /* LPI configuration tables are shared across cpus. Should be same */
+        if ( (v->domain->arch.vits->propbase != 0) && 
+             ((v->domain->arch.vits->propbase & 0xfffffffff000UL) !=
+                  (*r & 0xfffffffff000UL)) )
+        {
+            dprintk(XENLOG_G_ERR,
+                "vGICv3: vITS: Wrong configuration of LPI_PROPBASER\n");
+            return 0;
+        }     
+        v->domain->arch.vits->propbase = *r;
+        vgic_unlock(v);
+        return vgic_its_unmap_lpi_prop(v);
     case GICR_PENDBASER:
-        /* LPI is not implemented */
-        goto write_ignore_64;
+        /* Just hold pendbaser value for guest read */
+        if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
+        vgic_lock(v);
+        v->domain->arch.vits->pendbase[v->vcpu_id] = *r;
+        vgic_unlock(v);
+        return 1;
     case GICR_INVLPIR:
         /* LPI is not implemented */
         goto write_ignore_64;
@@ -694,6 +731,14 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, 
mmio_info_t *info)
         *r = ((ncpus - 1) << GICD_TYPE_CPUS_SHIFT |
               DIV_ROUND_UP(v->domain->arch.vgic.nr_spis, 32));
 
+        if ( gic_lpi_supported() )
+        {
+            irq_bits = gic_nr_id_bits();
+            *r |= GICD_TYPE_LPIS;
+        }
+        else
+            irq_bits = get_count_order(vgic_num_irqs(v->domain));
+
         *r |= (irq_bits - 1) << GICD_TYPE_ID_BITS_SHIFT;
 
         return 1;
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index da73cf5..db1d1db 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -102,6 +102,7 @@ struct arch_domain
         paddr_t dbase; /* Distributor base address */
         paddr_t cbase; /* CPU base address */
 #ifdef CONFIG_ARM_64
+       int gicr_ctlr;
         /* GIC V3 addressing */
         paddr_t dbase_size; /* Distributor base size */
         /* List of contiguous occupied by the redistributors */
diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h
index 3271477..1de57a7 100644
--- a/xen/include/asm-arm/gic-its.h
+++ b/xen/include/asm-arm/gic-its.h
@@ -277,6 +277,7 @@ static inline uint32_t its_decode_devid(struct domain *d, 
its_cmd_block *cmd)
 void its_set_affinity(struct irq_desc *desc, int cpu);
 void lpi_set_config(struct irq_desc *desc, int enable);
 uint32_t its_get_nr_events(void);
+int vgic_its_unmap_lpi_prop(struct vcpu *v);
 struct vits_device * find_vits_device(struct rb_root *root, uint32_t devid);
 int insert_vits_device(struct rb_root *root, struct vits_device *dev);
 int remove_vits_device(struct rb_root *root, struct vits_device *dev);
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 0209cc5..ee612de 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -99,6 +99,7 @@
 #define GICD_TYPE_CPUS_SHIFT 5
 #define GICD_TYPE_CPUS  0x0e0
 #define GICD_TYPE_SEC   0x400
+#define GICD_TYPE_LPIS  (0x1UL << 17)
 
 #define GICC_CTL_ENABLE 0x1
 #define GICC_CTL_EOI    (0x1 << 9)
@@ -282,6 +283,10 @@ extern void gic_dump_info(struct vcpu *v);
 
 /* Number of interrupt lines */
 extern unsigned int gic_number_lines(void);
+/* Number of interrupt id bits supported */
+extern unsigned int gic_nr_id_bits(void);
+/* LPI support info */
+bool_t gic_lpi_supported(void);
 
 /* IRQ translation function for the device tree */
 int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
@@ -299,6 +304,10 @@ struct gic_info {
     unsigned int maintenance_irq;
     /* Pointer to the device tree node representing the interrupt controller */
     const struct dt_device_node *node;
+    /* Number of IRQ ID bits supported */
+    uint32_t nr_id_bits;
+    /* LPIs are support information */
+    bool_t lpi_supported; 
 };
 
 struct gic_hw_operations {
diff --git a/xen/include/asm-arm/gic_v3_defs.h 
b/xen/include/asm-arm/gic_v3_defs.h
index dc4fe14..0872097 100644
--- a/xen/include/asm-arm/gic_v3_defs.h
+++ b/xen/include/asm-arm/gic_v3_defs.h
@@ -136,6 +136,7 @@
 #define GICR_TYPER_VLPIS             (1U << 1)
 #define GICR_TYPER_DISTRIBUTED_IMP   (1U << 3)
 #define GICR_TYPER_LAST              (1U << 4)
+#define GICR_TYPER_PROCESSOR_SHIFT   (8)
 
 #define DEFAULT_PMR_VALUE            0xff
 
-- 
1.7.9.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.