All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7a 00/14] GIC and VGIC code refactoring
@ 2014-07-01  6:41 vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 01/14] xen/arm: make sgi handling generic vijay.kilari
                   ` (15 more replies)
  0 siblings, 16 replies; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

Made changes to existing gic and vgic drivers to make it
generic and added support for GIC v3 hw version.

The complete GICv3 patch series
"[PATCH v5 00/21] xen/arm: Add GICv3 support" is split
into two patch series version v6a and v6.

The 14 patches of v7a series is posted here which contains
refactoring of existing GIC and VGIC drivers to accomodate
GICv3 series (v6)

Tested with ARM64 simulator with multicore core
and booted Dom0 kernel.

Major changes in v7a:
 - Made changes to send_SGI() to pass NULL as cpu_mask for 
   sgi modes which does not require cpu mask
 - Renamed update_cpu_lr_mask() clear_cpu_lr_mask()
 - used writeb_relaxed() to access ITARGETR & IPRIORITYR 
   registers

Major changes in v6a:
 - Changed send_SGI parameters ordering
 - coding styles and missing comments
 - New patch (17) to check for idle domain before saving GIC context
 - Introduced new callback in vgic handler for handling SGI

Major changes in v5:
 - Introduced new patch for checking platform capability for gicv3
 - Introduced more patches for vgic clean up and code movement
 - Added synchronization barriers and clean up in GICv3 driver
 - Rebase on top of master branch +
   remotes/origin/no_maintenance_interrupts-v8 patch set
 - Code base available in github
   git clone https://github.com/vijaykilari/Xen-GICv3.git
 - Fixed comments and coding style

Major changes in v4:
 - Changed io handlers to take mmio address and size as
   parameters
 - ioremap is used instead of fixmap to map GICv2 address
   space. Removed /4 in GICv2 register definitions
 - vGIC driver now uses register size to calculate IRQ rank
 - GICv2 LR register definitions are declared locally in GICv2 driver
 - GICR & GICD common register handling in vgic-v3 driver are segregated
   in one common function
 - irq_hw_controller definition is managed in GICv2 and GICv3 drivers
 - Made irq_ops const
 - GIC DT node is updated in respective drivers
 - Comments and coding style fixes
 - Rebased on remotes/origin/no_maintenance_interrupts-v8 + Julien's
   patch set

Major changes in v3:
 - Moved io.h from xen/arch/arm to xen/include/asm-arm
   and renamed as mmio.h
 - Made all the io handlers as domain specific and removed
   check handlers. Instead address and size are passed
 - Cleaned up sgi handling functions in V2 gic driver and
   made generic
 - Removed unused parameters in do_sgi call
 - VGIC driver is chosen based on GIC driver initialized
 - Implemented SGI handling for GICv3 to boot multicore
 - Missing coding style fixes
 - Rebased to remotes/origin/no_maintenance_interrupts-v6
   branch of Stephano's unstable tree

Major Changes in v2:
 - Added per domain io handler
 - Use device api to initialize gic driver
 - Avoid use of void pointer to access common data
 - Moved vgic address information data from domain.h
 - Coding style

Vijaya Kumar K (14):
  xen/arm: make sgi handling generic
  xen/arm: use ioremap to map gic-v2 registers
  xen/arm: segregate and split GIC low level functionality
  xen/arm: move GIC context data structure to gic driver
  xen/arm: use device api to detect GIC version
  xen/arm: switch to dynamic allocation of vgic rank
  xen/arm: prefix byte_read and byte_write functions with vgic
  xen/arm: move vgic defines to vgic header file
  xen/arm: move and rename is_vcpu_running function to sched.h
  xen/arm: move pending_irq structure to vgic header file
  xen/arm: calculate vgic irq rank based on register size
  xen/arm: Remove REG macro in vgic driver
  xen/arm: split vgic driver into generic and vgic-v2 driver
  xen/arm: Restrict saving of gic register for idle domain

 xen/arch/arm/Makefile           |    4 +-
 xen/arch/arm/domain.c           |    2 +
 xen/arch/arm/domain_build.c     |    2 +-
 xen/arch/arm/gic-v2.c           |  684 +++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/gic.c              |  537 ++++++------------------------
 xen/arch/arm/irq.c              |    1 +
 xen/arch/arm/time.c             |    1 +
 xen/arch/arm/vgic-v2.c          |  507 +++++++++++++++++++++++++++++
 xen/arch/arm/vgic.c             |  568 ++++----------------------------
 xen/arch/arm/vpsci.c            |    1 +
 xen/arch/arm/vtimer.c           |    1 +
 xen/include/asm-arm/device.h    |    1 +
 xen/include/asm-arm/domain.h    |   75 +----
 xen/include/asm-arm/gic.h       |  250 +++++++++-----
 xen/include/asm-arm/processor.h |    8 +
 xen/include/asm-arm/vgic.h      |  179 ++++++++++
 xen/include/xen/sched.h         |   14 +
 17 files changed, 1733 insertions(+), 1102 deletions(-)
 create mode 100644 xen/arch/arm/gic-v2.c
 create mode 100644 xen/arch/arm/vgic-v2.c
 create mode 100644 xen/include/asm-arm/vgic.h

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH v7a 01/14] xen/arm: make sgi handling generic
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01 11:13   ` Julien Grall
  2014-07-01  6:41 ` [PATCH v7a 02/14] xen/arm: use ioremap to map gic-v2 registers vijay.kilari
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

move all the hw specific sgi handling functionality
to one function and use it.

-----------------------------------------
changes in v6a: change send_SGI() parameter order
changes in v7a: passed NULL as null for SGIs sent
                with SGI_TARGET_SELF and SGI_TARGET_OTHERS mode

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
 xen/arch/arm/gic.c        |   40 ++++++++++++++++++++++++++--------------
 xen/include/asm-arm/gic.h |    8 ++++++++
 2 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 0ca0234..054e1ca 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -483,21 +483,37 @@ void __init gic_init(void)
     spin_unlock(&gic.lock);
 }
 
-void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi)
+static void send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
+                     const cpumask_t *cpu_mask)
 {
     unsigned int mask = 0;
     cpumask_t online_mask;
 
-    ASSERT(sgi < 16); /* There are only 16 SGIs */
+    switch ( irqmode )
+    {
+    case SGI_TARGET_OTHERS:
+        GICD[GICD_SGIR] = GICD_SGI_TARGET_OTHERS | sgi;
+        break;
+    case SGI_TARGET_SELF:
+        GICD[GICD_SGIR] = GICD_SGI_TARGET_SELF | sgi;
+        break;
+    case SGI_TARGET_LIST:
+        cpumask_and(&online_mask, cpu_mask, &cpu_online_map);
+        mask = gic_cpu_mask(&online_mask);
+        GICD[GICD_SGIR] = GICD_SGI_TARGET_LIST |
+                          (mask << GICD_SGI_TARGET_SHIFT) | sgi;
+        break;
+    default:
+        BUG();
+    }
+}
 
-    cpumask_and(&online_mask, cpumask, &cpu_online_map);
-    mask = gic_cpu_mask(&online_mask);
+void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi)
+{
+    ASSERT(sgi < 16); /* There are only 16 SGIs */
 
     dsb(sy);
-
-    GICD[GICD_SGIR] = GICD_SGI_TARGET_LIST
-        | (mask<<GICD_SGI_TARGET_SHIFT)
-        | sgi;
+    send_SGI(sgi, SGI_TARGET_LIST, cpumask);
 }
 
 void send_SGI_one(unsigned int cpu, enum gic_sgi sgi)
@@ -511,9 +527,7 @@ void send_SGI_self(enum gic_sgi sgi)
     ASSERT(sgi < 16); /* There are only 16 SGIs */
 
     dsb(sy);
-
-    GICD[GICD_SGIR] = GICD_SGI_TARGET_SELF
-        | sgi;
+    send_SGI(sgi, SGI_TARGET_SELF, NULL);
 }
 
 void send_SGI_allbutself(enum gic_sgi sgi)
@@ -521,9 +535,7 @@ void send_SGI_allbutself(enum gic_sgi sgi)
    ASSERT(sgi < 16); /* There are only 16 SGIs */
 
    dsb(sy);
-
-   GICD[GICD_SGIR] = GICD_SGI_TARGET_OTHERS
-       | sgi;
+   send_SGI(sgi, SGI_TARGET_OTHERS, NULL);
 }
 
 void smp_send_state_dump(unsigned int cpu)
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 8e37ccf..c7b7368 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -210,6 +210,14 @@ enum gic_sgi {
     GIC_SGI_DUMP_STATE  = 1,
     GIC_SGI_CALL_FUNCTION = 2,
 };
+
+/* SGI irq mode types */
+enum gic_sgi_mode {
+    SGI_TARGET_LIST,
+    SGI_TARGET_OTHERS,
+    SGI_TARGET_SELF,
+};
+
 extern void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi);
 extern void send_SGI_one(unsigned int cpu, enum gic_sgi sgi);
 extern void send_SGI_self(enum gic_sgi sgi);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 02/14] xen/arm: use ioremap to map gic-v2 registers
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 01/14] xen/arm: make sgi handling generic vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 03/14] xen/arm: segregate and split GIC low level functionality vijay.kilari
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

gic-v2 driver uses fixmap to map the registers.
Instead use ioremap to access mmio registers.

With this patch, gic-v2 register definitions are updated
to use absolute offset address instead of dividing the
register offset by 4.

-------------------------------------
changes in v7a: accessed ITARGETR and IPRIORITYR registers
                using writeb_relaxed() call

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/gic.c        |  165 ++++++++++++++++++++++++---------------------
 xen/arch/arm/vgic.c       |   15 ++---
 xen/include/asm-arm/gic.h |  104 ++++++++++++++--------------
 3 files changed, 149 insertions(+), 135 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 054e1ca..4ac6da3 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -31,20 +31,23 @@
 #include <asm/p2m.h>
 #include <asm/domain.h>
 #include <asm/platform.h>
-
+#include <asm/io.h>
 #include <asm/gic.h>
 
-/* Access to the GIC Distributor registers through the fixmap */
-#define GICD ((volatile uint32_t *) FIXMAP_ADDR(FIXMAP_GICD))
-#define GICC ((volatile uint32_t *) FIXMAP_ADDR(FIXMAP_GICC1))
-#define GICH ((volatile uint32_t *) FIXMAP_ADDR(FIXMAP_GICH))
+#define GICD (gic.map_dbase)
+#define GICC (gic.map_cbase)
+#define GICH (gic.map_hbase)
+
 static void gic_restore_pending_irqs(struct vcpu *v);
 
 /* Global state */
 static struct {
     paddr_t dbase;       /* Address of distributor registers */
+    void __iomem * map_dbase;  /* IO mapped Address of distributor registers */
     paddr_t cbase;       /* Address of CPU interface registers */
+    void __iomem * map_cbase; /* IO mapped Address of CPU interface registers*/
     paddr_t hbase;       /* Address of virtual interface registers */
+    void __iomem * map_hbase; /* IO Address of virtual interface registers */
     paddr_t vbase;       /* Address of virtual cpu interface registers */
     unsigned int lines;  /* Number of interrupts (SPIs + PPIs + SGIs) */
     unsigned int maintenance_irq; /* IRQ maintenance */
@@ -101,12 +104,12 @@ void gic_save_state(struct vcpu *v)
      * accessed simultaneously by another pCPU.
      */
     for ( i=0; i<nr_lrs; i++)
-        v->arch.gic_lr[i] = GICH[GICH_LR + i];
+        v->arch.gic_lr[i] = readl_relaxed(GICH + GICH_LR + i * 4);
     v->arch.lr_mask = this_cpu(lr_mask);
-    v->arch.gic_apr = GICH[GICH_APR];
-    v->arch.gic_vmcr = GICH[GICH_VMCR];
+    v->arch.gic_apr = readl_relaxed(GICH + GICH_APR);
+    v->arch.gic_vmcr = readl_relaxed(GICH + GICH_VMCR);
     /* Disable until next VCPU scheduled */
-    GICH[GICH_HCR] = 0;
+    writel_relaxed(0, GICH + GICH_HCR);
     isb();
 }
 
@@ -120,10 +123,10 @@ void gic_restore_state(struct vcpu *v)
 
     this_cpu(lr_mask) = v->arch.lr_mask;
     for ( i=0; i<nr_lrs; i++)
-        GICH[GICH_LR + i] = v->arch.gic_lr[i];
-    GICH[GICH_APR] = v->arch.gic_apr;
-    GICH[GICH_VMCR] = v->arch.gic_vmcr;
-    GICH[GICH_HCR] = GICH_HCR_EN;
+        writel_relaxed(v->arch.gic_lr[i], GICH + GICH_LR + i * 4);
+    writel_relaxed(v->arch.gic_apr, GICH + GICH_APR);
+    writel_relaxed(v->arch.gic_vmcr, GICH + GICH_VMCR);
+    writel_relaxed(GICH_HCR_EN, GICH + GICH_HCR);
     isb();
 
     gic_restore_pending_irqs(v);
@@ -137,10 +140,10 @@ static void gic_irq_enable(struct irq_desc *desc)
     ASSERT(spin_is_locked(&desc->lock));
 
     spin_lock_irqsave(&gic.lock, flags);
+    /* Enable routing */
     desc->status &= ~IRQ_DISABLED;
     dsb(sy);
-    /* Enable routing */
-    GICD[GICD_ISENABLER + irq / 32] = (1u << (irq % 32));
+    writel_relaxed((1u << (irq % 32)), GICD + GICD_ISENABLER + (irq / 32) * 4);
     spin_unlock_irqrestore(&gic.lock, flags);
 }
 
@@ -153,7 +156,7 @@ static void gic_irq_disable(struct irq_desc *desc)
 
     spin_lock_irqsave(&gic.lock, flags);
     /* Disable routing */
-    GICD[GICD_ICENABLER + irq / 32] = (1u << (irq % 32));
+    writel_relaxed(1u << (irq % 32), GICD + GICD_ICENABLER + (irq / 32) * 4);
     desc->status |= IRQ_DISABLED;
     spin_unlock_irqrestore(&gic.lock, flags);
 }
@@ -179,16 +182,16 @@ static void gic_host_irq_end(struct irq_desc *desc)
 {
     int irq = desc->irq;
     /* Lower the priority */
-    GICC[GICC_EOIR] = irq;
+    writel_relaxed(irq, GICC + GICC_EOIR);
     /* Deactivate */
-    GICC[GICC_DIR] = irq;
+    writel_relaxed(irq, GICC + GICC_DIR);
 }
 
 static void gic_guest_irq_end(struct irq_desc *desc)
 {
     int irq = desc->irq;
     /* Lower the priority of the IRQ */
-    GICC[GICC_EOIR] = irq;
+    writel_relaxed(irq, GICC + GICC_EOIR);
     /* Deactivation happens in maintenance interrupt / via GICV */
 }
 
@@ -229,7 +232,6 @@ static void gic_set_irq_properties(struct irq_desc *desc,
                                    const cpumask_t *cpu_mask,
                                    unsigned int priority)
 {
-    volatile unsigned char *bytereg;
     uint32_t cfg, edgebit;
     unsigned int mask;
     unsigned int irq = desc->irq;
@@ -243,21 +245,18 @@ static void gic_set_irq_properties(struct irq_desc *desc,
     mask = gic_cpu_mask(cpu_mask);
 
     /* Set edge / level */
-    cfg = GICD[GICD_ICFGR + irq / 16];
+    cfg = readl_relaxed(GICD + GICD_ICFGR + (irq / 16) * 4);
     edgebit = 2u << (2 * (irq % 16));
     if ( type & DT_IRQ_TYPE_LEVEL_MASK )
         cfg &= ~edgebit;
     else if ( type & DT_IRQ_TYPE_EDGE_BOTH )
         cfg |= edgebit;
-    GICD[GICD_ICFGR + irq / 16] = cfg;
+    writel_relaxed(cfg, GICD + GICD_ICFGR + (irq / 16) * 4);
 
     /* Set target CPU mask (RAZ/WI on uniprocessor) */
-    bytereg = (unsigned char *) (GICD + GICD_ITARGETSR);
-    bytereg[irq] = mask;
-
+    writeb_relaxed(mask, GICD + GICD_ITARGETSR + irq);
     /* Set priority */
-    bytereg = (unsigned char *) (GICD + GICD_IPRIORITYR);
-    bytereg[irq] = priority;
+    writeb_relaxed(priority, GICD + GICD_IPRIORITYR + irq);
 
     spin_unlock(&gic.lock);
 }
@@ -303,87 +302,94 @@ static void __init gic_dist_init(void)
     uint32_t cpumask;
     int i;
 
-    cpumask = GICD[GICD_ITARGETSR] & 0xff;
+    cpumask = readl_relaxed(GICD + GICD_ITARGETSR) & 0xff;
     cpumask |= cpumask << 8;
     cpumask |= cpumask << 16;
 
     /* Disable the distributor */
-    GICD[GICD_CTLR] = 0;
+    writel_relaxed(0, GICD + GICD_CTLR);
 
-    type = GICD[GICD_TYPER];
+    type = readl_relaxed(GICD + GICD_TYPER);
     gic.lines = 32 * ((type & GICD_TYPE_LINES) + 1);
     gic.cpus = 1 + ((type & GICD_TYPE_CPUS) >> 5);
     printk("GIC: %d lines, %d cpu%s%s (IID %8.8x).\n",
            gic.lines, gic.cpus, (gic.cpus == 1) ? "" : "s",
            (type & GICD_TYPE_SEC) ? ", secure" : "",
-           GICD[GICD_IIDR]);
+           readl_relaxed(GICD + GICD_IIDR));
 
     /* Default all global IRQs to level, active low */
     for ( i = 32; i < gic.lines; i += 16 )
-        GICD[GICD_ICFGR + i / 16] = 0x0;
+        writel_relaxed(0x0, GICD + GICD_ICFGR + (i / 16) * 4);
 
     /* Route all global IRQs to this CPU */
     for ( i = 32; i < gic.lines; i += 4 )
-        GICD[GICD_ITARGETSR + i / 4] = cpumask;
+        writel_relaxed(cpumask, GICD + GICD_ITARGETSR + (i / 4) * 4);
 
     /* Default priority for global interrupts */
     for ( i = 32; i < gic.lines; i += 4 )
-        GICD[GICD_IPRIORITYR + i / 4] =
-            GIC_PRI_IRQ<<24 | GIC_PRI_IRQ<<16 | GIC_PRI_IRQ<<8 | GIC_PRI_IRQ;
+        writel_relaxed (GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
+                        GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
+                        GICD + GICD_IPRIORITYR + (i / 4) * 4);
 
     /* Disable all global interrupts */
     for ( i = 32; i < gic.lines; i += 32 )
-        GICD[GICD_ICENABLER + i / 32] = (uint32_t)~0ul;
+        writel_relaxed(~0x0, GICD + GICD_ICENABLER + (i / 32) * 4);
 
     /* Turn on the distributor */
-    GICD[GICD_CTLR] = GICD_CTL_ENABLE;
+    writel_relaxed(GICD_CTL_ENABLE, GICD + GICD_CTLR);
 }
 
 static void __cpuinit gic_cpu_init(void)
 {
     int i;
 
-    this_cpu(gic_cpu_id) = GICD[GICD_ITARGETSR] & 0xff;
+    this_cpu(gic_cpu_id) = readl_relaxed(GICD + GICD_ITARGETSR) & 0xff;
 
     /* The first 32 interrupts (PPI and SGI) are banked per-cpu, so
      * even though they are controlled with GICD registers, they must
      * be set up here with the other per-cpu state. */
-    GICD[GICD_ICENABLER] = 0xffff0000; /* Disable all PPI */
-    GICD[GICD_ISENABLER] = 0x0000ffff; /* Enable all SGI */
+    writel_relaxed(0xffff0000, GICD + GICD_ICENABLER); /* Disable all PPI */
+    writel_relaxed(0x0000ffff, GICD + GICD_ISENABLER); /* Enable all SGI */
+
     /* Set SGI priorities */
     for (i = 0; i < 16; i += 4)
-        GICD[GICD_IPRIORITYR + i / 4] =
-            GIC_PRI_IPI<<24 | GIC_PRI_IPI<<16 | GIC_PRI_IPI<<8 | GIC_PRI_IPI;
+        writel_relaxed(GIC_PRI_IPI << 24 | GIC_PRI_IPI << 16 |
+                       GIC_PRI_IPI << 8 | GIC_PRI_IPI,
+                       GICD + GICD_IPRIORITYR + (i / 4) * 4);
     /* Set PPI priorities */
     for (i = 16; i < 32; i += 4)
-        GICD[GICD_IPRIORITYR + i / 4] =
-            GIC_PRI_IRQ<<24 | GIC_PRI_IRQ<<16 | GIC_PRI_IRQ<<8 | GIC_PRI_IRQ;
+        writel_relaxed(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
+                      GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
+                      GICD + GICD_IPRIORITYR + (i / 4) * 4);
 
     /* Local settings: interface controller */
-    GICC[GICC_PMR] = 0xff;                /* Don't mask by priority */
-    GICC[GICC_BPR] = 0;                   /* Finest granularity of priority */
-    GICC[GICC_CTLR] = GICC_CTL_ENABLE|GICC_CTL_EOI;    /* Turn on delivery */
+    /* Don't mask by priority */
+    writel_relaxed(0xff, GICC + GICC_PMR);
+    /* Finest granularity of priority */
+    writel_relaxed(0x0, GICC + GICC_BPR);
+    /* Turn on delivery */
+    writel_relaxed(GICC_CTL_ENABLE|GICC_CTL_EOI, GICC + GICC_CTLR);
 }
 
 static void gic_cpu_disable(void)
 {
-    GICC[GICC_CTLR] = 0;
+    writel_relaxed(0x0, GICC + GICC_CTLR);
 }
 
 static void __cpuinit gic_hyp_init(void)
 {
     uint32_t vtr;
 
-    vtr = GICH[GICH_VTR];
+    vtr = readl_relaxed(GICH + GICH_VTR);
     nr_lrs  = (vtr & GICH_VTR_NRLRGS) + 1;
 
-    GICH[GICH_MISR] = GICH_MISR_EOI;
+    writel_relaxed(GICH_MISR_EOI, GICH + GICH_MISR);
     this_cpu(lr_mask) = 0ULL;
 }
 
 static void __cpuinit gic_hyp_disable(void)
 {
-    GICH[GICH_HCR] = 0;
+    writel_relaxed(0, GICH + GICH_HCR);
 }
 
 int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
@@ -462,15 +468,21 @@ void __init gic_init(void)
          (gic.hbase & ~PAGE_MASK) || (gic.vbase & ~PAGE_MASK) )
         panic("GIC interfaces not page aligned");
 
-    set_fixmap(FIXMAP_GICD, gic.dbase >> PAGE_SHIFT, DEV_SHARED);
-    BUILD_BUG_ON(FIXMAP_ADDR(FIXMAP_GICC1) !=
-                 FIXMAP_ADDR(FIXMAP_GICC2)-PAGE_SIZE);
-    set_fixmap(FIXMAP_GICC1, gic.cbase >> PAGE_SHIFT, DEV_SHARED);
+    gic.map_dbase = ioremap_nocache(gic.dbase, PAGE_SIZE);
+    if ( !gic.map_dbase )
+        panic("Failed to ioremap for GIC distributor\n");
+
     if ( platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
-        set_fixmap(FIXMAP_GICC2, (gic.cbase >> PAGE_SHIFT) + 0x10, DEV_SHARED);
+        gic.map_cbase = ioremap_nocache(gic.cbase, PAGE_SIZE * 0x10);
     else
-        set_fixmap(FIXMAP_GICC2, (gic.cbase >> PAGE_SHIFT) + 0x1, DEV_SHARED);
-    set_fixmap(FIXMAP_GICH, gic.hbase >> PAGE_SHIFT, DEV_SHARED);
+        gic.map_cbase = ioremap_nocache(gic.cbase, PAGE_SIZE * 2);
+
+    if ( !gic.map_cbase )
+        panic("Failed to ioremap for GIC CPU interface\n");
+
+    gic.map_hbase = ioremap_nocache(gic.hbase, PAGE_SIZE);
+    if ( !gic.map_hbase )
+        panic("Failed to ioremap for GIC Virtual interface\n");
 
     /* Global settings: interrupt distributor */
     spin_lock_init(&gic.lock);
@@ -492,16 +504,17 @@ static void send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
     switch ( irqmode )
     {
     case SGI_TARGET_OTHERS:
-        GICD[GICD_SGIR] = GICD_SGI_TARGET_OTHERS | sgi;
+        writel_relaxed(GICD_SGI_TARGET_OTHERS | sgi, GICD + GICD_SGIR);
         break;
     case SGI_TARGET_SELF:
-        GICD[GICD_SGIR] = GICD_SGI_TARGET_SELF | sgi;
+        writel_relaxed(GICD_SGI_TARGET_SELF | sgi, GICD + GICD_SGIR);
         break;
     case SGI_TARGET_LIST:
         cpumask_and(&online_mask, cpu_mask, &cpu_online_map);
         mask = gic_cpu_mask(&online_mask);
-        GICD[GICD_SGIR] = GICD_SGI_TARGET_LIST |
-                          (mask << GICD_SGI_TARGET_SHIFT) | sgi;
+        writel_relaxed(GICD_SGI_TARGET_LIST |
+                       (mask << GICD_SGI_TARGET_SHIFT) | sgi,
+                       GICD + GICD_SGIR);
         break;
     default:
         BUG();
@@ -578,7 +591,7 @@ static inline void gic_set_lr(int lr, struct pending_irq *p,
     if ( p->desc != NULL )
         lr_val |= GICH_LR_HW | (p->desc->irq << GICH_LR_PHYSICAL_SHIFT);
 
-    GICH[GICH_LR + lr] = lr_val;
+    writel_relaxed(lr_val, GICH + GICH_LR + lr * 4);
 
     set_bit(GIC_IRQ_GUEST_VISIBLE, &p->status);
     clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status);
@@ -663,7 +676,7 @@ static void gic_update_one_lr(struct vcpu *v, int i)
     ASSERT(spin_is_locked(&v->arch.vgic.lock));
     ASSERT(!local_irq_is_enabled());
 
-    lr = GICH[GICH_LR + i];
+    lr = readl_relaxed(GICH + GICH_LR + i * 4);
     irq = (lr >> GICH_LR_VIRTUAL_SHIFT) & GICH_LR_VIRTUAL_MASK;
     p = irq_to_pending(v, irq);
     if ( lr & GICH_LR_ACTIVE )
@@ -673,7 +686,7 @@ static void gic_update_one_lr(struct vcpu *v, int i)
              test_and_clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status) )
         {
             if ( p->desc == NULL )
-                GICH[GICH_LR + i] = lr | GICH_LR_PENDING;
+                writel_relaxed(lr | GICH_LR_PENDING, GICH + GICH_LR + i * 4);
             else
                 gdprintk(XENLOG_WARNING, "unable to inject hw irq=%d into d%dv%d: already active in LR%d\n",
                          irq, v->domain->domain_id, v->vcpu_id, i);
@@ -686,7 +699,7 @@ static void gic_update_one_lr(struct vcpu *v, int i)
                     irq, v->domain->domain_id, v->vcpu_id, i);
 #endif
     } else {
-        GICH[GICH_LR + i] = 0;
+        writel_relaxed(0, GICH + GICH_LR + i * 4);
         clear_bit(i, &this_cpu(lr_mask));
 
         if ( p->desc != NULL )
@@ -794,12 +807,13 @@ int gic_events_need_delivery(void)
     struct vcpu *v = current;
     struct pending_irq *p;
     unsigned long flags;
-    const unsigned long apr = GICH[GICH_APR];
+    const unsigned long apr = readl_relaxed(GICH + GICH_APR);
     int mask_priority;
     int active_priority;
     int rc = 0;
 
-    mask_priority = (GICH[GICH_VMCR] >> GICH_VMCR_PRIORITY_SHIFT) & GICH_VMCR_PRIORITY_MASK;
+    mask_priority = (readl_relaxed(GICH + GICH_VMCR)
+                     >> GICH_VMCR_PRIORITY_SHIFT) & GICH_VMCR_PRIORITY_MASK;
     active_priority = find_next_bit(&apr, 32, 0);
 
     spin_lock_irqsave(&v->arch.vgic.lock, flags);
@@ -829,22 +843,23 @@ out:
 
 void gic_inject(void)
 {
+    uint32_t hcr;
     ASSERT(!local_irq_is_enabled());
 
     gic_restore_pending_irqs(current);
 
+    hcr = readl_relaxed(GICH + GICH_HCR);
 
     if ( !list_empty(&current->arch.vgic.lr_pending) && lr_all_full() )
-        GICH[GICH_HCR] |= GICH_HCR_UIE;
+        writel_relaxed(hcr | GICH_HCR_UIE, GICH + GICH_HCR);
     else
-        GICH[GICH_HCR] &= ~GICH_HCR_UIE;
-
+        writel_relaxed(hcr & ~GICH_HCR_UIE, GICH + GICH_HCR);
 }
 
 static void do_sgi(struct cpu_user_regs *regs, enum gic_sgi sgi)
 {
     /* Lower the priority */
-    GICC[GICC_EOIR] = sgi;
+    writel_relaxed(sgi, GICC + GICC_EOIR);
 
     switch (sgi)
     {
@@ -863,7 +878,7 @@ static void do_sgi(struct cpu_user_regs *regs, enum gic_sgi sgi)
     }
 
     /* Deactivate */
-    GICC[GICC_DIR] = sgi;
+    writel_relaxed(sgi, GICC + GICC_DIR);
 }
 
 /* Accept an interrupt from the GIC and dispatch its handler */
@@ -874,7 +889,7 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
 
 
     do  {
-        intack = GICC[GICC_IAR];
+        intack = readl_relaxed(GICC + GICC_IAR);
         irq = intack & GICC_IA_IRQ;
 
         if ( likely(irq >= 16 && irq < 1021) )
@@ -961,7 +976,7 @@ void gic_dump_info(struct vcpu *v)
     if ( v == current )
     {
         for ( i = 0; i < nr_lrs; i++ )
-            printk("   HW_LR[%d]=%x\n", i, GICH[GICH_LR + i]);
+            printk("   HW_LR[%d]=%x\n", i, readl_relaxed(GICH + GICH_LR + i * 4));
     } else {
         for ( i = 0; i < nr_lrs; i++ )
             printk("   VCPU_LR[%d]=%x\n", i, v->arch.gic_lr[i]);
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 074d2f3..139c2e9 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -30,7 +30,7 @@
 #include <asm/mmio.h>
 #include <asm/gic.h>
 
-#define REG(n) (n/4)
+#define REG(n) (n)
 
 /* Number of ranks of interrupt registers for a domain */
 #define DOMAIN_NR_RANKS(d) (((d)->arch.vgic.nr_lines+31)/32)
@@ -58,7 +58,7 @@ static inline int REG_RANK_NR(int b, uint32_t n)
  * Offset of GICD_<FOO><n> with its rank, for GICD_<FOO> with
  * <b>-bits-per-interrupt.
  */
-#define REG_RANK_INDEX(b, n) ((n) & ((b)-1))
+#define REG_RANK_INDEX(b, n) (((n) >> 2) & ((b)-1))
 
 /*
  * Returns rank corresponding to a GICD_<FOO><n> register for
@@ -66,7 +66,7 @@ static inline int REG_RANK_NR(int b, uint32_t n)
  */
 static struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n)
 {
-    int rank = REG_RANK_NR(b, n);
+    int rank = REG_RANK_NR(b, (n >> 2));
 
     if ( rank == 0 )
         return &v->arch.vgic.private_irqs;
@@ -78,7 +78,7 @@ static struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n)
 
 static struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq)
 {
-    return vgic_rank_offset(v, 8, irq >> 2);
+    return vgic_rank_offset(v, 8, irq);
 }
 
 static const struct mmio_handler_ops vgic_distr_mmio_handler = {
@@ -552,7 +552,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         tr = rank->ienable;
         rank->ienable |= *r;
         vgic_unlock_rank(v, rank);
-        vgic_enable_irqs(v, (*r) & (~tr), gicd_reg - GICD_ISENABLER);
+        vgic_enable_irqs(v, (*r) & (~tr), (gicd_reg - GICD_ISENABLER) >> 2);
         return 1;
 
     case GICD_ICENABLER ... GICD_ICENABLERN:
@@ -563,7 +563,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         tr = rank->ienable;
         rank->ienable &= ~*r;
         vgic_unlock_rank(v, rank);
-        vgic_disable_irqs(v, (*r) & tr, gicd_reg - GICD_ICENABLER);
+        vgic_disable_irqs(v, (*r) & tr, (gicd_reg - GICD_ICENABLER) >> 2);
         return 1;
 
     case GICD_ISPENDR ... GICD_ISPENDRN:
@@ -725,7 +725,6 @@ void vgic_clear_pending_irqs(struct vcpu *v)
 
 void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
 {
-    int idx = irq >> 2, byte = irq & 0x3;
     uint8_t priority;
     struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
     struct pending_irq *iter, *n = irq_to_pending(v, irq);
@@ -748,7 +747,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
         return;
     }
 
-    priority = byte_read(rank->ipriority[REG_RANK_INDEX(8, idx)], 0, byte);
+    priority = byte_read(rank->ipriority[REG_RANK_INDEX(8, irq)], 0, irq & 0x3);
 
     n->irq = irq;
     set_bit(GIC_IRQ_GUEST_QUEUED, &n->status);
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index c7b7368..7fa3b95 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -18,37 +18,37 @@
 #ifndef __ASM_ARM_GIC_H__
 #define __ASM_ARM_GIC_H__
 
-#define GICD_CTLR       (0x000/4)
-#define GICD_TYPER      (0x004/4)
-#define GICD_IIDR       (0x008/4)
-#define GICD_IGROUPR    (0x080/4)
-#define GICD_IGROUPRN   (0x0FC/4)
-#define GICD_ISENABLER  (0x100/4)
-#define GICD_ISENABLERN (0x17C/4)
-#define GICD_ICENABLER  (0x180/4)
-#define GICD_ICENABLERN (0x1fC/4)
-#define GICD_ISPENDR    (0x200/4)
-#define GICD_ISPENDRN   (0x27C/4)
-#define GICD_ICPENDR    (0x280/4)
-#define GICD_ICPENDRN   (0x2FC/4)
-#define GICD_ISACTIVER  (0x300/4)
-#define GICD_ISACTIVERN (0x37C/4)
-#define GICD_ICACTIVER  (0x380/4)
-#define GICD_ICACTIVERN (0x3FC/4)
-#define GICD_IPRIORITYR (0x400/4)
-#define GICD_IPRIORITYRN (0x7F8/4)
-#define GICD_ITARGETSR  (0x800/4)
-#define GICD_ITARGETSRN (0xBF8/4)
-#define GICD_ICFGR      (0xC00/4)
-#define GICD_ICFGRN     (0xCFC/4)
-#define GICD_NSACR      (0xE00/4)
-#define GICD_NSACRN     (0xEFC/4)
-#define GICD_SGIR       (0xF00/4)
-#define GICD_CPENDSGIR  (0xF10/4)
-#define GICD_CPENDSGIRN (0xF1C/4)
-#define GICD_SPENDSGIR  (0xF20/4)
-#define GICD_SPENDSGIRN (0xF2C/4)
-#define GICD_ICPIDR2    (0xFE8/4)
+#define GICD_CTLR       (0x000)
+#define GICD_TYPER      (0x004)
+#define GICD_IIDR       (0x008)
+#define GICD_IGROUPR    (0x080)
+#define GICD_IGROUPRN   (0x0FC)
+#define GICD_ISENABLER  (0x100)
+#define GICD_ISENABLERN (0x17C)
+#define GICD_ICENABLER  (0x180)
+#define GICD_ICENABLERN (0x1fC)
+#define GICD_ISPENDR    (0x200)
+#define GICD_ISPENDRN   (0x27C)
+#define GICD_ICPENDR    (0x280)
+#define GICD_ICPENDRN   (0x2FC)
+#define GICD_ISACTIVER  (0x300)
+#define GICD_ISACTIVERN (0x37C)
+#define GICD_ICACTIVER  (0x380)
+#define GICD_ICACTIVERN (0x3FC)
+#define GICD_IPRIORITYR (0x400)
+#define GICD_IPRIORITYRN (0x7F8)
+#define GICD_ITARGETSR  (0x800)
+#define GICD_ITARGETSRN (0xBF8)
+#define GICD_ICFGR      (0xC00)
+#define GICD_ICFGRN     (0xCFC)
+#define GICD_NSACR      (0xE00)
+#define GICD_NSACRN     (0xEFC)
+#define GICD_SGIR       (0xF00)
+#define GICD_CPENDSGIR  (0xF10)
+#define GICD_CPENDSGIRN (0xF1C)
+#define GICD_SPENDSGIR  (0xF20)
+#define GICD_SPENDSGIRN (0xF2C)
+#define GICD_ICPIDR2    (0xFE8)
 
 #define GICD_SGI_TARGET_LIST_SHIFT   (24)
 #define GICD_SGI_TARGET_LIST_MASK    (0x3UL << GICD_SGI_TARGET_LIST_SHIFT)
@@ -60,27 +60,27 @@
 #define GICD_SGI_GROUP1              (1UL<<15)
 #define GICD_SGI_INTID_MASK          (0xFUL)
 
-#define GICC_CTLR       (0x0000/4)
-#define GICC_PMR        (0x0004/4)
-#define GICC_BPR        (0x0008/4)
-#define GICC_IAR        (0x000C/4)
-#define GICC_EOIR       (0x0010/4)
-#define GICC_RPR        (0x0014/4)
-#define GICC_HPPIR      (0x0018/4)
-#define GICC_APR        (0x00D0/4)
-#define GICC_NSAPR      (0x00E0/4)
-#define GICC_DIR        (0x1000/4)
-
-#define GICH_HCR        (0x00/4)
-#define GICH_VTR        (0x04/4)
-#define GICH_VMCR       (0x08/4)
-#define GICH_MISR       (0x10/4)
-#define GICH_EISR0      (0x20/4)
-#define GICH_EISR1      (0x24/4)
-#define GICH_ELSR0      (0x30/4)
-#define GICH_ELSR1      (0x34/4)
-#define GICH_APR        (0xF0/4)
-#define GICH_LR         (0x100/4)
+#define GICC_CTLR       (0x0000)
+#define GICC_PMR        (0x0004)
+#define GICC_BPR        (0x0008)
+#define GICC_IAR        (0x000C)
+#define GICC_EOIR       (0x0010)
+#define GICC_RPR        (0x0014)
+#define GICC_HPPIR      (0x0018)
+#define GICC_APR        (0x00D0)
+#define GICC_NSAPR      (0x00E0)
+#define GICC_DIR        (0x1000)
+
+#define GICH_HCR        (0x00)
+#define GICH_VTR        (0x04)
+#define GICH_VMCR       (0x08)
+#define GICH_MISR       (0x10)
+#define GICH_EISR0      (0x20)
+#define GICH_EISR1      (0x24)
+#define GICH_ELSR0      (0x30)
+#define GICH_ELSR1      (0x34)
+#define GICH_APR        (0xF0)
+#define GICH_LR         (0x100)
 
 /* Register bits */
 #define GICD_CTL_ENABLE 0x1
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 03/14] xen/arm: segregate and split GIC low level functionality
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 01/14] xen/arm: make sgi handling generic vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 02/14] xen/arm: use ioremap to map gic-v2 registers vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01 11:32   ` Julien Grall
  2014-07-01  6:41 ` [PATCH v7a 04/14] xen/arm: move GIC context data structure to gic driver vijay.kilari
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

GIC driver contains both generic and hardware specific low
level functionality in gic.c file.

With this patch, low level functionality is moved to separate
file gic-v2.c and generic code is kept in gic.c file

Callbacks are registered by low level driver with generic driver
and are called wherever required.

The locking mechanism is not changed.

This helps to separate generic and hardware functionality
and implement future hardware version drivers.

-------------------------------------------------------------
Changes in v7a:
           -Renamed update_cpu_lr_mask() to clear_cpu_lr_mask().
           -Reflected changes made to gic.c in patch 1 & 2
            to gic-v2.c

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
 xen/arch/arm/Makefile     |    2 +-
 xen/arch/arm/gic-v2.c     |  679 +++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/gic.c        |  546 +++++-------------------------------
 xen/include/asm-arm/gic.h |  107 +++++--
 4 files changed, 837 insertions(+), 497 deletions(-)

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 63e0460..969ee52 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -10,7 +10,7 @@ obj-y += vpsci.o
 obj-y += domctl.o
 obj-y += sysctl.o
 obj-y += domain_build.o
-obj-y += gic.o
+obj-y += gic.o gic-v2.o
 obj-y += io.o
 obj-y += irq.o
 obj-y += kernel.o
diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
new file mode 100644
index 0000000..3539cb8
--- /dev/null
+++ b/xen/arch/arm/gic-v2.c
@@ -0,0 +1,679 @@
+/*
+ * xen/arch/arm/gic-v2.c
+ *
+ * ARM Generic Interrupt Controller support v2
+ *
+ * Tim Deegan <tim@xen.org>
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/irq.h>
+#include <xen/sched.h>
+#include <xen/errno.h>
+#include <xen/softirq.h>
+#include <xen/list.h>
+#include <xen/device_tree.h>
+#include <asm/p2m.h>
+#include <asm/domain.h>
+#include <asm/platform.h>
+
+#include <asm/io.h>
+#include <asm/gic.h>
+
+/*
+ * LR register definitions are GIC v2 specific.
+ * Moved these definitions from header file to here
+ */
+#define GICH_V2_LR_VIRTUAL_MASK    0x3ff
+#define GICH_V2_LR_VIRTUAL_SHIFT   0
+#define GICH_V2_LR_PHYSICAL_MASK   0x3ff
+#define GICH_V2_LR_PHYSICAL_SHIFT  10
+#define GICH_V2_LR_STATE_MASK      0x3
+#define GICH_V2_LR_STATE_SHIFT     28
+#define GICH_V2_LR_PRIORITY_SHIFT  23
+#define GICH_V2_LR_PRIORITY_MASK   0x1f
+#define GICH_V2_LR_HW_SHIFT        31
+#define GICH_V2_LR_HW_MASK         0x1
+#define GICH_V2_LR_GRP_SHIFT       30
+#define GICH_V2_LR_GRP_MASK        0x1
+#define GICH_V2_LR_MAINTENANCE_IRQ (1<<19)
+#define GICH_V2_LR_GRP1            (1<<30)
+#define GICH_V2_LR_HW              (1<<31)
+#define GICH_V2_LR_CPUID_SHIFT     9
+#define GICH_V2_VTR_NRLRGS         0x3f
+
+#define GICH_V2_VMCR_PRIORITY_MASK   0x1f
+#define GICH_V2_VMCR_PRIORITY_SHIFT  27
+
+#define GICD (gicv2.map_dbase)
+#define GICC (gicv2.map_cbase)
+#define GICH (gicv2.map_hbase)
+
+/* Global state */
+static struct {
+    paddr_t dbase;            /* Address of distributor registers */
+    void __iomem * map_dbase; /* IO mapped Address of distributor registers */
+    paddr_t cbase;            /* Address of CPU interface registers */
+    void __iomem * map_cbase; /* IO mapped Address of CPU interface registers*/
+    paddr_t hbase;            /* Address of virtual interface registers */
+    void __iomem * map_hbase; /* IO Address of virtual interface registers */
+    paddr_t vbase;            /* Address of virtual cpu interface registers */
+    spinlock_t lock;
+} gicv2;
+
+static struct gic_info gicv2_info;
+
+/* The GIC mapping of CPU interfaces does not necessarily match the
+ * logical CPU numbering. Let's use mapping as returned by the GIC
+ * itself
+ */
+static DEFINE_PER_CPU(u8, gic_cpu_id);
+
+/* Maximum cpu interface per GIC */
+#define NR_GIC_CPU_IF 8
+
+static unsigned int gicv2_cpu_mask(const cpumask_t *cpumask)
+{
+    unsigned int cpu;
+    unsigned int mask = 0;
+    cpumask_t possible_mask;
+
+    cpumask_and(&possible_mask, cpumask, &cpu_possible_map);
+    for_each_cpu( cpu, &possible_mask )
+    {
+        ASSERT(cpu < NR_GIC_CPU_IF);
+        mask |= per_cpu(gic_cpu_id, cpu);
+    }
+
+    return mask;
+}
+
+static void gicv2_save_state(struct vcpu *v)
+{
+    int i;
+
+    /* No need for spinlocks here because interrupts are disabled around
+     * this call and it only accesses struct vcpu fields that cannot be
+     * accessed simultaneously by another pCPU.
+     */
+    for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+        v->arch.gic_lr[i] = readl_relaxed(GICH + GICH_LR + i * 4);
+
+    v->arch.gic_apr = readl_relaxed(GICH + GICH_APR);
+    v->arch.gic_vmcr = readl_relaxed(GICH + GICH_VMCR);
+    /* Disable until next VCPU scheduled */
+    writel_relaxed(0, GICH + GICH_HCR);
+}
+
+static void gicv2_restore_state(const struct vcpu *v)
+{
+    int i;
+
+    for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+        writel_relaxed(v->arch.gic_lr[i], GICH + GICH_LR + i * 4);
+
+    writel_relaxed(v->arch.gic_apr, GICH + GICH_APR);
+    writel_relaxed(v->arch.gic_vmcr, GICH + GICH_VMCR);
+    writel_relaxed(GICH_HCR_EN, GICH + GICH_HCR);
+}
+
+static void gicv2_dump_state(const struct vcpu *v)
+{
+    int i;
+
+    if ( v == current )
+    {
+        for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+            printk("   HW_LR[%d]=%x\n", i,
+                   readl_relaxed(GICH + GICH_LR + i * 4));
+    }
+    else
+    {
+        for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+            printk("   VCPU_LR[%d]=%x\n", i, v->arch.gic_lr[i]);
+    }
+}
+
+static void gicv2_eoi_irq(struct irq_desc *irqd)
+{
+    int irq = irqd->irq;
+    /* Lower the priority */
+    writel_relaxed(irq, GICC + GICC_EOIR);
+}
+
+static void gicv2_dir_irq(struct irq_desc *irqd)
+{
+    /* Deactivate */
+    writel_relaxed(irqd->irq, GICC + GICC_DIR);
+}
+
+static unsigned int gicv2_read_irq(void)
+{
+    return (readl_relaxed(GICC + GICC_IAR) & GICC_IA_IRQ);
+}
+
+/*
+ * needs to be called with a valid cpu_mask, ie each cpu in the mask has
+ * already called gic_cpu_init
+ */
+static void gicv2_set_irq_properties(struct irq_desc *desc,
+                                   const cpumask_t *cpu_mask,
+                                   unsigned int priority)
+{
+    uint32_t cfg, edgebit;
+    unsigned int mask = gicv2_cpu_mask(cpu_mask);
+    unsigned int irq = desc->irq;
+    unsigned int type = desc->arch.type;
+
+    ASSERT(type != DT_IRQ_TYPE_INVALID);
+    ASSERT(spin_is_locked(&desc->lock));
+
+    spin_lock(&gicv2.lock);
+    /* Set edge / level */
+    cfg = readl_relaxed(GICD + GICD_ICFGR + (irq / 16) * 4);
+    edgebit = 2u << (2 * (irq % 16));
+    if ( type & DT_IRQ_TYPE_LEVEL_MASK )
+        cfg &= ~edgebit;
+    else if ( type & DT_IRQ_TYPE_EDGE_BOTH )
+        cfg |= edgebit;
+    writel_relaxed(cfg, GICD + GICD_ICFGR + (irq / 16) * 4);
+
+    /* Set target CPU mask (RAZ/WI on uniprocessor) */
+    writeb_relaxed(mask, GICD + GICD_ITARGETSR + irq);
+    /* Set priority */
+    writeb_relaxed(priority, GICD + GICD_IPRIORITYR + irq);
+
+    spin_unlock(&gicv2.lock);
+}
+
+static void __init gicv2_dist_init(void)
+{
+    uint32_t type;
+    uint32_t cpumask;
+    uint32_t gic_cpus;
+    int i;
+
+    cpumask = readl_relaxed(GICD + GICD_ITARGETSR) & 0xff;
+    cpumask |= cpumask << 8;
+    cpumask |= cpumask << 16;
+
+    /* Disable the distributor */
+    writel_relaxed(0, GICD + GICD_CTLR);
+
+    type = readl_relaxed(GICD + GICD_TYPER);
+    gicv2_info.nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1);
+    gic_cpus = 1 + ((type & GICD_TYPE_CPUS) >> 5);
+    printk("GICv2: %d lines, %d cpu%s%s (IID %8.8x).\n",
+           gicv2_info.nr_lines, gic_cpus, (gic_cpus == 1) ? "" : "s",
+           (type & GICD_TYPE_SEC) ? ", secure" : "",
+           readl_relaxed(GICD + GICD_IIDR));
+
+    /* Default all global IRQs to level, active low */
+    for ( i = 32; i < gicv2_info.nr_lines; i += 16 )
+        writel_relaxed(0x0, GICD + GICD_ICFGR + (i / 16) * 4);
+
+    /* Route all global IRQs to this CPU */
+    for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
+        writel_relaxed(cpumask, GICD + GICD_ITARGETSR + (i / 4) * 4);
+
+    /* Default priority for global interrupts */
+    for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
+        writel_relaxed (GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
+                        GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
+                        GICD + GICD_IPRIORITYR + (i / 4) * 4);
+
+    /* Disable all global interrupts */
+    for ( i = 32; i < gicv2_info.nr_lines; i += 32 )
+        writel_relaxed(~0x0, GICD + GICD_ICENABLER + (i / 32) * 4);
+
+    /* Turn on the distributor */
+    writel_relaxed(GICD_CTL_ENABLE, GICD + GICD_CTLR);
+}
+
+static void __cpuinit gicv2_cpu_init(void)
+{
+    int i;
+
+    this_cpu(gic_cpu_id) = readl_relaxed(GICD + GICD_ITARGETSR) & 0xff;
+
+    /* The first 32 interrupts (PPI and SGI) are banked per-cpu, so
+     * even though they are controlled with GICD registers, they must
+     * be set up here with the other per-cpu state. */
+    writel_relaxed(0xffff0000, GICD + GICD_ICENABLER); /* Disable all PPI */
+    writel_relaxed(0x0000ffff, GICD + GICD_ISENABLER); /* Enable all SGI */
+
+    /* Set SGI priorities */
+    for ( i = 0; i < 16; i += 4 )
+        writel_relaxed(GIC_PRI_IPI << 24 | GIC_PRI_IPI << 16 |
+                       GIC_PRI_IPI << 8 | GIC_PRI_IPI,
+                       GICD + GICD_IPRIORITYR + (i / 4) * 4);
+
+    /* Set PPI priorities */
+    for ( i = 16; i < 32; i += 4 )
+        writel_relaxed(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
+                      GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
+                      GICD + GICD_IPRIORITYR + (i / 4) * 4);
+
+    /* Local settings: interface controller */
+    /* Don't mask by priority */
+    writel_relaxed(0xff, GICC + GICC_PMR);
+    /* Finest granularity of priority */
+    writel_relaxed(0x0, GICC + GICC_BPR);
+    /* Turn on delivery */
+    writel_relaxed(GICC_CTL_ENABLE|GICC_CTL_EOI, GICC + GICC_CTLR);
+}
+
+static void gicv2_cpu_disable(void)
+{
+    writel_relaxed(0x0, GICC + GICC_CTLR);
+}
+
+static void __cpuinit gicv2_hyp_init(void)
+{
+    uint32_t vtr;
+    uint8_t nr_lrs;
+
+    vtr = readl_relaxed(GICH + GICH_VTR);
+    nr_lrs  = (vtr & GICH_V2_VTR_NRLRGS) + 1;
+    gicv2_info.nr_lrs = nr_lrs;
+
+    writel_relaxed(GICH_MISR_EOI, GICH + GICH_MISR);
+}
+
+static void __cpuinit gicv2_hyp_disable(void)
+{
+    writel_relaxed(0, GICH + GICH_HCR);
+}
+
+static int gicv2_secondary_cpu_init(void)
+{
+    spin_lock(&gicv2.lock);
+
+    gicv2_cpu_init();
+    gicv2_hyp_init();
+
+    spin_unlock(&gicv2.lock);
+
+    return 0;
+}
+
+static void gicv2_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
+                           const cpumask_t *cpu_mask)
+{
+    unsigned int mask = 0;
+    cpumask_t online_mask;
+
+    switch ( irqmode )
+    {
+    case SGI_TARGET_OTHERS:
+        writel_relaxed(GICD_SGI_TARGET_OTHERS | sgi, GICD + GICD_SGIR);
+        break;
+    case SGI_TARGET_SELF:
+        writel_relaxed(GICD_SGI_TARGET_SELF | sgi, GICD + GICD_SGIR);
+        break;
+    case SGI_TARGET_LIST:
+        cpumask_and(&online_mask, cpu_mask, &cpu_online_map);
+        mask = gicv2_cpu_mask(&online_mask);
+        writel_relaxed(GICD_SGI_TARGET_LIST |
+                       (mask << GICD_SGI_TARGET_SHIFT) | sgi,
+                       GICD + GICD_SGIR);
+        break;
+    default:
+        BUG();
+    }
+}
+
+/* Shut down the per-CPU GIC interface */
+static void gicv2_disable_interface(void)
+{
+    spin_lock(&gicv2.lock);
+    gicv2_cpu_disable();
+    gicv2_hyp_disable();
+    spin_unlock(&gicv2.lock);
+}
+
+static void gicv2_update_lr(int lr, const struct pending_irq *p,
+                            unsigned int state)
+{
+    uint32_t lr_reg;
+
+    BUG_ON(lr >= gicv2_info.nr_lrs);
+    BUG_ON(lr < 0);
+
+    lr_reg = (((state & GICH_V2_LR_STATE_MASK) << GICH_V2_LR_STATE_SHIFT)  |
+              ((GIC_PRI_TO_GUEST(p->priority) & GICH_V2_LR_PRIORITY_MASK)
+                                             << GICH_V2_LR_PRIORITY_SHIFT) |
+              ((p->irq & GICH_V2_LR_VIRTUAL_MASK) << GICH_V2_LR_VIRTUAL_SHIFT));
+
+    if ( p->desc != NULL )
+        lr_reg |= GICH_V2_LR_HW | ((p->desc->irq & GICH_V2_LR_PHYSICAL_MASK )
+                                  << GICH_V2_LR_PHYSICAL_SHIFT);
+
+    writel_relaxed(lr_reg, GICH + GICH_LR + lr * 4);
+}
+
+static void gicv2_clear_lr(int lr)
+{
+    writel_relaxed(0, GICH + GICH_LR + lr * 4);
+}
+
+static int gicv_v2_init(struct domain *d)
+{
+    int ret;
+
+    /*
+     * Domain 0 gets the hardware address.
+     * Guests get the virtual platform layout.
+     */
+    if ( is_hardware_domain(d) )
+    {
+        d->arch.vgic.dbase = gicv2.dbase;
+        d->arch.vgic.cbase = gicv2.cbase;
+    }
+    else
+    {
+        d->arch.vgic.dbase = GUEST_GICD_BASE;
+        d->arch.vgic.cbase = GUEST_GICC_BASE;
+    }
+
+    d->arch.vgic.nr_lines = 0;
+
+    /*
+     * Map the gic virtual cpu interface in the gic cpu interface
+     * region of the guest.
+     *
+     * The second page is always mapped at +4K irrespective of the
+     * GIC_64K_STRIDE quirk. The DTB passed to the guest reflects this.
+     */
+    ret = map_mmio_regions(d, d->arch.vgic.cbase,
+                           d->arch.vgic.cbase + PAGE_SIZE - 1,
+                           gicv2.vbase);
+    if ( ret )
+        return ret;
+
+    if ( !platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
+        ret = map_mmio_regions(d, d->arch.vgic.cbase + PAGE_SIZE,
+                               d->arch.vgic.cbase + (2 * PAGE_SIZE) - 1,
+                               gicv2.vbase + PAGE_SIZE);
+    else
+        ret = map_mmio_regions(d, d->arch.vgic.cbase + PAGE_SIZE,
+                               d->arch.vgic.cbase + (2 * PAGE_SIZE) - 1,
+                               gicv2.vbase + 16*PAGE_SIZE);
+
+    return ret;
+}
+
+static void gicv2_read_lr(int lr, struct gic_lr *lr_reg)
+{
+    uint32_t lrv;
+
+    lrv          = readl_relaxed(GICH + GICH_LR + lr * 4);
+    lr_reg->pirq = (lrv >> GICH_V2_LR_PHYSICAL_SHIFT) & GICH_V2_LR_PHYSICAL_MASK;
+    lr_reg->virq = (lrv >> GICH_V2_LR_VIRTUAL_SHIFT) & GICH_V2_LR_VIRTUAL_MASK;
+    lr_reg->priority = (lrv >> GICH_V2_LR_PRIORITY_SHIFT) & GICH_V2_LR_PRIORITY_MASK;
+    lr_reg->state     = (lrv >> GICH_V2_LR_STATE_SHIFT) & GICH_V2_LR_STATE_MASK;
+    lr_reg->hw_status = (lrv >> GICH_V2_LR_HW_SHIFT) & GICH_V2_LR_HW_MASK;
+    lr_reg->grp       = (lrv >> GICH_V2_LR_GRP_SHIFT) & GICH_V2_LR_GRP_MASK;
+}
+
+static void gicv2_write_lr(int lr, const struct gic_lr *lr_reg)
+{
+    uint32_t lrv = 0;
+
+    lrv = ( ((lr_reg->pirq & GICH_V2_LR_PHYSICAL_MASK) << GICH_V2_LR_PHYSICAL_SHIFT) |
+          ((lr_reg->virq & GICH_V2_LR_VIRTUAL_MASK) << GICH_V2_LR_VIRTUAL_SHIFT)   |
+          ((uint32_t)(lr_reg->priority & GICH_V2_LR_PRIORITY_MASK)
+                                      << GICH_V2_LR_PRIORITY_SHIFT) |
+          ((uint32_t)(lr_reg->state & GICH_V2_LR_STATE_MASK)
+                                   << GICH_V2_LR_STATE_SHIFT) |
+          ((uint32_t)(lr_reg->hw_status & GICH_V2_LR_HW_MASK)
+                                       << GICH_V2_LR_HW_SHIFT)  |
+          ((uint32_t)(lr_reg->grp & GICH_V2_LR_GRP_MASK) << GICH_V2_LR_GRP_SHIFT) );
+
+    writel_relaxed(lrv, GICH + GICH_LR + lr * 4);
+}
+
+static void gicv2_hcr_status(uint32_t flag, bool_t status)
+{
+    uint32_t hcr = readl_relaxed(GICH + GICH_HCR);
+
+    if ( status )
+        hcr |= flag;
+    else
+        hcr &= (~flag);
+
+    writel_relaxed(hcr, GICH + GICH_HCR);
+}
+
+static unsigned int gicv2_read_vmcr_priority(void)
+{
+   return ((readl_relaxed(GICH + GICH_VMCR) >> GICH_V2_VMCR_PRIORITY_SHIFT)
+           & GICH_V2_VMCR_PRIORITY_MASK);
+}
+
+static unsigned int gicv2_read_apr(int apr_reg)
+{
+   return readl_relaxed(GICH + GICH_APR);
+}
+
+static void gicv2_irq_enable(struct irq_desc *desc)
+{
+    unsigned long flags;
+    int irq = desc->irq;
+
+    ASSERT(spin_is_locked(&desc->lock));
+
+    spin_lock_irqsave(&gicv2.lock, flags);
+    desc->status &= ~IRQ_DISABLED;
+    dsb(sy);
+    /* Enable routing */
+    writel_relaxed((1u << (irq % 32)), GICD + GICD_ISENABLER + (irq / 32) * 4);
+    spin_unlock_irqrestore(&gicv2.lock, flags);
+}
+
+static void gicv2_irq_disable(struct irq_desc *desc)
+{
+    unsigned long flags;
+    int irq = desc->irq;
+
+    ASSERT(spin_is_locked(&desc->lock));
+
+    spin_lock_irqsave(&gicv2.lock, flags);
+    /* Disable routing */
+    writel_relaxed(1u << (irq % 32), GICD + GICD_ICENABLER + (irq / 32) * 4);
+    desc->status |= IRQ_DISABLED;
+    spin_unlock_irqrestore(&gicv2.lock, flags);
+}
+
+static unsigned int gicv2_irq_startup(struct irq_desc *desc)
+{
+    gicv2_irq_enable(desc);
+
+    return 0;
+}
+
+static void gicv2_irq_shutdown(struct irq_desc *desc)
+{
+    gicv2_irq_disable(desc);
+}
+
+static void gicv2_irq_ack(struct irq_desc *desc)
+{
+    /* No ACK -- reading IAR has done this for us */
+}
+
+static void gicv2_host_irq_end(struct irq_desc *desc)
+{
+    /* Lower the priority */
+    gicv2_eoi_irq(desc);
+    /* Deactivate */
+    gicv2_dir_irq(desc);
+}
+
+static void gicv2_guest_irq_end(struct irq_desc *desc)
+{
+    /* Lower the priority of the IRQ */
+    gicv2_eoi_irq(desc);
+    /* Deactivation happens in maintenance interrupt / via GICV */
+}
+
+static void gicv2_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask)
+{
+    BUG();
+}
+
+/* XXX different for level vs edge */
+static hw_irq_controller gicv2_host_irq_type = {
+    .typename     = "gic-v2",
+    .startup      = gicv2_irq_startup,
+    .shutdown     = gicv2_irq_shutdown,
+    .enable       = gicv2_irq_enable,
+    .disable      = gicv2_irq_disable,
+    .ack          = gicv2_irq_ack,
+    .end          = gicv2_host_irq_end,
+    .set_affinity = gicv2_irq_set_affinity,
+};
+
+static hw_irq_controller gicv2_guest_irq_type = {
+    .typename     = "gic-v2",
+    .startup      = gicv2_irq_startup,
+    .shutdown     = gicv2_irq_shutdown,
+    .enable       = gicv2_irq_enable,
+    .disable      = gicv2_irq_disable,
+    .ack          = gicv2_irq_ack,
+    .end          = gicv2_guest_irq_end,
+    .set_affinity = gicv2_irq_set_affinity,
+};
+
+const static struct gic_hw_operations gicv2_ops = {
+    .info                = &gicv2_info,
+    .secondary_init      = gicv2_secondary_cpu_init,
+    .save_state          = gicv2_save_state,
+    .restore_state       = gicv2_restore_state,
+    .dump_state          = gicv2_dump_state,
+    .gicv_setup          = gicv_v2_init,
+    .gic_host_irq_type   = &gicv2_host_irq_type,
+    .gic_guest_irq_type  = &gicv2_guest_irq_type,
+    .eoi_irq             = gicv2_eoi_irq,
+    .deactivate_irq      = gicv2_dir_irq,
+    .read_irq            = gicv2_read_irq,
+    .set_irq_properties  = gicv2_set_irq_properties,
+    .send_SGI            = gicv2_send_SGI,
+    .disable_interface   = gicv2_disable_interface,
+    .update_lr           = gicv2_update_lr,
+    .update_hcr_status   = gicv2_hcr_status,
+    .clear_lr            = gicv2_clear_lr,
+    .read_lr             = gicv2_read_lr,
+    .write_lr            = gicv2_write_lr,
+    .read_vmcr_priority  = gicv2_read_vmcr_priority,
+    .read_apr            = gicv2_read_apr,
+};
+
+/* Set up the GIC */
+void __init gicv2_init(void)
+{
+    static const struct dt_device_match gic_ids[] __initconst =
+    {
+        DT_MATCH_GIC,
+        { /* sentinel */ },
+    };
+    struct dt_device_node *node;
+    int res;
+
+    node = dt_find_interrupt_controller(gic_ids);
+    if ( !node )
+        panic("GICv2: Unable to find compatible GIC in the device tree");
+
+    dt_device_set_used_by(node, DOMID_XEN);
+
+    res = dt_device_get_address(node, 0, &gicv2.dbase, NULL);
+    if ( res || !gicv2.dbase || (gicv2.dbase & ~PAGE_MASK) )
+        panic("GICv2: Cannot find a valid address for the distributor");
+
+    res = dt_device_get_address(node, 1, &gicv2.cbase, NULL);
+    if ( res || !gicv2.cbase || (gicv2.cbase & ~PAGE_MASK) )
+        panic("GICv2: Cannot find a valid address for the CPU");
+
+    res = dt_device_get_address(node, 2, &gicv2.hbase, NULL);
+    if ( res || !gicv2.hbase || (gicv2.hbase & ~PAGE_MASK) )
+        panic("GICv2: Cannot find a valid address for the hypervisor");
+
+    res = dt_device_get_address(node, 3, &gicv2.vbase, NULL);
+    if ( res || !gicv2.vbase || (gicv2.vbase & ~PAGE_MASK) )
+        panic("GICv2: Cannot find a valid address for the virtual CPU");
+
+    res = platform_get_irq(node, 0);
+    if ( res < 0 )
+        panic("GICv2: Cannot find the maintenance IRQ");
+    gicv2_info.maintenance_irq = res;
+
+    /* Set the GIC as the primary interrupt controller */
+    dt_interrupt_controller = node;
+
+    /* TODO: Add check on distributor, cpu size */
+
+    printk("GICv2 initialization:\n"
+              "        gic_dist_addr=%"PRIpaddr"\n"
+              "        gic_cpu_addr=%"PRIpaddr"\n"
+              "        gic_hyp_addr=%"PRIpaddr"\n"
+              "        gic_vcpu_addr=%"PRIpaddr"\n"
+              "        gic_maintenance_irq=%u\n",
+              gicv2.dbase, gicv2.cbase, gicv2.hbase, gicv2.vbase,
+              gicv2_info.maintenance_irq);
+
+    if ( (gicv2.dbase & ~PAGE_MASK) || (gicv2.cbase & ~PAGE_MASK) ||
+         (gicv2.hbase & ~PAGE_MASK) || (gicv2.vbase & ~PAGE_MASK) )
+        panic("GICv2 interfaces not page aligned");
+
+    gicv2.map_dbase = ioremap_nocache(gicv2.dbase, PAGE_SIZE);
+    if ( !gicv2.map_dbase )
+        panic("GICv2: Failed to ioremap for GIC distributor\n");
+
+    if ( platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
+        gicv2.map_cbase = ioremap_nocache(gicv2.cbase, PAGE_SIZE * 0x10);
+    else
+        gicv2.map_cbase = ioremap_nocache(gicv2.cbase, PAGE_SIZE * 2);
+
+    if ( !gicv2.map_cbase )
+        panic("GICv2: Failed to ioremap for GIC CPU interface\n");
+
+    gicv2.map_hbase = ioremap_nocache(gicv2.hbase, PAGE_SIZE);
+    if ( !gicv2.map_hbase )
+        panic("GICv2: Failed to ioremap for GIC Virtual interface\n");
+
+    /* Global settings: interrupt distributor */
+    spin_lock_init(&gicv2.lock);
+    spin_lock(&gicv2.lock);
+
+    gicv2_dist_init();
+    gicv2_cpu_init();
+    gicv2_hyp_init();
+
+    spin_unlock(&gicv2.lock);
+
+    gicv2_info.hw_version = GIC_V2;
+    register_gic_ops(&gicv2_ops);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 4ac6da3..3624391 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -24,7 +24,6 @@
 #include <xen/irq.h>
 #include <xen/sched.h>
 #include <xen/errno.h>
-#include <xen/serial.h>
 #include <xen/softirq.h>
 #include <xen/list.h>
 #include <xen/device_tree.h>
@@ -34,196 +33,68 @@
 #include <asm/io.h>
 #include <asm/gic.h>
 
-#define GICD (gic.map_dbase)
-#define GICC (gic.map_cbase)
-#define GICH (gic.map_hbase)
-
 static void gic_restore_pending_irqs(struct vcpu *v);
 
-/* Global state */
-static struct {
-    paddr_t dbase;       /* Address of distributor registers */
-    void __iomem * map_dbase;  /* IO mapped Address of distributor registers */
-    paddr_t cbase;       /* Address of CPU interface registers */
-    void __iomem * map_cbase; /* IO mapped Address of CPU interface registers*/
-    paddr_t hbase;       /* Address of virtual interface registers */
-    void __iomem * map_hbase; /* IO Address of virtual interface registers */
-    paddr_t vbase;       /* Address of virtual cpu interface registers */
-    unsigned int lines;  /* Number of interrupts (SPIs + PPIs + SGIs) */
-    unsigned int maintenance_irq; /* IRQ maintenance */
-    unsigned int cpus;
-    spinlock_t lock;
-} gic;
-
 static DEFINE_PER_CPU(uint64_t, lr_mask);
 
-static uint8_t nr_lrs;
-#define lr_all_full() (this_cpu(lr_mask) == ((1 << nr_lrs) - 1))
-
-/* The GIC mapping of CPU interfaces does not necessarily match the
- * logical CPU numbering. Let's use mapping as returned by the GIC
- * itself
- */
-static DEFINE_PER_CPU(u8, gic_cpu_id);
-
-/* Maximum cpu interface per GIC */
-#define NR_GIC_CPU_IF 8
+#define lr_all_full() (this_cpu(lr_mask) == ((1 << gic_hw_ops->info->nr_lrs) - 1))
 
 #undef GIC_DEBUG
 
 static void gic_update_one_lr(struct vcpu *v, int i);
 
-static unsigned int gic_cpu_mask(const cpumask_t *cpumask)
+static const struct gic_hw_operations *gic_hw_ops;
+
+void register_gic_ops(const struct gic_hw_operations *ops)
 {
-    unsigned int cpu;
-    unsigned int mask = 0;
-    cpumask_t possible_mask;
+    gic_hw_ops = ops;
+}
 
-    cpumask_and(&possible_mask, cpumask, &cpu_possible_map);
-    for_each_cpu(cpu, &possible_mask)
-    {
-        ASSERT(cpu < NR_GIC_CPU_IF);
-        mask |= per_cpu(gic_cpu_id, cpu);
-    }
+static void clear_cpu_lr_mask(void)
+{
+    this_cpu(lr_mask) = 0ULL;
+}
 
-    return mask;
+enum gic_version gic_hw_version(void)
+{
+   return gic_hw_ops->info->hw_version;
 }
 
 unsigned int gic_number_lines(void)
 {
-    return gic.lines;
+    return gic_hw_ops->info->nr_lines;
 }
 
 void gic_save_state(struct vcpu *v)
 {
-    int i;
     ASSERT(!local_irq_is_enabled());
 
     /* No need for spinlocks here because interrupts are disabled around
      * this call and it only accesses struct vcpu fields that cannot be
      * accessed simultaneously by another pCPU.
      */
-    for ( i=0; i<nr_lrs; i++)
-        v->arch.gic_lr[i] = readl_relaxed(GICH + GICH_LR + i * 4);
     v->arch.lr_mask = this_cpu(lr_mask);
-    v->arch.gic_apr = readl_relaxed(GICH + GICH_APR);
-    v->arch.gic_vmcr = readl_relaxed(GICH + GICH_VMCR);
-    /* Disable until next VCPU scheduled */
-    writel_relaxed(0, GICH + GICH_HCR);
+    gic_hw_ops->save_state(v);
     isb();
 }
 
 void gic_restore_state(struct vcpu *v)
 {
-    int i;
     ASSERT(!local_irq_is_enabled());
 
     if ( is_idle_vcpu(v) )
         return;
 
     this_cpu(lr_mask) = v->arch.lr_mask;
-    for ( i=0; i<nr_lrs; i++)
-        writel_relaxed(v->arch.gic_lr[i], GICH + GICH_LR + i * 4);
-    writel_relaxed(v->arch.gic_apr, GICH + GICH_APR);
-    writel_relaxed(v->arch.gic_vmcr, GICH + GICH_VMCR);
-    writel_relaxed(GICH_HCR_EN, GICH + GICH_HCR);
+    gic_hw_ops->restore_state(v);
+
     isb();
 
     gic_restore_pending_irqs(v);
 }
 
-static void gic_irq_enable(struct irq_desc *desc)
-{
-    int irq = desc->irq;
-    unsigned long flags;
-
-    ASSERT(spin_is_locked(&desc->lock));
-
-    spin_lock_irqsave(&gic.lock, flags);
-    /* Enable routing */
-    desc->status &= ~IRQ_DISABLED;
-    dsb(sy);
-    writel_relaxed((1u << (irq % 32)), GICD + GICD_ISENABLER + (irq / 32) * 4);
-    spin_unlock_irqrestore(&gic.lock, flags);
-}
-
-static void gic_irq_disable(struct irq_desc *desc)
-{
-    int irq = desc->irq;
-    unsigned long flags;
-
-    ASSERT(spin_is_locked(&desc->lock));
-
-    spin_lock_irqsave(&gic.lock, flags);
-    /* Disable routing */
-    writel_relaxed(1u << (irq % 32), GICD + GICD_ICENABLER + (irq / 32) * 4);
-    desc->status |= IRQ_DISABLED;
-    spin_unlock_irqrestore(&gic.lock, flags);
-}
-
-static unsigned int gic_irq_startup(struct irq_desc *desc)
-{
-    gic_irq_enable(desc);
-
-    return 0;
-}
-
-static void gic_irq_shutdown(struct irq_desc *desc)
-{
-    gic_irq_disable(desc);
-}
-
-static void gic_irq_ack(struct irq_desc *desc)
-{
-    /* No ACK -- reading IAR has done this for us */
-}
-
-static void gic_host_irq_end(struct irq_desc *desc)
-{
-    int irq = desc->irq;
-    /* Lower the priority */
-    writel_relaxed(irq, GICC + GICC_EOIR);
-    /* Deactivate */
-    writel_relaxed(irq, GICC + GICC_DIR);
-}
-
-static void gic_guest_irq_end(struct irq_desc *desc)
-{
-    int irq = desc->irq;
-    /* Lower the priority of the IRQ */
-    writel_relaxed(irq, GICC + GICC_EOIR);
-    /* Deactivation happens in maintenance interrupt / via GICV */
-}
-
-static void gic_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask)
-{
-    BUG();
-}
-
-/* XXX different for level vs edge */
-static hw_irq_controller gic_host_irq_type = {
-    .typename = "gic",
-    .startup = gic_irq_startup,
-    .shutdown = gic_irq_shutdown,
-    .enable = gic_irq_enable,
-    .disable = gic_irq_disable,
-    .ack = gic_irq_ack,
-    .end = gic_host_irq_end,
-    .set_affinity = gic_irq_set_affinity,
-};
-static hw_irq_controller gic_guest_irq_type = {
-    .typename = "gic",
-    .startup = gic_irq_startup,
-    .shutdown = gic_irq_shutdown,
-    .enable = gic_irq_enable,
-    .disable = gic_irq_disable,
-    .ack = gic_irq_ack,
-    .end = gic_guest_irq_end,
-    .set_affinity = gic_irq_set_affinity,
-};
-
 /*
- * - needs to be called with a valid cpu_mask, ie each cpu in the mask has
+ * needs to be called with a valid cpu_mask, ie each cpu in the mask has
  * already called gic_cpu_init
  * - desc.lock must be held
  * - arch.type must be valid (i.e != DT_IRQ_TYPE_INVALID)
@@ -232,33 +103,7 @@ static void gic_set_irq_properties(struct irq_desc *desc,
                                    const cpumask_t *cpu_mask,
                                    unsigned int priority)
 {
-    uint32_t cfg, edgebit;
-    unsigned int mask;
-    unsigned int irq = desc->irq;
-    unsigned int type = desc->arch.type;
-
-    ASSERT(type != DT_IRQ_TYPE_INVALID);
-    ASSERT(spin_is_locked(&desc->lock));
-
-    spin_lock(&gic.lock);
-
-    mask = gic_cpu_mask(cpu_mask);
-
-    /* Set edge / level */
-    cfg = readl_relaxed(GICD + GICD_ICFGR + (irq / 16) * 4);
-    edgebit = 2u << (2 * (irq % 16));
-    if ( type & DT_IRQ_TYPE_LEVEL_MASK )
-        cfg &= ~edgebit;
-    else if ( type & DT_IRQ_TYPE_EDGE_BOTH )
-        cfg |= edgebit;
-    writel_relaxed(cfg, GICD + GICD_ICFGR + (irq / 16) * 4);
-
-    /* Set target CPU mask (RAZ/WI on uniprocessor) */
-    writeb_relaxed(mask, GICD + GICD_ITARGETSR + irq);
-    /* Set priority */
-    writeb_relaxed(priority, GICD + GICD_IPRIORITYR + irq);
-
-    spin_unlock(&gic.lock);
+   gic_hw_ops->set_irq_properties(desc, cpu_mask, priority);
 }
 
 /* Program the GIC to route an interrupt to the host (i.e. Xen)
@@ -268,11 +113,11 @@ void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask,
                           unsigned int priority)
 {
     ASSERT(priority <= 0xff);     /* Only 8 bits of priority */
-    ASSERT(desc->irq < gic.lines);/* Can't route interrupts that don't exist */
+    ASSERT(desc->irq < gic_number_lines());/* Can't route interrupts that don't exist */
     ASSERT(desc->status & IRQ_DISABLED);
     ASSERT(spin_is_locked(&desc->lock));
 
-    desc->handler = &gic_host_irq_type;
+    desc->handler = gic_hw_ops->gic_host_irq_type;
 
     gic_set_irq_properties(desc, cpu_mask, priority);
 }
@@ -286,7 +131,7 @@ void gic_route_irq_to_guest(struct domain *d, struct irq_desc *desc,
     struct pending_irq *p;
     ASSERT(spin_is_locked(&desc->lock));
 
-    desc->handler = &gic_guest_irq_type;
+    desc->handler = gic_hw_ops->gic_guest_irq_type;
     desc->status |= IRQ_GUEST;
 
     gic_set_irq_properties(desc, cpumask_of(smp_processor_id()), GIC_PRI_IRQ);
@@ -296,102 +141,6 @@ void gic_route_irq_to_guest(struct domain *d, struct irq_desc *desc,
     p->desc = desc;
 }
 
-static void __init gic_dist_init(void)
-{
-    uint32_t type;
-    uint32_t cpumask;
-    int i;
-
-    cpumask = readl_relaxed(GICD + GICD_ITARGETSR) & 0xff;
-    cpumask |= cpumask << 8;
-    cpumask |= cpumask << 16;
-
-    /* Disable the distributor */
-    writel_relaxed(0, GICD + GICD_CTLR);
-
-    type = readl_relaxed(GICD + GICD_TYPER);
-    gic.lines = 32 * ((type & GICD_TYPE_LINES) + 1);
-    gic.cpus = 1 + ((type & GICD_TYPE_CPUS) >> 5);
-    printk("GIC: %d lines, %d cpu%s%s (IID %8.8x).\n",
-           gic.lines, gic.cpus, (gic.cpus == 1) ? "" : "s",
-           (type & GICD_TYPE_SEC) ? ", secure" : "",
-           readl_relaxed(GICD + GICD_IIDR));
-
-    /* Default all global IRQs to level, active low */
-    for ( i = 32; i < gic.lines; i += 16 )
-        writel_relaxed(0x0, GICD + GICD_ICFGR + (i / 16) * 4);
-
-    /* Route all global IRQs to this CPU */
-    for ( i = 32; i < gic.lines; i += 4 )
-        writel_relaxed(cpumask, GICD + GICD_ITARGETSR + (i / 4) * 4);
-
-    /* Default priority for global interrupts */
-    for ( i = 32; i < gic.lines; i += 4 )
-        writel_relaxed (GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
-                        GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
-                        GICD + GICD_IPRIORITYR + (i / 4) * 4);
-
-    /* Disable all global interrupts */
-    for ( i = 32; i < gic.lines; i += 32 )
-        writel_relaxed(~0x0, GICD + GICD_ICENABLER + (i / 32) * 4);
-
-    /* Turn on the distributor */
-    writel_relaxed(GICD_CTL_ENABLE, GICD + GICD_CTLR);
-}
-
-static void __cpuinit gic_cpu_init(void)
-{
-    int i;
-
-    this_cpu(gic_cpu_id) = readl_relaxed(GICD + GICD_ITARGETSR) & 0xff;
-
-    /* The first 32 interrupts (PPI and SGI) are banked per-cpu, so
-     * even though they are controlled with GICD registers, they must
-     * be set up here with the other per-cpu state. */
-    writel_relaxed(0xffff0000, GICD + GICD_ICENABLER); /* Disable all PPI */
-    writel_relaxed(0x0000ffff, GICD + GICD_ISENABLER); /* Enable all SGI */
-
-    /* Set SGI priorities */
-    for (i = 0; i < 16; i += 4)
-        writel_relaxed(GIC_PRI_IPI << 24 | GIC_PRI_IPI << 16 |
-                       GIC_PRI_IPI << 8 | GIC_PRI_IPI,
-                       GICD + GICD_IPRIORITYR + (i / 4) * 4);
-    /* Set PPI priorities */
-    for (i = 16; i < 32; i += 4)
-        writel_relaxed(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
-                      GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
-                      GICD + GICD_IPRIORITYR + (i / 4) * 4);
-
-    /* Local settings: interface controller */
-    /* Don't mask by priority */
-    writel_relaxed(0xff, GICC + GICC_PMR);
-    /* Finest granularity of priority */
-    writel_relaxed(0x0, GICC + GICC_BPR);
-    /* Turn on delivery */
-    writel_relaxed(GICC_CTL_ENABLE|GICC_CTL_EOI, GICC + GICC_CTLR);
-}
-
-static void gic_cpu_disable(void)
-{
-    writel_relaxed(0x0, GICC + GICC_CTLR);
-}
-
-static void __cpuinit gic_hyp_init(void)
-{
-    uint32_t vtr;
-
-    vtr = readl_relaxed(GICH + GICH_VTR);
-    nr_lrs  = (vtr & GICH_VTR_NRLRGS) + 1;
-
-    writel_relaxed(GICH_MISR_EOI, GICH + GICH_MISR);
-    this_cpu(lr_mask) = 0ULL;
-}
-
-static void __cpuinit gic_hyp_disable(void)
-{
-    writel_relaxed(0, GICH + GICH_HCR);
-}
-
 int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
                   unsigned int *out_hwirq,
                   unsigned int *out_type)
@@ -415,110 +164,9 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
 /* Set up the GIC */
 void __init gic_init(void)
 {
-    static const struct dt_device_match gic_ids[] __initconst =
-    {
-        DT_MATCH_GIC,
-        { /* sentinel */ },
-    };
-    struct dt_device_node *node;
-    int res;
-
-    node = dt_find_interrupt_controller(gic_ids);
-    if ( !node )
-        panic("Unable to find compatible GIC in the device tree");
-
-    dt_device_set_used_by(node, DOMID_XEN);
-
-    res = dt_device_get_address(node, 0, &gic.dbase, NULL);
-    if ( res || !gic.dbase || (gic.dbase & ~PAGE_MASK) )
-        panic("GIC: Cannot find a valid address for the distributor");
-
-    res = dt_device_get_address(node, 1, &gic.cbase, NULL);
-    if ( res || !gic.cbase || (gic.cbase & ~PAGE_MASK) )
-        panic("GIC: Cannot find a valid address for the CPU");
-
-    res = dt_device_get_address(node, 2, &gic.hbase, NULL);
-    if ( res || !gic.hbase || (gic.hbase & ~PAGE_MASK) )
-        panic("GIC: Cannot find a valid address for the hypervisor");
-
-    res = dt_device_get_address(node, 3, &gic.vbase, NULL);
-    if ( res || !gic.vbase || (gic.vbase & ~PAGE_MASK) )
-        panic("GIC: Cannot find a valid address for the virtual CPU");
-
-    res = platform_get_irq(node, 0);
-    if ( res < 0 )
-        panic("GIC: Cannot find the maintenance IRQ");
-    gic.maintenance_irq = res;
-
-    /* Set the GIC as the primary interrupt controller */
-    dt_interrupt_controller = node;
-
-    /* TODO: Add check on distributor, cpu size */
-
-    printk("GIC initialization:\n"
-              "        gic_dist_addr=%"PRIpaddr"\n"
-              "        gic_cpu_addr=%"PRIpaddr"\n"
-              "        gic_hyp_addr=%"PRIpaddr"\n"
-              "        gic_vcpu_addr=%"PRIpaddr"\n"
-              "        gic_maintenance_irq=%u\n",
-              gic.dbase, gic.cbase, gic.hbase, gic.vbase,
-              gic.maintenance_irq);
-
-    if ( (gic.dbase & ~PAGE_MASK) || (gic.cbase & ~PAGE_MASK) ||
-         (gic.hbase & ~PAGE_MASK) || (gic.vbase & ~PAGE_MASK) )
-        panic("GIC interfaces not page aligned");
-
-    gic.map_dbase = ioremap_nocache(gic.dbase, PAGE_SIZE);
-    if ( !gic.map_dbase )
-        panic("Failed to ioremap for GIC distributor\n");
-
-    if ( platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
-        gic.map_cbase = ioremap_nocache(gic.cbase, PAGE_SIZE * 0x10);
-    else
-        gic.map_cbase = ioremap_nocache(gic.cbase, PAGE_SIZE * 2);
-
-    if ( !gic.map_cbase )
-        panic("Failed to ioremap for GIC CPU interface\n");
-
-    gic.map_hbase = ioremap_nocache(gic.hbase, PAGE_SIZE);
-    if ( !gic.map_hbase )
-        panic("Failed to ioremap for GIC Virtual interface\n");
-
-    /* Global settings: interrupt distributor */
-    spin_lock_init(&gic.lock);
-    spin_lock(&gic.lock);
-
-    gic_dist_init();
-    gic_cpu_init();
-    gic_hyp_init();
-
-    spin_unlock(&gic.lock);
-}
-
-static void send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
-                     const cpumask_t *cpu_mask)
-{
-    unsigned int mask = 0;
-    cpumask_t online_mask;
-
-    switch ( irqmode )
-    {
-    case SGI_TARGET_OTHERS:
-        writel_relaxed(GICD_SGI_TARGET_OTHERS | sgi, GICD + GICD_SGIR);
-        break;
-    case SGI_TARGET_SELF:
-        writel_relaxed(GICD_SGI_TARGET_SELF | sgi, GICD + GICD_SGIR);
-        break;
-    case SGI_TARGET_LIST:
-        cpumask_and(&online_mask, cpu_mask, &cpu_online_map);
-        mask = gic_cpu_mask(&online_mask);
-        writel_relaxed(GICD_SGI_TARGET_LIST |
-                       (mask << GICD_SGI_TARGET_SHIFT) | sgi,
-                       GICD + GICD_SGIR);
-        break;
-    default:
-        BUG();
-    }
+    gicv2_init();
+    /* Clear LR mask for cpu0 */
+    clear_cpu_lr_mask();
 }
 
 void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi)
@@ -526,12 +174,11 @@ void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi)
     ASSERT(sgi < 16); /* There are only 16 SGIs */
 
     dsb(sy);
-    send_SGI(sgi, SGI_TARGET_LIST, cpumask);
+    gic_hw_ops->send_SGI(sgi, SGI_TARGET_LIST, cpumask);
 }
 
 void send_SGI_one(unsigned int cpu, enum gic_sgi sgi)
 {
-    ASSERT(cpu < NR_GIC_CPU_IF);  /* Targets bitmap only supports 8 CPUs */
     send_SGI_mask(cpumask_of(cpu), sgi);
 }
 
@@ -540,7 +187,7 @@ void send_SGI_self(enum gic_sgi sgi)
     ASSERT(sgi < 16); /* There are only 16 SGIs */
 
     dsb(sy);
-    send_SGI(sgi, SGI_TARGET_SELF, NULL);
+    gic_hw_ops->send_SGI(sgi, SGI_TARGET_SELF, NULL);
 }
 
 void send_SGI_allbutself(enum gic_sgi sgi)
@@ -548,7 +195,7 @@ void send_SGI_allbutself(enum gic_sgi sgi)
    ASSERT(sgi < 16); /* There are only 16 SGIs */
 
    dsb(sy);
-   send_SGI(sgi, SGI_TARGET_OTHERS, NULL);
+   gic_hw_ops->send_SGI(sgi, SGI_TARGET_OTHERS, NULL);
 }
 
 void smp_send_state_dump(unsigned int cpu)
@@ -559,10 +206,9 @@ void smp_send_state_dump(unsigned int cpu)
 /* Set up the per-CPU parts of the GIC for a secondary CPU */
 void __cpuinit gic_init_secondary_cpu(void)
 {
-    spin_lock(&gic.lock);
-    gic_cpu_init();
-    gic_hyp_init();
-    spin_unlock(&gic.lock);
+    gic_hw_ops->secondary_init();
+    /* Clear LR mask for secondary cpus */
+    clear_cpu_lr_mask();
 }
 
 /* Shut down the per-CPU GIC interface */
@@ -570,28 +216,15 @@ void gic_disable_cpu(void)
 {
     ASSERT(!local_irq_is_enabled());
 
-    spin_lock(&gic.lock);
-    gic_cpu_disable();
-    gic_hyp_disable();
-    spin_unlock(&gic.lock);
+    gic_hw_ops->disable_interface();
 }
 
 static inline void gic_set_lr(int lr, struct pending_irq *p,
-        unsigned int state)
+                              unsigned int state)
 {
-    uint32_t lr_val;
-
     ASSERT(!local_irq_is_enabled());
-    BUG_ON(lr >= nr_lrs);
-    BUG_ON(lr < 0);
-    BUG_ON(state & ~(GICH_LR_STATE_MASK<<GICH_LR_STATE_SHIFT));
-
-    lr_val = state | (GIC_PRI_TO_GUEST(p->priority) << GICH_LR_PRIORITY_SHIFT) |
-        ((p->irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT);
-    if ( p->desc != NULL )
-        lr_val |= GICH_LR_HW | (p->desc->irq << GICH_LR_PHYSICAL_SHIFT);
 
-    writel_relaxed(lr_val, GICH + GICH_LR + lr * 4);
+    gic_hw_ops->update_lr(lr, p, state);
 
     set_bit(GIC_IRQ_GUEST_VISIBLE, &p->status);
     clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status);
@@ -651,6 +284,7 @@ void gic_raise_guest_irq(struct vcpu *v, unsigned int virtual_irq,
         unsigned int priority)
 {
     int i;
+    unsigned int nr_lrs = gic_hw_ops->info->nr_lrs;
 
     ASSERT(spin_is_locked(&v->arch.vgic.lock));
 
@@ -670,36 +304,43 @@ void gic_raise_guest_irq(struct vcpu *v, unsigned int virtual_irq,
 static void gic_update_one_lr(struct vcpu *v, int i)
 {
     struct pending_irq *p;
-    uint32_t lr;
     int irq;
+    struct gic_lr lr_val;
 
     ASSERT(spin_is_locked(&v->arch.vgic.lock));
     ASSERT(!local_irq_is_enabled());
 
-    lr = readl_relaxed(GICH + GICH_LR + i * 4);
-    irq = (lr >> GICH_LR_VIRTUAL_SHIFT) & GICH_LR_VIRTUAL_MASK;
+    gic_hw_ops->read_lr(i, &lr_val);
+    irq = lr_val.virq;
     p = irq_to_pending(v, irq);
-    if ( lr & GICH_LR_ACTIVE )
+    if ( lr_val.state & GICH_LR_ACTIVE )
     {
         set_bit(GIC_IRQ_GUEST_ACTIVE, &p->status);
         if ( test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) &&
              test_and_clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status) )
         {
             if ( p->desc == NULL )
-                writel_relaxed(lr | GICH_LR_PENDING, GICH + GICH_LR + i * 4);
+            {
+                 lr_val.state |= GICH_LR_PENDING;
+                 gic_hw_ops->write_lr(i, &lr_val);
+            }
             else
                 gdprintk(XENLOG_WARNING, "unable to inject hw irq=%d into d%dv%d: already active in LR%d\n",
                          irq, v->domain->domain_id, v->vcpu_id, i);
         }
-    } else if ( lr & GICH_LR_PENDING ) {
+    }
+    else if ( lr_val.state & GICH_LR_PENDING )
+    {
         int q __attribute__ ((unused)) = test_and_clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status);
 #ifdef GIC_DEBUG
         if ( q )
             gdprintk(XENLOG_DEBUG, "trying to inject irq=%d into d%dv%d, when it is already pending in LR%d\n",
                     irq, v->domain->domain_id, v->vcpu_id, i);
 #endif
-    } else {
-        writel_relaxed(0, GICH + GICH_LR + i * 4);
+    }
+    else
+    {
+        gic_hw_ops->clear_lr(i);
         clear_bit(i, &this_cpu(lr_mask));
 
         if ( p->desc != NULL )
@@ -719,6 +360,7 @@ void gic_clear_lrs(struct vcpu *v)
 {
     int i = 0;
     unsigned long flags;
+    unsigned int nr_lrs = gic_hw_ops->info->nr_lrs;
 
     /* The idle domain has no LRs to be cleared. Since gic_restore_state
      * doesn't write any LR registers for the idle domain they could be
@@ -739,10 +381,12 @@ void gic_clear_lrs(struct vcpu *v)
 
 static void gic_restore_pending_irqs(struct vcpu *v)
 {
-    int lr = 0, lrs = nr_lrs;
+    int lr = 0;
     struct pending_irq *p, *t, *p_r;
     struct list_head *inflight_r;
     unsigned long flags;
+    unsigned int nr_lrs = gic_hw_ops->info->nr_lrs;
+    int lrs = nr_lrs;
 
     spin_lock_irqsave(&v->arch.vgic.lock, flags);
 
@@ -807,13 +451,12 @@ int gic_events_need_delivery(void)
     struct vcpu *v = current;
     struct pending_irq *p;
     unsigned long flags;
-    const unsigned long apr = readl_relaxed(GICH + GICH_APR);
+    const unsigned long apr = gic_hw_ops->read_apr(0);
     int mask_priority;
     int active_priority;
     int rc = 0;
 
-    mask_priority = (readl_relaxed(GICH + GICH_VMCR)
-                     >> GICH_VMCR_PRIORITY_SHIFT) & GICH_VMCR_PRIORITY_MASK;
+    mask_priority = gic_hw_ops->read_vmcr_priority();
     active_priority = find_next_bit(&apr, 32, 0);
 
     spin_lock_irqsave(&v->arch.vgic.lock, flags);
@@ -843,23 +486,23 @@ out:
 
 void gic_inject(void)
 {
-    uint32_t hcr;
     ASSERT(!local_irq_is_enabled());
 
     gic_restore_pending_irqs(current);
 
-    hcr = readl_relaxed(GICH + GICH_HCR);
-
     if ( !list_empty(&current->arch.vgic.lr_pending) && lr_all_full() )
-        writel_relaxed(hcr | GICH_HCR_UIE, GICH + GICH_HCR);
+        gic_hw_ops->update_hcr_status(GICH_HCR_UIE, 1);
     else
-        writel_relaxed(hcr & ~GICH_HCR_UIE, GICH + GICH_HCR);
+        gic_hw_ops->update_hcr_status(GICH_HCR_UIE, 0);
 }
 
 static void do_sgi(struct cpu_user_regs *regs, enum gic_sgi sgi)
 {
     /* Lower the priority */
-    writel_relaxed(sgi, GICC + GICC_EOIR);
+    struct irq_desc *desc = irq_to_desc(sgi);
+
+    /* Lower the priority */
+    gic_hw_ops->eoi_irq(desc);
 
     switch (sgi)
     {
@@ -878,19 +521,17 @@ static void do_sgi(struct cpu_user_regs *regs, enum gic_sgi sgi)
     }
 
     /* Deactivate */
-    writel_relaxed(sgi, GICC + GICC_DIR);
+    gic_hw_ops->deactivate_irq(desc);
 }
 
 /* Accept an interrupt from the GIC and dispatch its handler */
 void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
 {
-    uint32_t intack;
     unsigned int irq;
 
-
     do  {
-        intack = readl_relaxed(GICC + GICC_IAR);
-        irq = intack & GICC_IA_IRQ;
+        /* Reading IRQ will ACK it */
+        irq = gic_hw_ops->read_irq();
 
         if ( likely(irq >= 16 && irq < 1021) )
         {
@@ -912,49 +553,7 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
 
 int gicv_setup(struct domain *d)
 {
-    int ret;
-
-    /*
-     * The hardware domain gets the hardware address.
-     * Guests get the virtual platform layout.
-     */
-    if ( is_hardware_domain(d) )
-    {
-        d->arch.vgic.dbase = gic.dbase;
-        d->arch.vgic.cbase = gic.cbase;
-    }
-    else
-    {
-        d->arch.vgic.dbase = GUEST_GICD_BASE;
-        d->arch.vgic.cbase = GUEST_GICC_BASE;
-    }
-
-    d->arch.vgic.nr_lines = 0;
-
-    /*
-     * Map the gic virtual cpu interface in the gic cpu interface
-     * region of the guest.
-     *
-     * The second page is always mapped at +4K irrespective of the
-     * GIC_64K_STRIDE quirk. The DTB passed to the guest reflects this.
-     */
-    ret = map_mmio_regions(d, d->arch.vgic.cbase,
-                           d->arch.vgic.cbase + PAGE_SIZE - 1,
-                           gic.vbase);
-    if (ret)
-        return ret;
-
-    if ( !platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
-        ret = map_mmio_regions(d, d->arch.vgic.cbase + PAGE_SIZE,
-                               d->arch.vgic.cbase + (2 * PAGE_SIZE) - 1,
-                               gic.vbase + PAGE_SIZE);
-    else
-        ret = map_mmio_regions(d, d->arch.vgic.cbase + PAGE_SIZE,
-                               d->arch.vgic.cbase + (2 * PAGE_SIZE) - 1,
-                               gic.vbase + 16*PAGE_SIZE);
-
-    return ret;
-
+    return gic_hw_ops->gicv_setup(d);
 }
 
 static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
@@ -969,18 +568,10 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r
 
 void gic_dump_info(struct vcpu *v)
 {
-    int i;
     struct pending_irq *p;
 
     printk("GICH_LRs (vcpu %d) mask=%"PRIx64"\n", v->vcpu_id, v->arch.lr_mask);
-    if ( v == current )
-    {
-        for ( i = 0; i < nr_lrs; i++ )
-            printk("   HW_LR[%d]=%x\n", i, readl_relaxed(GICH + GICH_LR + i * 4));
-    } else {
-        for ( i = 0; i < nr_lrs; i++ )
-            printk("   VCPU_LR[%d]=%x\n", i, v->arch.gic_lr[i]);
-    }
+    gic_hw_ops->dump_state(v);
 
     list_for_each_entry ( p, &v->arch.vgic.inflight_irqs, inflight )
     {
@@ -991,12 +582,11 @@ void gic_dump_info(struct vcpu *v)
     {
         printk("Pending irq=%d\n", p->irq);
     }
-
 }
 
 void __cpuinit init_maintenance_interrupt(void)
 {
-    request_irq(gic.maintenance_irq, 0, maintenance_interrupt,
+    request_irq(gic_hw_ops->info->maintenance_irq, 0, maintenance_interrupt,
                 "irq-maintenance", NULL);
 }
 
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 7fa3b95..9a85633 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -114,24 +114,6 @@
 #define GICH_MISR_VGRP1E  (1 << 6)
 #define GICH_MISR_VGRP1D  (1 << 7)
 
-#define GICH_LR_VIRTUAL_MASK    0x3ff
-#define GICH_LR_VIRTUAL_SHIFT   0
-#define GICH_LR_PHYSICAL_MASK   0x3ff
-#define GICH_LR_PHYSICAL_SHIFT  10
-#define GICH_LR_STATE_MASK      0x3
-#define GICH_LR_STATE_SHIFT     28
-#define GICH_LR_PRIORITY_SHIFT  23
-#define GICH_LR_MAINTENANCE_IRQ (1<<19)
-#define GICH_LR_PENDING         (1<<28)
-#define GICH_LR_ACTIVE          (1<<29)
-#define GICH_LR_GRP1            (1<<30)
-#define GICH_LR_HW              (1<<31)
-#define GICH_LR_CPUID_SHIFT     9
-#define GICH_VTR_NRLRGS         0x3f
-
-#define GICH_VMCR_PRIORITY_MASK   0x1f
-#define GICH_VMCR_PRIORITY_SHIFT  27
-
 /*
  * The minimum GICC_BPR is required to be in the range 0-3. We set
  * GICC_BPR to 0 but we must expect that it might be 3. This means we
@@ -155,6 +137,8 @@
 #define GIC_PRI_TO_GUEST(pri) (pri >> 3) /* GICH_LR and GICH_VMCR only support
                                             5 bits for guest irq priority */
 
+#define GICH_LR_PENDING         1
+#define GICH_LR_ACTIVE          2
 
 #ifndef __ASSEMBLY__
 #include <xen/device_tree.h>
@@ -163,6 +147,28 @@
 #define DT_MATCH_GIC    DT_MATCH_COMPATIBLE("arm,cortex-a15-gic"), \
                         DT_MATCH_COMPATIBLE("arm,cortex-a7-gic")
 
+/*
+ * Decode LR register content.
+ * The LR register format is different for GIC HW version
+ */
+struct gic_lr {
+   /* Physical IRQ */
+   uint32_t pirq;
+   /* Virtual IRQ */
+   uint32_t virq;
+   uint8_t priority;
+   uint8_t state;
+   uint8_t hw_status;
+   uint8_t grp;
+};
+
+enum gic_version {
+    GIC_V2,
+};
+
+extern enum gic_version gic_hw_version(void);
+extern void gicv2_init(void);
+
 extern int domain_vgic_init(struct domain *d);
 extern void domain_vgic_free(struct domain *d);
 
@@ -234,6 +240,71 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
                   unsigned int *out_hwirq, unsigned int *out_type);
 void gic_clear_lrs(struct vcpu *v);
 
+struct gic_info {
+    /* GIC version */
+    enum gic_version hw_version;
+    /* Number of GIC lines supported */
+    unsigned int nr_lines;
+    /* Number of LR registers */
+    uint8_t nr_lrs;
+    /* Maintenance irq number */
+    unsigned int maintenance_irq;
+};
+
+struct gic_hw_operations {
+    /* Hold GIC HW information */
+    const struct gic_info *info;
+    /* Save GIC registers */
+    void (*save_state)(struct vcpu *);
+    /* Restore GIC registers */
+    void (*restore_state)(const struct vcpu *);
+    /* Dump GIC LR register information */
+    void (*dump_state)(const struct vcpu *);
+    /* Map MMIO region of GIC */
+    int (*gicv_setup)(struct domain *);
+
+    /* hw_irq_controller to enable/disable/eoi host irq */
+    hw_irq_controller *gic_host_irq_type;
+
+    /* hw_irq_controller to enable/disable/eoi guest irq */
+    hw_irq_controller *gic_guest_irq_type;
+
+    /* End of Interrupt */
+    void (*eoi_irq)(struct irq_desc *irqd);
+    /* Deactivate/reduce priority of irq */
+    void (*deactivate_irq)(struct irq_desc *irqd);
+    /* Read IRQ id and Ack */
+    unsigned int (*read_irq)(void);
+    /* Set IRQ property */
+    void (*set_irq_properties)(struct irq_desc *desc,
+                               const cpumask_t *cpu_mask,
+                               unsigned int priority);
+    /* Send SGI */
+    void (*send_SGI)(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
+                     const cpumask_t *online_mask);
+    /* Disable CPU physical and virtual interfaces */
+    void (*disable_interface)(void);
+    /* Update LR register with state and priority */
+    void (*update_lr)(int lr, const struct pending_irq *pending_irq,
+                      unsigned int state);
+    /* Update HCR status register */
+    void (*update_hcr_status)(uint32_t flag, bool_t set);
+    /* Clear LR register */
+    void (*clear_lr)(int lr);
+    /* Read LR register and populate gic_lr structure */
+    void (*read_lr)(int lr, struct gic_lr *);
+    /* Write LR register from gic_lr structure */
+    void (*write_lr)(int lr, const struct gic_lr *);
+    /* Read VMCR priority */
+    unsigned int (*read_vmcr_priority)(void);
+    /* Read APRn register */
+    unsigned int (*read_apr)(int apr_reg);
+    /* Secondary CPU init */
+    int (*secondary_init)(void);
+};
+
+void register_gic_ops(const struct gic_hw_operations *ops);
+
 #endif /* __ASSEMBLY__ */
 #endif
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 04/14] xen/arm: move GIC context data structure to gic driver
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (2 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 03/14] xen/arm: segregate and split GIC low level functionality vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 05/14] xen/arm: use device api to detect GIC version vijay.kilari
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

arch_domain in domain.h defines all the GIC registers
that needs to be saved/restored directly.

These GIC registers are GIC HW version specific. The number
of registers and size of registers varies with GIC version.
So move these registers to gic.h file and make a union of these
registers. This helps to define GIC HW version specific
structure to this union for later GIC versions.

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/gic-v2.c        |   14 +++++++-------
 xen/include/asm-arm/domain.h |    5 +++--
 xen/include/asm-arm/gic.h    |   18 ++++++++++++++++++
 3 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
index 3539cb8..c18cd4c 100644
--- a/xen/arch/arm/gic-v2.c
+++ b/xen/arch/arm/gic-v2.c
@@ -111,10 +111,10 @@ static void gicv2_save_state(struct vcpu *v)
      * accessed simultaneously by another pCPU.
      */
     for ( i = 0; i < gicv2_info.nr_lrs; i++ )
-        v->arch.gic_lr[i] = readl_relaxed(GICH + GICH_LR + i * 4);
+        v->arch.gic.v2.lr[i] = readl_relaxed(GICH + GICH_LR + i * 4);
 
-    v->arch.gic_apr = readl_relaxed(GICH + GICH_APR);
-    v->arch.gic_vmcr = readl_relaxed(GICH + GICH_VMCR);
+    v->arch.gic.v2.apr = readl_relaxed(GICH + GICH_APR);
+    v->arch.gic.v2.vmcr = readl_relaxed(GICH + GICH_VMCR);
     /* Disable until next VCPU scheduled */
     writel_relaxed(0, GICH + GICH_HCR);
 }
@@ -124,10 +124,10 @@ static void gicv2_restore_state(const struct vcpu *v)
     int i;
 
     for ( i = 0; i < gicv2_info.nr_lrs; i++ )
-        writel_relaxed(v->arch.gic_lr[i], GICH + GICH_LR + i * 4);
+        writel_relaxed(v->arch.gic.v2.lr[i], GICH + GICH_LR + i * 4);
 
-    writel_relaxed(v->arch.gic_apr, GICH + GICH_APR);
-    writel_relaxed(v->arch.gic_vmcr, GICH + GICH_VMCR);
+    writel_relaxed(v->arch.gic.v2.apr, GICH + GICH_APR);
+    writel_relaxed(v->arch.gic.v2.vmcr, GICH + GICH_VMCR);
     writel_relaxed(GICH_HCR_EN, GICH + GICH_HCR);
 }
 
@@ -144,7 +144,7 @@ static void gicv2_dump_state(const struct vcpu *v)
     else
     {
         for ( i = 0; i < gicv2_info.nr_lrs; i++ )
-            printk("   VCPU_LR[%d]=%x\n", i, v->arch.gic_lr[i]);
+            printk("   VCPU_LR[%d]=%x\n", i, v->arch.gic.v2.lr[i]);
     }
 }
 
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 046362c..bfd462c 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -8,6 +8,7 @@
 #include <asm/p2m.h>
 #include <asm/vfp.h>
 #include <asm/mmio.h>
+#include <asm/gic.h>
 #include <public/hvm/params.h>
 #include <xen/serial.h>
 #include <xen/hvm/iommu.h>
@@ -263,8 +264,8 @@ struct arch_vcpu
     uint32_t csselr;
     register_t vmpidr;
 
-    uint32_t gic_hcr, gic_vmcr, gic_apr;
-    uint32_t gic_lr[64];
+    /* Holds gic context data */
+    union gic_state_data gic;
     uint64_t lr_mask;
 
     struct {
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 9a85633..a3c5f3d 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -148,6 +148,24 @@
                         DT_MATCH_COMPATIBLE("arm,cortex-a7-gic")
 
 /*
+ * GICv2 register that needs to be saved/restored
+ * on VCPU context switch
+ */
+struct gic_v2 {
+    uint32_t hcr;
+    uint32_t vmcr;
+    uint32_t apr;
+    uint32_t lr[64];
+};
+
+/*
+ * Union to hold underlying hw version context information
+ */
+union gic_state_data {
+    struct gic_v2 v2;
+};
+
+/*
  * Decode LR register content.
  * The LR register format is different for GIC HW version
  */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 05/14] xen/arm: use device api to detect GIC version
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (3 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 04/14] xen/arm: move GIC context data structure to gic driver vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 06/14] xen/arm: switch to dynamic allocation of vgic rank vijay.kilari
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

Run through the device tree to detect
compatible GIC version and initialize GIC driver

Also change DT_MATCH_GIC to DT_MATCH_GIC_V2 to point
the GIC HW version to add later GIC versions

--------------------------------------------
changes in v7a: changed num_gics variable from bool_t to uint8_t

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/domain_build.c  |    2 +-
 xen/arch/arm/gic-v2.c        |   27 ++++++++++++++++-----------
 xen/arch/arm/gic.c           |   25 ++++++++++++++++++++++++-
 xen/include/asm-arm/device.h |    1 +
 xen/include/asm-arm/gic.h    |    9 +++++----
 5 files changed, 47 insertions(+), 17 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 9d9cba9..8c850ca 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -804,7 +804,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
     };
     static const struct dt_device_match gic_matches[] __initconst =
     {
-        DT_MATCH_GIC,
+        DT_MATCH_GIC_V2,
         { /* sentinel */ },
     };
     static const struct dt_device_match timer_matches[] __initconst =
diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
index c18cd4c..695c232 100644
--- a/xen/arch/arm/gic-v2.c
+++ b/xen/arch/arm/gic-v2.c
@@ -30,6 +30,7 @@
 #include <asm/p2m.h>
 #include <asm/domain.h>
 #include <asm/platform.h>
+#include <asm/device.h>
 
 #include <asm/io.h>
 #include <asm/gic.h>
@@ -584,20 +585,10 @@ const static struct gic_hw_operations gicv2_ops = {
 };
 
 /* Set up the GIC */
-void __init gicv2_init(void)
+static int __init gicv2_init(struct dt_device_node *node, const void *data)
 {
-    static const struct dt_device_match gic_ids[] __initconst =
-    {
-        DT_MATCH_GIC,
-        { /* sentinel */ },
-    };
-    struct dt_device_node *node;
     int res;
 
-    node = dt_find_interrupt_controller(gic_ids);
-    if ( !node )
-        panic("GICv2: Unable to find compatible GIC in the device tree");
-
     dt_device_set_used_by(node, DOMID_XEN);
 
     res = dt_device_get_address(node, 0, &gicv2.dbase, NULL);
@@ -667,8 +658,22 @@ void __init gicv2_init(void)
 
     gicv2_info.hw_version = GIC_V2;
     register_gic_ops(&gicv2_ops);
+
+    return 0;
 }
 
+static const char * const gicv2_dt_compat[] __initconst =
+{
+    DT_COMPAT_GIC_CORTEX_A15,
+    DT_COMPAT_GIC_CORTEX_A7,
+    NULL
+};
+
+DT_DEVICE_START(gicv2, "GICv2:", DEVICE_GIC)
+        .compatible = gicv2_dt_compat,
+        .init = gicv2_init,
+DT_DEVICE_END
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 3624391..e1e27b35 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -30,6 +30,7 @@
 #include <asm/p2m.h>
 #include <asm/domain.h>
 #include <asm/platform.h>
+#include <asm/device.h>
 #include <asm/io.h>
 #include <asm/gic.h>
 
@@ -164,7 +165,29 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
 /* Set up the GIC */
 void __init gic_init(void)
 {
-    gicv2_init();
+    int rc;
+    struct dt_device_node *node;
+    uint8_t num_gics = 0;
+
+    dt_for_each_device_node( dt_host, node )
+    {
+        if ( !dt_get_property(node, "interrupt-controller", NULL) )
+            continue;
+
+        if ( !dt_get_parent(node) )
+            continue;
+
+        rc = device_init(node, DEVICE_GIC, NULL);
+        if ( !rc )
+        {
+            /* NOTE: Only one GIC is supported */
+            num_gics = 1;
+            break;
+        }
+    }
+    if ( !num_gics )
+        panic("Unable to find compatible GIC in the device tree");
+
     /* Clear LR mask for cpu0 */
     clear_cpu_lr_mask();
 }
diff --git a/xen/include/asm-arm/device.h b/xen/include/asm-arm/device.h
index 60109cc..74a80c6 100644
--- a/xen/include/asm-arm/device.h
+++ b/xen/include/asm-arm/device.h
@@ -8,6 +8,7 @@ enum device_type
 {
     DEVICE_SERIAL,
     DEVICE_IOMMU,
+    DEVICE_GIC,
     /* Use for error */
     DEVICE_UNKNOWN,
 };
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index a3c5f3d..5ff4477 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -144,8 +144,11 @@
 #include <xen/device_tree.h>
 #include <xen/irq.h>
 
-#define DT_MATCH_GIC    DT_MATCH_COMPATIBLE("arm,cortex-a15-gic"), \
-                        DT_MATCH_COMPATIBLE("arm,cortex-a7-gic")
+#define DT_COMPAT_GIC_CORTEX_A15     "arm,cortex-a15-gic"
+#define DT_COMPAT_GIC_CORTEX_A7      "arm,cortex-a7-gic"
+
+#define DT_MATCH_GIC_V2 DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_CORTEX_A15), \
+                        DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_CORTEX_A7)
 
 /*
  * GICv2 register that needs to be saved/restored
@@ -185,8 +188,6 @@ enum gic_version {
 };
 
 extern enum gic_version gic_hw_version(void);
-extern void gicv2_init(void);
-
 extern int domain_vgic_init(struct domain *d);
 extern void domain_vgic_free(struct domain *d);
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 06/14] xen/arm: switch to dynamic allocation of vgic rank
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (4 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 05/14] xen/arm: use device api to detect GIC version vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 07/14] xen/arm: prefix byte_read and byte_write functions with vgic vijay.kilari
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

vgic_irq_rank structure contains gic specific data elements.
Move this out of domain.h to new vgic header file vgic.h
Allocate memory dynamically in vgic driver.

This patch reduces the size of domain struct and helps to
keep domain struct within PAGE_SIZE when future GIC hw versions
are added

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/domain.c        |    2 ++
 xen/arch/arm/vgic.c          |   18 ++++++++++++++----
 xen/include/asm-arm/domain.h |   11 +----------
 xen/include/asm-arm/vgic.h   |   40 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 74fadbd..829d49f 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -31,6 +31,7 @@
 #include <asm/procinfo.h>
 
 #include <asm/gic.h>
+#include <asm/vgic.h>
 #include <asm/platform.h>
 #include "vtimer.h"
 #include "vuart.h"
@@ -485,6 +486,7 @@ fail:
 void vcpu_destroy(struct vcpu *v)
 {
     vcpu_timer_destroy(v);
+    vcpu_vgic_free(v);
     free_xenheap_pages(v->arch.stack, STACK_ORDER);
 }
 
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 139c2e9..088ded3 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -29,6 +29,7 @@
 
 #include <asm/mmio.h>
 #include <asm/gic.h>
+#include <asm/vgic.h>
 
 #define REG(n) (n)
 
@@ -69,7 +70,7 @@ static struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n)
     int rank = REG_RANK_NR(b, (n >> 2));
 
     if ( rank == 0 )
-        return &v->arch.vgic.private_irqs;
+        return v->arch.vgic.private_irqs;
     else if ( rank <= DOMAIN_NR_RANKS(v->domain) )
         return &v->domain->arch.vgic.shared_irqs[rank - 1];
     else
@@ -139,9 +140,12 @@ void domain_vgic_free(struct domain *d)
 int vcpu_vgic_init(struct vcpu *v)
 {
     int i;
-    memset(&v->arch.vgic.private_irqs, 0, sizeof(v->arch.vgic.private_irqs));
 
-    spin_lock_init(&v->arch.vgic.private_irqs.lock);
+    v->arch.vgic.private_irqs = xzalloc(struct vgic_irq_rank);
+    if ( v->arch.vgic.private_irqs == NULL )
+      return -ENOMEM;
+
+    spin_lock_init(&v->arch.vgic.private_irqs->lock);
 
     memset(&v->arch.vgic.pending_irqs, 0, sizeof(v->arch.vgic.pending_irqs));
     for (i = 0; i < 32; i++)
@@ -152,7 +156,7 @@ int vcpu_vgic_init(struct vcpu *v)
 
     /* For SGI and PPI the target is always this CPU */
     for ( i = 0 ; i < 8 ; i++ )
-        v->arch.vgic.private_irqs.itargets[i] =
+        v->arch.vgic.private_irqs->itargets[i] =
               (1<<(v->vcpu_id+0))
             | (1<<(v->vcpu_id+8))
             | (1<<(v->vcpu_id+16))
@@ -164,6 +168,12 @@ int vcpu_vgic_init(struct vcpu *v)
     return 0;
 }
 
+int vcpu_vgic_free(struct vcpu *v)
+{
+    xfree(v->arch.vgic.private_irqs);
+    return 0;
+}
+
 #define vgic_lock(v)   spin_lock_irq(&(v)->domain->arch.vgic.lock)
 #define vgic_unlock(v) spin_unlock_irq(&(v)->domain->arch.vgic.lock)
 
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index bfd462c..077ac1e 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -13,15 +13,6 @@
 #include <xen/serial.h>
 #include <xen/hvm/iommu.h>
 
-/* Represents state corresponding to a block of 32 interrupts */
-struct vgic_irq_rank {
-    spinlock_t lock; /* Covers access to all other members of this struct */
-    uint32_t ienable, iactive, ipend, pendsgi;
-    uint32_t icfg[2];
-    uint32_t ipriority[8];
-    uint32_t itargets[8];
-};
-
 struct pending_irq
 {
     /*
@@ -274,7 +265,7 @@ struct arch_vcpu
          * struct arch_domain.
          */
         struct pending_irq pending_irqs[32];
-        struct vgic_irq_rank private_irqs;
+        struct vgic_irq_rank *private_irqs;
 
         /* This list is ordered by IRQ priority and it is used to keep
          * track of the IRQs that the VGIC injected into the guest.
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
new file mode 100644
index 0000000..0fd5b41
--- /dev/null
+++ b/xen/include/asm-arm/vgic.h
@@ -0,0 +1,40 @@
+/*
+ * ARM Virtual Generic Interrupt Controller support
+ *
+ * Ian Campbell <ian.campbell@citrix.com>
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARM_VGIC_H__
+#define __ASM_ARM_VGIC_H__
+
+/* Represents state corresponding to a block of 32 interrupts */
+struct vgic_irq_rank {
+    spinlock_t lock; /* Covers access to all other members of this struct */
+    uint32_t ienable, iactive, ipend, pendsgi;
+    uint32_t icfg[2];
+    uint32_t ipriority[8];
+    uint32_t itargets[8];
+};
+
+extern int vcpu_vgic_free(struct vcpu *v);
+#endif /* __ASM_ARM_VGIC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 07/14] xen/arm: prefix byte_read and byte_write functions with vgic
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (5 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 06/14] xen/arm: switch to dynamic allocation of vgic rank vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 08/14] xen/arm: move vgic defines to vgic header file vijay.kilari
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

prefix byte_read and byte_write vgic functions with vgic_
to make these function vgic specific.

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/vgic.c |   30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 088ded3..d01f1d9 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -180,7 +180,7 @@ int vcpu_vgic_free(struct vcpu *v)
 #define vgic_lock_rank(v, r) spin_lock(&(r)->lock)
 #define vgic_unlock_rank(v, r) spin_unlock(&(r)->lock)
 
-static uint32_t byte_read(uint32_t val, int sign, int offset)
+static uint32_t vgic_byte_read(uint32_t val, int sign, int offset)
 {
     int byte = offset & 0x3;
 
@@ -192,7 +192,7 @@ static uint32_t byte_read(uint32_t val, int sign, int offset)
     return val;
 }
 
-static void byte_write(uint32_t *reg, uint32_t var, int offset)
+static void vgic_byte_write(uint32_t *reg, uint32_t var, int offset)
 {
     int byte = offset & 0x3;
 
@@ -267,7 +267,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISPENDR);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
-        *r = byte_read(rank->ipend, dabt.sign, offset);
+        *r = vgic_byte_read(rank->ipend, dabt.sign, offset);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -276,7 +276,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICPENDR);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
-        *r = byte_read(rank->ipend, dabt.sign, offset);
+        *r = vgic_byte_read(rank->ipend, dabt.sign, offset);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -306,7 +306,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         vgic_lock_rank(v, rank);
         *r = rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)];
         if ( dabt.size == 0 )
-            *r = byte_read(*r, dabt.sign, offset);
+            *r = vgic_byte_read(*r, dabt.sign, offset);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -318,7 +318,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         vgic_lock_rank(v, rank);
         *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR)];
         if ( dabt.size == 0 )
-            *r = byte_read(*r, dabt.sign, offset);
+            *r = vgic_byte_read(*r, dabt.sign, offset);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -346,7 +346,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         rank = vgic_rank_offset(v, 1, gicd_reg - GICD_CPENDSGIR);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
-        *r = byte_read(rank->pendsgi, dabt.sign, offset);
+        *r = vgic_byte_read(rank->pendsgi, dabt.sign, offset);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -355,7 +355,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         rank = vgic_rank_offset(v, 1, gicd_reg - GICD_SPENDSGIR);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
-        *r = byte_read(rank->pendsgi, dabt.sign, offset);
+        *r = vgic_byte_read(rank->pendsgi, dabt.sign, offset);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -618,8 +618,10 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         if ( dabt.size == 2 )
             rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)] = *r;
         else
-            byte_write(&rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)],
-                       *r, offset);
+        {
+            tr = REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR);
+            vgic_byte_write(&rank->itargets[tr], *r, offset);
+        }
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -631,8 +633,10 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         if ( dabt.size == 2 )
             rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR)] = *r;
         else
-            byte_write(&rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR)],
-                       *r, offset);
+        {
+            tr = REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR);
+            vgic_byte_write(&rank->ipriority[tr], *r, offset);
+        }
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -757,7 +761,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
         return;
     }
 
-    priority = byte_read(rank->ipriority[REG_RANK_INDEX(8, irq)], 0, irq & 0x3);
+    priority = vgic_byte_read(rank->ipriority[REG_RANK_INDEX(8, irq)], 0, irq & 0x3);
 
     n->irq = irq;
     set_bit(GIC_IRQ_GUEST_QUEUED, &n->status);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 08/14] xen/arm: move vgic defines to vgic header file
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (6 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 07/14] xen/arm: prefix byte_read and byte_write functions with vgic vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 09/14] xen/arm: move and rename is_vcpu_running function to sched.h vijay.kilari
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

gic.h contains defines of vgic. Move these to vgic
header file. Also move inline functions and defines/macros
in vgic.c to vgic.h. These vgic functions and macros
can be used by other GIC HW specific VGIC drivers,

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/irq.c         |    1 +
 xen/arch/arm/time.c        |    1 +
 xen/arch/arm/vgic.c        |   53 --------------------------------------
 xen/arch/arm/vpsci.c       |    1 +
 xen/arch/arm/vtimer.c      |    1 +
 xen/include/asm-arm/gic.h  |    7 -----
 xen/include/asm-arm/vgic.h |   61 ++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 65 insertions(+), 60 deletions(-)

diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 9c141bc..3a8acbf 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -26,6 +26,7 @@
 #include <xen/sched.h>
 
 #include <asm/gic.h>
+#include <asm/vgic.h>
 
 static unsigned int local_irqs_type[NR_LOCAL_IRQS];
 static DEFINE_SPINLOCK(local_irqs_type_lock);
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index 06cc709..4c3e1a6 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -32,6 +32,7 @@
 #include <asm/system.h>
 #include <asm/time.h>
 #include <asm/gic.h>
+#include <asm/vgic.h>
 #include <asm/cpufeature.h>
 #include <asm/platform.h>
 
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index d01f1d9..96bd7c1 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -33,35 +33,10 @@
 
 #define REG(n) (n)
 
-/* Number of ranks of interrupt registers for a domain */
-#define DOMAIN_NR_RANKS(d) (((d)->arch.vgic.nr_lines+31)/32)
-
 static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info);
 static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info);
 
 /*
- * Rank containing GICD_<FOO><n> for GICD_<FOO> with
- * <b>-bits-per-interrupt
- */
-static inline int REG_RANK_NR(int b, uint32_t n)
-{
-    switch ( b )
-    {
-    case 8: return n >> 3;
-    case 4: return n >> 2;
-    case 2: return n >> 1;
-    case 1: return n;
-    default: BUG();
-    }
-}
-
-/*
- * Offset of GICD_<FOO><n> with its rank, for GICD_<FOO> with
- * <b>-bits-per-interrupt.
- */
-#define REG_RANK_INDEX(b, n) (((n) >> 2) & ((b)-1))
-
-/*
  * Returns rank corresponding to a GICD_<FOO><n> register for
  * GICD_<FOO> with <b>-bits-per-interrupt.
  */
@@ -174,34 +149,6 @@ int vcpu_vgic_free(struct vcpu *v)
     return 0;
 }
 
-#define vgic_lock(v)   spin_lock_irq(&(v)->domain->arch.vgic.lock)
-#define vgic_unlock(v) spin_unlock_irq(&(v)->domain->arch.vgic.lock)
-
-#define vgic_lock_rank(v, r) spin_lock(&(r)->lock)
-#define vgic_unlock_rank(v, r) spin_unlock(&(r)->lock)
-
-static uint32_t vgic_byte_read(uint32_t val, int sign, int offset)
-{
-    int byte = offset & 0x3;
-
-    val = val >> (8*byte);
-    if ( sign && (val & 0x80) )
-        val |= 0xffffff00;
-    else
-        val &= 0x000000ff;
-    return val;
-}
-
-static void vgic_byte_write(uint32_t *reg, uint32_t var, int offset)
-{
-    int byte = offset & 0x3;
-
-    var &= (0xff << (8*byte));
-
-    *reg &= ~(0xff << (8*byte));
-    *reg |= var;
-}
-
 static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
 {
     struct hsr_dabt dabt = info->dabt;
diff --git a/xen/arch/arm/vpsci.c b/xen/arch/arm/vpsci.c
index 1ceb8cb..80678f6 100644
--- a/xen/arch/arm/vpsci.c
+++ b/xen/arch/arm/vpsci.c
@@ -16,6 +16,7 @@
 
 #include <asm/current.h>
 #include <asm/gic.h>
+#include <asm/vgic.h>
 #include <asm/psci.h>
 
 int do_psci_cpu_on(uint32_t vcpuid, register_t entry_point)
diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c
index c268873..690657b 100644
--- a/xen/arch/arm/vtimer.c
+++ b/xen/arch/arm/vtimer.c
@@ -24,6 +24,7 @@
 #include <asm/irq.h>
 #include <asm/time.h>
 #include <asm/gic.h>
+#include <asm/vgic.h>
 #include <asm/regs.h>
 
 extern s_time_t ticks_to_ns(uint64_t ticks);
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 5ff4477..ed610cb 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -188,13 +188,6 @@ enum gic_version {
 };
 
 extern enum gic_version gic_hw_version(void);
-extern int domain_vgic_init(struct domain *d);
-extern void domain_vgic_free(struct domain *d);
-
-extern int vcpu_vgic_init(struct vcpu *v);
-
-extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq);
-extern void vgic_clear_pending_irqs(struct vcpu *v);
 extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
 
 /* Program the GIC to route an interrupt */
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 0fd5b41..92f1e86 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -18,6 +18,8 @@
 #ifndef __ASM_ARM_VGIC_H__
 #define __ASM_ARM_VGIC_H__
 
+#include <xen/bitops.h>
+
 /* Represents state corresponding to a block of 32 interrupts */
 struct vgic_irq_rank {
     spinlock_t lock; /* Covers access to all other members of this struct */
@@ -27,6 +29,65 @@ struct vgic_irq_rank {
     uint32_t itargets[8];
 };
 
+/* Number of ranks of interrupt registers for a domain */
+#define DOMAIN_NR_RANKS(d) (((d)->arch.vgic.nr_lines+31)/32)
+
+#define vgic_lock(v)   spin_lock_irq(&(v)->domain->arch.vgic.lock)
+#define vgic_unlock(v) spin_unlock_irq(&(v)->domain->arch.vgic.lock)
+
+#define vgic_lock_rank(v, r) spin_lock(&(r)->lock)
+#define vgic_unlock_rank(v, r) spin_unlock(&(r)->lock)
+
+/*
+ * Rank containing GICD_<FOO><n> for GICD_<FOO> with
+ * <b>-bits-per-interrupt
+ */
+static inline int REG_RANK_NR(int b, uint32_t n)
+{
+    switch ( b )
+    {
+    case 8: return n >> 3;
+    case 4: return n >> 2;
+    case 2: return n >> 1;
+    case 1: return n;
+    default: BUG();
+    }
+}
+
+static inline uint32_t vgic_byte_read(uint32_t val, int sign, int offset)
+{
+    int byte = offset & 0x3;
+
+    val = val >> (8*byte);
+    if ( sign && (val & 0x80) )
+        val |= 0xffffff00;
+    else
+        val &= 0x000000ff;
+    return val;
+}
+
+static inline void vgic_byte_write(uint32_t *reg, uint32_t var, int offset)
+{
+    int byte = offset & 0x3;
+
+    var &= (0xff << (8*byte));
+
+    *reg &= ~(0xff << (8*byte));
+    *reg |= var;
+}
+
+/*
+ * Offset of GICD_<FOO><n> with its rank, for GICD_<FOO> with
+ * <b>-bits-per-interrupt.
+ */
+#define REG_RANK_INDEX(b, n) (((n) >> 2) & ((b)-1))
+
+extern int domain_vgic_init(struct domain *d);
+extern void domain_vgic_free(struct domain *d);
+extern int vcpu_vgic_init(struct vcpu *v);
+extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq);
+extern void vgic_clear_pending_irqs(struct vcpu *v);
+
 extern int vcpu_vgic_free(struct vcpu *v);
 #endif /* __ASM_ARM_VGIC_H__ */
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 09/14] xen/arm: move and rename is_vcpu_running function to sched.h
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (7 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 08/14] xen/arm: move vgic defines to vgic header file vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01  7:55   ` Jan Beulich
  2014-07-01  6:41 ` [PATCH v7a 10/14] xen/arm: move pending_irq structure to vgic header file vijay.kilari
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: keir, vijay.kilari, Prasun.Kapoor, Vijaya Kumar K, george.dunlap,
	jbeulich

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

is_vcpu_running function in vgic driver is generic. So move
this to sched.h and rename it as is_vcpu_online

----------------------------------------------
changes in v7a:
        - Changed vcpuid parameter from int to unsigned int
        - Removed check for test_bit. Return !test_bit()

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
CC: jbeulich@suse.com
CC: keir@xen.org
CC: george.dunlap@citrix.com
---
 xen/arch/arm/vgic.c     |   20 ++------------------
 xen/include/xen/sched.h |   14 ++++++++++++++
 2 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 96bd7c1..d29474b 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -405,22 +405,6 @@ static void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
     }
 }
 
-static inline int is_vcpu_running(struct domain *d, int vcpuid)
-{
-    struct vcpu *v;
-
-    if ( vcpuid >= d->max_vcpus )
-        return 0;
-
-    v = d->vcpu[vcpuid];
-    if ( v == NULL )
-        return 0;
-    if (test_bit(_VPF_down, &v->pause_flags) )
-        return 0;
-
-    return 1;
-}
-
 static int vgic_to_sgi(struct vcpu *v, register_t sgir)
 {
     struct domain *d = v->domain;
@@ -444,7 +428,7 @@ static int vgic_to_sgi(struct vcpu *v, register_t sgir)
         case GICD_SGI_TARGET_OTHERS:
             for ( i = 0; i < d->max_vcpus; i++ )
             {
-                if ( i != current->vcpu_id && is_vcpu_running(d, i) )
+                if ( i != current->vcpu_id && is_vcpu_online(d, i) )
                     set_bit(i, &vcpu_mask);
             }
             break;
@@ -459,7 +443,7 @@ static int vgic_to_sgi(struct vcpu *v, register_t sgir)
 
     for_each_set_bit( vcpuid, &vcpu_mask, d->max_vcpus )
     {
-        if ( !is_vcpu_running(d, vcpuid) )
+        if ( !is_vcpu_online(d, vcpuid) )
         {
             gdprintk(XENLOG_WARNING, "vGICD: GICD_SGIR write r=%"PRIregister" vcpu_mask=%lx, wrong CPUTargetList\n",
                      sgir, vcpu_mask);
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index f920e1a..5fde72a 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -829,6 +829,20 @@ void watchdog_domain_destroy(struct domain *d);
 #define need_iommu(d)    (0)
 #endif
 
+static inline bool_t is_vcpu_online(const struct domain *d, unsigned int vcpuid)
+{
+    const struct vcpu *v;
+
+    if ( vcpuid >= d->max_vcpus || d->vcpu == NULL )
+        return 0;
+
+    v = d->vcpu[vcpuid];
+    if ( v == NULL )
+        return 0;
+
+    return !test_bit(_VPF_down, &v->pause_flags);
+}
+
 void set_vcpu_migration_delay(unsigned int delay);
 unsigned int get_vcpu_migration_delay(void);
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 10/14] xen/arm: move pending_irq structure to vgic header file
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (8 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 09/14] xen/arm: move and rename is_vcpu_running function to sched.h vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 11/14] xen/arm: calculate vgic irq rank based on register size vijay.kilari
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

gic.h requires definition of pending_irq structure defined
in domain.h and domain.h requires gic_state structure defined
in gic.h and hence there is inter-dependency between domain.h
and gic.h files.

So move pending_irq to vgic.h which is relevant place for this
structure and break domain.h and gic.h interdependency

By this move irq_to_pending function declaration from gic.h
to vgic.h

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
---
 xen/include/asm-arm/domain.h |   57 -----------------------------------------
 xen/include/asm-arm/gic.h    |    2 +-
 xen/include/asm-arm/vgic.h   |   58 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+), 58 deletions(-)

diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 077ac1e..2a1e976 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -13,63 +13,6 @@
 #include <xen/serial.h>
 #include <xen/hvm/iommu.h>
 
-struct pending_irq
-{
-    /*
-     * The following two states track the lifecycle of the guest irq.
-     * However because we are not sure and we don't want to track
-     * whether an irq added to an LR register is PENDING or ACTIVE, the
-     * following states are just an approximation.
-     *
-     * GIC_IRQ_GUEST_QUEUED: the irq is asserted and queued for
-     * injection into the guest's LRs.
-     *
-     * GIC_IRQ_GUEST_VISIBLE: the irq has been added to an LR register,
-     * therefore the guest is aware of it. From the guest point of view
-     * the irq can be pending (if the guest has not acked the irq yet)
-     * or active (after acking the irq).
-     *
-     * In order for the state machine to be fully accurate, for level
-     * interrupts, we should keep the interrupt's pending state until
-     * the guest deactivates the irq. However because we are not sure
-     * when that happens, we instead track whether there is an interrupt
-     * queued using GIC_IRQ_GUEST_QUEUED. We clear it when we add it to
-     * an LR register. We set it when we receive another interrupt
-     * notification.  Therefore it is possible to set
-     * GIC_IRQ_GUEST_QUEUED while the irq is GIC_IRQ_GUEST_VISIBLE. We
-     * could also change the state of the guest irq in the LR register
-     * from active to active and pending, but for simplicity we simply
-     * inject a second irq after the guest EOIs the first one.
-     *
-     *
-     * An additional state is used to keep track of whether the guest
-     * irq is enabled at the vgicd level:
-     *
-     * GIC_IRQ_GUEST_ENABLED: the guest IRQ is enabled at the VGICD
-     * level (GICD_ICENABLER/GICD_ISENABLER).
-     *
-     */
-#define GIC_IRQ_GUEST_QUEUED   0
-#define GIC_IRQ_GUEST_ACTIVE   1
-#define GIC_IRQ_GUEST_VISIBLE  2
-#define GIC_IRQ_GUEST_ENABLED  3
-    unsigned long status;
-    struct irq_desc *desc; /* only set it the irq corresponds to a physical irq */
-    int irq;
-#define GIC_INVALID_LR         ~(uint8_t)0
-    uint8_t lr;
-    uint8_t priority;
-    /* inflight is used to append instances of pending_irq to
-     * vgic.inflight_irqs */
-    struct list_head inflight;
-    /* lr_queue is used to append instances of pending_irq to
-     * lr_pending. lr_pending is a per vcpu queue, therefore lr_queue
-     * accesses are protected with the vgic lock.
-     * TODO: when implementing irq migration, taking only the current
-     * vgic lock is not going to be enough. */
-    struct list_head lr_queue;
-};
-
 struct hvm_domain
 {
     uint64_t              params[HVM_NR_PARAMS];
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index ed610cb..875729e 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -143,6 +143,7 @@
 #ifndef __ASSEMBLY__
 #include <xen/device_tree.h>
 #include <xen/irq.h>
+#include <asm-arm/vgic.h>
 
 #define DT_COMPAT_GIC_CORTEX_A15     "arm,cortex-a15-gic"
 #define DT_COMPAT_GIC_CORTEX_A7      "arm,cortex-a7-gic"
@@ -188,7 +189,6 @@ enum gic_version {
 };
 
 extern enum gic_version gic_hw_version(void);
-extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
 
 /* Program the GIC to route an interrupt */
 extern void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask,
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 92f1e86..003c3e9 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -20,6 +20,63 @@
 
 #include <xen/bitops.h>
 
+struct pending_irq
+{
+    /*
+     * The following two states track the lifecycle of the guest irq.
+     * However because we are not sure and we don't want to track
+     * whether an irq added to an LR register is PENDING or ACTIVE, the
+     * following states are just an approximation.
+     *
+     * GIC_IRQ_GUEST_QUEUED: the irq is asserted and queued for
+     * injection into the guest's LRs.
+     *
+     * GIC_IRQ_GUEST_VISIBLE: the irq has been added to an LR register,
+     * therefore the guest is aware of it. From the guest point of view
+     * the irq can be pending (if the guest has not acked the irq yet)
+     * or active (after acking the irq).
+     *
+     * In order for the state machine to be fully accurate, for level
+     * interrupts, we should keep the interrupt's pending state until
+     * the guest deactivates the irq. However because we are not sure
+     * when that happens, we instead track whether there is an interrupt
+     * queued using GIC_IRQ_GUEST_QUEUED. We clear it when we add it to
+     * an LR register. We set it when we receive another interrupt
+     * notification.  Therefore it is possible to set
+     * GIC_IRQ_GUEST_QUEUED while the irq is GIC_IRQ_GUEST_VISIBLE. We
+     * could also change the state of the guest irq in the LR register
+     * from active to active and pending, but for simplicity we simply
+     * inject a second irq after the guest EOIs the first one.
+     *
+     *
+     * An additional state is used to keep track of whether the guest
+     * irq is enabled at the vgicd level:
+     *
+     * GIC_IRQ_GUEST_ENABLED: the guest IRQ is enabled at the VGICD
+     * level (GICD_ICENABLER/GICD_ISENABLER).
+     *
+     */
+#define GIC_IRQ_GUEST_QUEUED   0
+#define GIC_IRQ_GUEST_ACTIVE   1
+#define GIC_IRQ_GUEST_VISIBLE  2
+#define GIC_IRQ_GUEST_ENABLED  3
+    unsigned long status;
+    struct irq_desc *desc; /* only set it the irq corresponds to a physical irq */
+    int irq;
+#define GIC_INVALID_LR         ~(uint8_t)0
+    uint8_t lr;
+    uint8_t priority;
+    /* inflight is used to append instances of pending_irq to
+     * vgic.inflight_irqs */
+    struct list_head inflight;
+    /* lr_queue is used to append instances of pending_irq to
+     * lr_pending. lr_pending is a per vcpu queue, therefore lr_queue
+     * accesses are protected with the vgic lock.
+     * TODO: when implementing irq migration, taking only the current
+     * vgic lock is not going to be enough. */
+    struct list_head lr_queue;
+};
+
 /* Represents state corresponding to a block of 32 interrupts */
 struct vgic_irq_rank {
     spinlock_t lock; /* Covers access to all other members of this struct */
@@ -87,6 +144,7 @@ extern void domain_vgic_free(struct domain *d);
 extern int vcpu_vgic_init(struct vcpu *v);
 extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq);
 extern void vgic_clear_pending_irqs(struct vcpu *v);
+extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
 
 extern int vcpu_vgic_free(struct vcpu *v);
 #endif /* __ASM_ARM_VGIC_H__ */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 11/14] xen/arm: calculate vgic irq rank based on register size
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (9 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 10/14] xen/arm: move pending_irq structure to vgic header file vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 12/14] xen/arm: Remove REG macro in vgic driver vijay.kilari
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

vGIC irq rank was computed assuming the register offset is byte
size.Use the HSR abort address size in calculating register size.

So, with this patch following are achieved
   (1) In the code 'dabt.size != number' this number is always
       BYTE/HALF_WORD/WORD/DOUBLE defined by HSR register.
       Instead of checking for hard coded values use HSR abort
       address size values.
   (2) The vgic_rank_offset also depends on register size to
       compute the rank offset. Though there is no direct relation
       between rank offset computation and HSR dabt.size the same
       values are used to calculate irq rank.

This make vgic_rank_offset generic as it takes register
size as parameter to calculate irq rank instead of hard coding to
value 2 in previous patches

Also, output of REG_RANK_INDEX macro is modulo by 32 to make
sure register index is always within irq rank

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/vgic.c             |  139 ++++++++++++++++++++-------------------
 xen/include/asm-arm/processor.h |    8 +++
 xen/include/asm-arm/vgic.h      |    4 +-
 3 files changed, 83 insertions(+), 68 deletions(-)

diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index d29474b..ca9eeda 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -40,9 +40,10 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info);
  * Returns rank corresponding to a GICD_<FOO><n> register for
  * GICD_<FOO> with <b>-bits-per-interrupt.
  */
-static struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n)
+static struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n,
+                                              int s)
 {
-    int rank = REG_RANK_NR(b, (n >> 2));
+    int rank = REG_RANK_NR(b, (n >> s));
 
     if ( rank == 0 )
         return v->arch.vgic.private_irqs;
@@ -54,7 +55,7 @@ static struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n)
 
 static struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq)
 {
-    return vgic_rank_offset(v, 8, irq);
+    return vgic_rank_offset(v, 8, irq, DABT_WORD);
 }
 
 static const struct mmio_handler_ops vgic_distr_mmio_handler = {
@@ -161,13 +162,13 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
     switch ( gicd_reg )
     {
     case GICD_CTLR:
-        if ( dabt.size != 2 ) goto bad_width;
+        if ( dabt.size != DABT_WORD ) goto bad_width;
         vgic_lock(v);
         *r = v->domain->arch.vgic.ctlr;
         vgic_unlock(v);
         return 1;
     case GICD_TYPER:
-        if ( dabt.size != 2 ) goto bad_width;
+        if ( dabt.size != DABT_WORD ) goto bad_width;
         /* No secure world support for guests. */
         vgic_lock(v);
         *r = ( (v->domain->max_vcpus<<5) & GICD_TYPE_CPUS )
@@ -175,7 +176,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         vgic_unlock(v);
         return 1;
     case GICD_IIDR:
-        if ( dabt.size != 2 ) goto bad_width;
+        if ( dabt.size != DABT_WORD ) goto bad_width;
         /*
          * XXX Do we need a JEP106 manufacturer ID?
          * Just use the physical h/w value for now
@@ -192,8 +193,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         goto read_as_zero;
 
     case GICD_ISENABLER ... GICD_ISENABLERN:
-        if ( dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER);
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
         *r = rank->ienable;
@@ -201,8 +202,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         return 1;
 
     case GICD_ICENABLER ... GICD_ICENABLERN:
-        if ( dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER);
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
         *r = rank->ienable;
@@ -210,8 +211,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         return 1;
 
     case GICD_ISPENDR ... GICD_ISPENDRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISPENDR);
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISPENDR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
         *r = vgic_byte_read(rank->ipend, dabt.sign, offset);
@@ -219,8 +220,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         return 1;
 
     case GICD_ICPENDR ... GICD_ICPENDRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICPENDR);
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICPENDR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
         *r = vgic_byte_read(rank->ipend, dabt.sign, offset);
@@ -228,8 +229,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         return 1;
 
     case GICD_ISACTIVER ... GICD_ISACTIVERN:
-        if ( dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER);
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
         *r = rank->iactive;
@@ -237,8 +238,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         return 1;
 
     case GICD_ICACTIVER ... GICD_ICACTIVERN:
-        if ( dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER);
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
         *r = rank->iactive;
@@ -246,35 +247,37 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         return 1;
 
     case GICD_ITARGETSR ... GICD_ITARGETSRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR);
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
 
         vgic_lock_rank(v, rank);
-        *r = rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)];
-        if ( dabt.size == 0 )
+        *r = rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR,
+                                           DABT_WORD)];
+        if ( dabt.size == DABT_BYTE )
             *r = vgic_byte_read(*r, dabt.sign, offset);
         vgic_unlock_rank(v, rank);
         return 1;
 
     case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR);
+        if ( dabt.size != 0 && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
 
         vgic_lock_rank(v, rank);
-        *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR)];
-        if ( dabt.size == 0 )
+        *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
+                                            DABT_WORD)];
+        if ( dabt.size == DABT_BYTE )
             *r = vgic_byte_read(*r, dabt.sign, offset);
         vgic_unlock_rank(v, rank);
         return 1;
 
     case GICD_ICFGR ... GICD_ICFGRN:
-        if ( dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR);
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
-        *r = rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR)];
+        *r = rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)];
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -283,14 +286,14 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         goto read_as_zero;
 
     case GICD_SGIR:
-        if ( dabt.size != 2 ) goto bad_width;
+        if ( dabt.size != DABT_WORD ) goto bad_width;
         /* Write only -- read unknown */
         *r = 0xdeadbeef;
         return 1;
 
     case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_CPENDSGIR);
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_CPENDSGIR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
         *r = vgic_byte_read(rank->pendsgi, dabt.sign, offset);
@@ -298,8 +301,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         return 1;
 
     case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_SPENDSGIR);
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_SPENDSGIR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
         *r = vgic_byte_read(rank->pendsgi, dabt.sign, offset);
@@ -311,7 +314,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         goto read_as_zero;
 
     case GICD_ICPIDR2:
-        if ( dabt.size != 2 ) goto bad_width;
+        if ( dabt.size != DABT_WORD ) goto bad_width;
         printk("vGICD: unhandled read from ICPIDR2\n");
         return 0;
 
@@ -341,7 +344,7 @@ bad_width:
     return 0;
 
 read_as_zero:
-    if ( dabt.size != 2 ) goto bad_width;
+    if ( dabt.size != DABT_WORD ) goto bad_width;
     *r = 0;
     return 1;
 }
@@ -467,7 +470,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
     switch ( gicd_reg )
     {
     case GICD_CTLR:
-        if ( dabt.size != 2 ) goto bad_width;
+        if ( dabt.size != DABT_WORD ) goto bad_width;
         /* Ignore all but the enable bit */
         v->domain->arch.vgic.ctlr = (*r) & GICD_CTL_ENABLE;
         return 1;
@@ -486,42 +489,44 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         goto write_ignore;
 
     case GICD_ISENABLER ... GICD_ISENABLERN:
-        if ( dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER);
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD);
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank);
         tr = rank->ienable;
         rank->ienable |= *r;
         vgic_unlock_rank(v, rank);
-        vgic_enable_irqs(v, (*r) & (~tr), (gicd_reg - GICD_ISENABLER) >> 2);
+        vgic_enable_irqs(v, (*r) & (~tr),
+                         (gicd_reg - GICD_ISENABLER) >> DABT_WORD);
         return 1;
 
     case GICD_ICENABLER ... GICD_ICENABLERN:
-        if ( dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER);
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD);
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank);
         tr = rank->ienable;
         rank->ienable &= ~*r;
         vgic_unlock_rank(v, rank);
-        vgic_disable_irqs(v, (*r) & tr, (gicd_reg - GICD_ICENABLER) >> 2);
+        vgic_disable_irqs(v, (*r) & tr,
+                          (gicd_reg - GICD_ICENABLER) >> DABT_WORD);
         return 1;
 
     case GICD_ISPENDR ... GICD_ISPENDRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
         printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDR%d\n",
                dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ISPENDR);
         return 0;
 
     case GICD_ICPENDR ... GICD_ICPENDRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
         printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDR%d\n",
                dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ICPENDR);
         return 0;
 
     case GICD_ISACTIVER ... GICD_ISACTIVERN:
-        if ( dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER);
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER, DABT_WORD);
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank);
         rank->iactive &= ~*r;
@@ -529,8 +534,8 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         return 1;
 
     case GICD_ICACTIVER ... GICD_ICACTIVERN:
-        if ( dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER);
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER, DABT_WORD);
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank);
         rank->iactive &= ~*r;
@@ -542,30 +547,32 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         goto write_ignore;
 
     case GICD_ITARGETSR + 8 ... GICD_ITARGETSRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR);
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank);
-        if ( dabt.size == 2 )
-            rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)] = *r;
+        if ( dabt.size == DABT_WORD )
+            rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR,
+                                          DABT_WORD)] = *r;
         else
         {
-            tr = REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR);
+            tr = REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
             vgic_byte_write(&rank->itargets[tr], *r, offset);
         }
         vgic_unlock_rank(v, rank);
         return 1;
 
     case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR);
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank);
-        if ( dabt.size == 2 )
-            rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR)] = *r;
+        if ( dabt.size == DABT_WORD )
+            rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
+                                           DABT_WORD)] = *r;
         else
         {
-            tr = REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR);
+            tr = REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
             vgic_byte_write(&rank->ipriority[tr], *r, offset);
         }
         vgic_unlock_rank(v, rank);
@@ -577,11 +584,11 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         /* It is implementation defined if these are writeable. We chose not */
         goto write_ignore;
     case GICD_ICFGR + 2 ... GICD_ICFGRN: /* SPIs */
-        if ( dabt.size != 2 ) goto bad_width;
-        rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR);
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD);
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank);
-        rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR)] = *r;
+        rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)] = *r;
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -595,13 +602,13 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         return vgic_to_sgi(v, *r);
 
     case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
         printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDSGIR%d\n",
                dabt.size ? "word" : "byte", *r, gicd_reg - GICD_CPENDSGIR);
         return 0;
 
     case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
-        if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width;
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
         printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDSGIR%d\n",
                dabt.size ? "word" : "byte", *r, gicd_reg - GICD_SPENDSGIR);
         return 0;
@@ -640,7 +647,7 @@ bad_width:
     return 0;
 
 write_ignore:
-    if ( dabt.size != 2 ) goto bad_width;
+    if ( dabt.size != DABT_WORD ) goto bad_width;
     return 1;
 }
 
@@ -692,7 +699,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
         return;
     }
 
-    priority = vgic_byte_read(rank->ipriority[REG_RANK_INDEX(8, irq)], 0, irq & 0x3);
+    priority = vgic_byte_read(rank->ipriority[REG_RANK_INDEX(8, irq, DABT_WORD)], 0, irq & 0x3);
 
     n->irq = irq;
     set_bit(GIC_IRQ_GUEST_QUEUED, &n->status);
diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h
index 3be86f1..bdfff4e 100644
--- a/xen/include/asm-arm/processor.h
+++ b/xen/include/asm-arm/processor.h
@@ -251,6 +251,14 @@ extern struct cpuinfo_arm cpu_data[];
 extern u32 __cpu_logical_map[];
 #define cpu_logical_map(cpu) __cpu_logical_map[cpu]
 
+/* HSR data abort size definition */
+enum dabt_size {
+    DABT_BYTE        = 0,
+    DABT_HALF_WORD   = 1,
+    DABT_WORD        = 2,
+    DABT_DOUBLE_WORD = 3,
+};
+
 union hsr {
     uint32_t bits;
     struct {
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 003c3e9..7c71d16 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -134,10 +134,10 @@ static inline void vgic_byte_write(uint32_t *reg, uint32_t var, int offset)
 }
 
 /*
- * Offset of GICD_<FOO><n> with its rank, for GICD_<FOO> with
+ * Offset of GICD_<FOO><n> with its rank, for GICD_<FOO> size <s> with
  * <b>-bits-per-interrupt.
  */
-#define REG_RANK_INDEX(b, n) (((n) >> 2) & ((b)-1))
+#define REG_RANK_INDEX(b, n, s) ((((n) >> s) & ((b)-1)) % 32)
 
 extern int domain_vgic_init(struct domain *d);
 extern void domain_vgic_free(struct domain *d);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 12/14] xen/arm: Remove REG macro in vgic driver
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (10 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 11/14] xen/arm: calculate vgic irq rank based on register size vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01  6:41 ` [PATCH v7a 13/14] xen/arm: split vgic driver into generic and vgic-v2 driver vijay.kilari
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

REG macro does not compute any value and offset
variable is no more required. Hence removed

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/vgic.c |   68 ++++++++++++++++++++++++---------------------------
 1 file changed, 32 insertions(+), 36 deletions(-)

diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index ca9eeda..78004b0 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -31,8 +31,6 @@
 #include <asm/gic.h>
 #include <asm/vgic.h>
 
-#define REG(n) (n)
-
 static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info);
 static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info);
 
@@ -156,8 +154,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
     struct cpu_user_regs *regs = guest_cpu_user_regs();
     register_t *r = select_user_reg(regs, dabt.reg);
     struct vgic_irq_rank *rank;
-    int offset = (int)(info->gpa - v->domain->arch.vgic.dbase);
-    int gicd_reg = REG(offset);
+    int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
 
     switch ( gicd_reg )
     {
@@ -185,7 +182,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         return 1;
 
     /* Implementation defined -- read as zero */
-    case REG(0x020) ... REG(0x03c):
+    case 0x020 ... 0x03c:
         goto read_as_zero;
 
     case GICD_IGROUPR ... GICD_IGROUPRN:
@@ -215,7 +212,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISPENDR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
-        *r = vgic_byte_read(rank->ipend, dabt.sign, offset);
+        *r = vgic_byte_read(rank->ipend, dabt.sign, gicd_reg);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -224,7 +221,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICPENDR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
-        *r = vgic_byte_read(rank->ipend, dabt.sign, offset);
+        *r = vgic_byte_read(rank->ipend, dabt.sign, gicd_reg);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -255,7 +252,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         *r = rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR,
                                            DABT_WORD)];
         if ( dabt.size == DABT_BYTE )
-            *r = vgic_byte_read(*r, dabt.sign, offset);
+            *r = vgic_byte_read(*r, dabt.sign, gicd_reg);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -268,7 +265,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
                                             DABT_WORD)];
         if ( dabt.size == DABT_BYTE )
-            *r = vgic_byte_read(*r, dabt.sign, offset);
+            *r = vgic_byte_read(*r, dabt.sign, gicd_reg);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -296,7 +293,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         rank = vgic_rank_offset(v, 1, gicd_reg - GICD_CPENDSGIR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
-        *r = vgic_byte_read(rank->pendsgi, dabt.sign, offset);
+        *r = vgic_byte_read(rank->pendsgi, dabt.sign, gicd_reg);
         vgic_unlock_rank(v, rank);
         return 1;
 
@@ -305,12 +302,12 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         rank = vgic_rank_offset(v, 1, gicd_reg - GICD_SPENDSGIR, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank);
-        *r = vgic_byte_read(rank->pendsgi, dabt.sign, offset);
+        *r = vgic_byte_read(rank->pendsgi, dabt.sign, gicd_reg);
         vgic_unlock_rank(v, rank);
         return 1;
 
     /* Implementation defined -- read as zero */
-    case REG(0xfd0) ... REG(0xfe4):
+    case 0xfd0 ... 0xfe4:
         goto read_as_zero;
 
     case GICD_ICPIDR2:
@@ -319,27 +316,27 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         return 0;
 
     /* Implementation defined -- read as zero */
-    case REG(0xfec) ... REG(0xffc):
+    case 0xfec ... 0xffc:
         goto read_as_zero;
 
     /* Reserved -- read as zero */
-    case REG(0x00c) ... REG(0x01c):
-    case REG(0x040) ... REG(0x07c):
-    case REG(0x7fc):
-    case REG(0xbfc):
-    case REG(0xf04) ... REG(0xf0c):
-    case REG(0xf30) ... REG(0xfcc):
+    case 0x00c ... 0x01c:
+    case 0x040 ... 0x07c:
+    case 0x7fc:
+    case 0xbfc:
+    case 0xf04 ... 0xf0c:
+    case 0xf30 ... 0xfcc:
         goto read_as_zero;
 
     default:
         printk("vGICD: unhandled read r%d offset %#08x\n",
-               dabt.reg, offset);
+               dabt.reg, gicd_reg);
         return 0;
     }
 
 bad_width:
     printk("vGICD: bad read width %d r%d offset %#08x\n",
-           dabt.size, dabt.reg, offset);
+           dabt.size, dabt.reg, gicd_reg);
     domain_crash_synchronous();
     return 0;
 
@@ -463,8 +460,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
     struct cpu_user_regs *regs = guest_cpu_user_regs();
     register_t *r = select_user_reg(regs, dabt.reg);
     struct vgic_irq_rank *rank;
-    int offset = (int)(info->gpa - v->domain->arch.vgic.dbase);
-    int gicd_reg = REG(offset);
+    int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
     uint32_t tr;
 
     switch ( gicd_reg )
@@ -481,7 +477,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         goto write_ignore;
 
     /* Implementation defined -- write ignored */
-    case REG(0x020) ... REG(0x03c):
+    case 0x020 ... 0x03c:
         goto write_ignore;
 
     case GICD_IGROUPR ... GICD_IGROUPRN:
@@ -557,7 +553,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         else
         {
             tr = REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
-            vgic_byte_write(&rank->itargets[tr], *r, offset);
+            vgic_byte_write(&rank->itargets[tr], *r, gicd_reg);
         }
         vgic_unlock_rank(v, rank);
         return 1;
@@ -573,7 +569,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         else
         {
             tr = REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
-            vgic_byte_write(&rank->ipriority[tr], *r, offset);
+            vgic_byte_write(&rank->ipriority[tr], *r, gicd_reg);
         }
         vgic_unlock_rank(v, rank);
         return 1;
@@ -614,7 +610,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         return 0;
 
     /* Implementation defined -- write ignored */
-    case REG(0xfd0) ... REG(0xfe4):
+    case 0xfd0 ... 0xfe4:
         goto write_ignore;
 
     /* R/O -- write ignore */
@@ -622,27 +618,27 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
         goto write_ignore;
 
     /* Implementation defined -- write ignored */
-    case REG(0xfec) ... REG(0xffc):
+    case 0xfec ... 0xffc:
         goto write_ignore;
 
     /* Reserved -- write ignored */
-    case REG(0x00c) ... REG(0x01c):
-    case REG(0x040) ... REG(0x07c):
-    case REG(0x7fc):
-    case REG(0xbfc):
-    case REG(0xf04) ... REG(0xf0c):
-    case REG(0xf30) ... REG(0xfcc):
+    case 0x00c ... 0x01c:
+    case 0x040 ... 0x07c:
+    case 0x7fc:
+    case 0xbfc:
+    case 0xf04 ... 0xf0c:
+    case 0xf30 ... 0xfcc:
         goto write_ignore;
 
     default:
         printk("vGICD: unhandled write r%d=%"PRIregister" offset %#08x\n",
-               dabt.reg, *r, offset);
+               dabt.reg, *r, gicd_reg);
         return 0;
     }
 
 bad_width:
     printk("vGICD: bad write width %d r%d=%"PRIregister" offset %#08x\n",
-           dabt.size, dabt.reg, *r, offset);
+           dabt.size, dabt.reg, *r, gicd_reg);
     domain_crash_synchronous();
     return 0;
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 13/14] xen/arm: split vgic driver into generic and vgic-v2 driver
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (11 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 12/14] xen/arm: Remove REG macro in vgic driver vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-01 13:08   ` Julien Grall
  2014-07-01  6:41 ` [PATCH v7a 14/14] xen/arm: Restrict saving of gic register for idle domain vijay.kilari
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

Existing vGIC driver has both generic code and hw specific
code. Segregate vGIC low level driver into vgic-v2.c and
keep generic code in existing vgic.c file

some static generic functions in vgic.c is made as non-static
so that these generic functions can be used in vGIC v2 driver.

vGIC v2 driver registers required callbacks to generic vGIC
driver. This helps to plug in next version of vGIC drivers
like vGIC v3. These callbacks are registered per domain

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
---
 xen/arch/arm/Makefile        |    2 +-
 xen/arch/arm/vgic-v2.c       |  507 ++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/vgic.c          |  487 ++++------------------------------------
 xen/include/asm-arm/domain.h |    2 +
 xen/include/asm-arm/gic.h    |    3 +
 xen/include/asm-arm/vgic.h   |   20 ++
 6 files changed, 582 insertions(+), 439 deletions(-)

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 969ee52..20f59f4 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -26,7 +26,7 @@ obj-y += smpboot.o
 obj-y += smp.o
 obj-y += shutdown.o
 obj-y += traps.o
-obj-y += vgic.o
+obj-y += vgic.o vgic-v2.o
 obj-y += vtimer.o
 obj-y += vuart.o
 obj-y += hvm.o
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
new file mode 100644
index 0000000..3484d57
--- /dev/null
+++ b/xen/arch/arm/vgic-v2.c
@@ -0,0 +1,507 @@
+/*
+ * xen/arch/arm/vgic-v2.c
+ *
+ * ARM Virtual Generic Interrupt Controller support v2
+ *
+ * Ian Campbell <ian.campbell@citrix.com>
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/bitops.h>
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/init.h>
+#include <xen/softirq.h>
+#include <xen/irq.h>
+#include <xen/sched.h>
+
+#include <asm/current.h>
+#include <asm/device.h>
+
+#include <asm/mmio.h>
+#include <asm/gic.h>
+#include <asm/vgic.h>
+
+static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
+{
+    struct hsr_dabt dabt = info->dabt;
+    struct cpu_user_regs *regs = guest_cpu_user_regs();
+    register_t *r = select_user_reg(regs, dabt.reg);
+    struct vgic_irq_rank *rank;
+    int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
+
+    switch ( gicd_reg )
+    {
+    case GICD_CTLR:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        vgic_lock(v);
+        *r = v->domain->arch.vgic.ctlr;
+        vgic_unlock(v);
+        return 1;
+    case GICD_TYPER:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        /* No secure world support for guests. */
+        vgic_lock(v);
+        *r = ( (v->domain->max_vcpus << 5) & GICD_TYPE_CPUS )
+            |( ((v->domain->arch.vgic.nr_lines / 32)) & GICD_TYPE_LINES );
+        vgic_unlock(v);
+        return 1;
+    case GICD_IIDR:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        /*
+         * XXX Do we need a JEP106 manufacturer ID?
+         * Just use the physical h/w value for now
+         */
+        *r = 0x0000043b;
+        return 1;
+
+    /* Implementation defined -- read as zero */
+    case 0x020 ... 0x03c:
+        goto read_as_zero;
+
+    case GICD_IGROUPR ... GICD_IGROUPRN:
+        /* We do not implement security extensions for guests, read zero */
+        goto read_as_zero;
+
+    case GICD_ISENABLER ... GICD_ISENABLERN:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+        vgic_lock_rank(v, rank);
+        *r = rank->ienable;
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_ICENABLER ... GICD_ICENABLERN:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+        vgic_lock_rank(v, rank);
+        *r = rank->ienable;
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_ISPENDR ... GICD_ISPENDRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISPENDR, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+        vgic_lock_rank(v, rank);
+        *r = vgic_byte_read(rank->ipend, dabt.sign, gicd_reg);
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_ICPENDR ... GICD_ICPENDRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICPENDR, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+        vgic_lock_rank(v, rank);
+        *r = vgic_byte_read(rank->ipend, dabt.sign, gicd_reg);
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_ISACTIVER ... GICD_ISACTIVERN:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+        vgic_lock_rank(v, rank);
+        *r = rank->iactive;
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_ICACTIVER ... GICD_ICACTIVERN:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+        vgic_lock_rank(v, rank);
+        *r = rank->iactive;
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_ITARGETSR ... GICD_ITARGETSRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+
+        vgic_lock_rank(v, rank);
+        *r = rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR,
+                                           DABT_WORD)];
+        if ( dabt.size == DABT_BYTE )
+            *r = vgic_byte_read(*r, dabt.sign, gicd_reg);
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+
+        vgic_lock_rank(v, rank);
+        *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
+                                            DABT_WORD)];
+        if ( dabt.size == DABT_BYTE )
+            *r = vgic_byte_read(*r, dabt.sign, gicd_reg);
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_ICFGR ... GICD_ICFGRN:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+        vgic_lock_rank(v, rank);
+        *r = rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)];
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_NSACR ... GICD_NSACRN:
+        /* We do not implement security extensions for guests, read zero */
+        goto read_as_zero;
+
+    case GICD_SGIR:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        /* Write only -- read unknown */
+        *r = 0xdeadbeef;
+        return 1;
+
+    case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_CPENDSGIR, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+        vgic_lock_rank(v, rank);
+        *r = vgic_byte_read(rank->pendsgi, dabt.sign, gicd_reg);
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_SPENDSGIR, DABT_WORD);
+        if ( rank == NULL) goto read_as_zero;
+        vgic_lock_rank(v, rank);
+        *r = vgic_byte_read(rank->pendsgi, dabt.sign, gicd_reg);
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    /* Implementation defined -- read as zero */
+    case 0xfd0 ... 0xfe4:
+        goto read_as_zero;
+
+    case GICD_ICPIDR2:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        printk("vGICD: unhandled read from ICPIDR2\n");
+        return 0;
+
+    /* Implementation defined -- read as zero */
+    case 0xfec ... 0xffc:
+        goto read_as_zero;
+
+    /* Reserved -- read as zero */
+    case 0x00c ... 0x01c:
+    case 0x040 ... 0x07c:
+    case 0x7fc:
+    case 0xbfc:
+    case 0xf04 ... 0xf0c:
+    case 0xf30 ... 0xfcc:
+        goto read_as_zero;
+
+    default:
+        printk("vGICD: unhandled read r%d offset %#08x\n",
+               dabt.reg, gicd_reg);
+        return 0;
+    }
+
+bad_width:
+    printk("vGICD: bad read width %d r%d offset %#08x\n",
+           dabt.size, dabt.reg, gicd_reg);
+    domain_crash_synchronous();
+    return 0;
+
+read_as_zero:
+    if ( dabt.size != DABT_WORD ) goto bad_width;
+    *r = 0;
+    return 1;
+}
+
+static int vgic_v2_to_sgi(struct vcpu *v, register_t sgir)
+{
+
+    int virq;
+    int irqmode;
+    enum gic_sgi_mode sgi_mode;
+    unsigned long vcpu_mask = 0;
+
+    irqmode = (sgir & GICD_SGI_TARGET_LIST_MASK) >> GICD_SGI_TARGET_LIST_SHIFT;
+    virq = (sgir & GICD_SGI_INTID_MASK);
+    vcpu_mask = (sgir & GICD_SGI_TARGET_MASK) >> GICD_SGI_TARGET_SHIFT;
+
+    /* Map GIC sgi value to enum value */
+    switch ( irqmode )
+    {
+    case GICD_SGI_TARGET_LIST_VAL:
+        sgi_mode = SGI_TARGET_LIST;
+        break;
+    case GICD_SGI_TARGET_OTHERS_VAL:
+        sgi_mode = SGI_TARGET_OTHERS;
+        break;
+    case GICD_SGI_TARGET_SELF_VAL:
+        sgi_mode = SGI_TARGET_SELF;
+        break;
+    default:
+        BUG();
+    }
+
+    return vgic_to_sgi(v, sgir, sgi_mode, virq, vcpu_mask);
+}
+
+static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
+{
+    struct hsr_dabt dabt = info->dabt;
+    struct cpu_user_regs *regs = guest_cpu_user_regs();
+    register_t *r = select_user_reg(regs, dabt.reg);
+    struct vgic_irq_rank *rank;
+    int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
+    uint32_t tr;
+
+    switch ( gicd_reg )
+    {
+    case GICD_CTLR:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        /* Ignore all but the enable bit */
+        v->domain->arch.vgic.ctlr = (*r) & GICD_CTL_ENABLE;
+        return 1;
+
+    /* R/O -- write ignored */
+    case GICD_TYPER:
+    case GICD_IIDR:
+        goto write_ignore;
+
+    /* Implementation defined -- write ignored */
+    case 0x020 ... 0x03c:
+        goto write_ignore;
+
+    case GICD_IGROUPR ... GICD_IGROUPRN:
+        /* We do not implement security extensions for guests, write ignore */
+        goto write_ignore;
+
+    case GICD_ISENABLER ... GICD_ISENABLERN:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD);
+        if ( rank == NULL) goto write_ignore;
+        vgic_lock_rank(v, rank);
+        tr = rank->ienable;
+        rank->ienable |= *r;
+        vgic_unlock_rank(v, rank);
+        /* The virtual irq is derived from register offset.
+         * The register difference is word difference. So divide by 2(DABT_WORD)
+         * to get Virtual irq number */
+        vgic_enable_irqs(v, (*r) & (~tr),
+                         (gicd_reg - GICD_ISENABLER) >> DABT_WORD);
+        return 1;
+
+    case GICD_ICENABLER ... GICD_ICENABLERN:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD);
+        if ( rank == NULL) goto write_ignore;
+        vgic_lock_rank(v, rank);
+        tr = rank->ienable;
+        rank->ienable &= ~*r;
+        vgic_unlock_rank(v, rank);
+        /* The virtual irq is derived from register offset.
+         * The register difference is word difference. So divide by 2(DABT_WORD)
+         * to get  Virtual irq number */
+        vgic_disable_irqs(v, (*r) & tr,
+                         (gicd_reg - GICD_ICENABLER) >> DABT_WORD);
+        return 1;
+
+    case GICD_ISPENDR ... GICD_ISPENDRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDR%d\n",
+               dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ISPENDR);
+        return 0;
+
+    case GICD_ICPENDR ... GICD_ICPENDRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDR%d\n",
+               dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ICPENDR);
+        return 0;
+
+    case GICD_ISACTIVER ... GICD_ISACTIVERN:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER, DABT_WORD);
+        if ( rank == NULL) goto write_ignore;
+        vgic_lock_rank(v, rank);
+        rank->iactive &= ~*r;
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_ICACTIVER ... GICD_ICACTIVERN:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER, DABT_WORD);
+        if ( rank == NULL) goto write_ignore;
+        vgic_lock_rank(v, rank);
+        rank->iactive &= ~*r;
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_ITARGETSR ... GICD_ITARGETSR + 7:
+        /* SGI/PPI target is read only */
+        goto write_ignore;
+
+    case GICD_ITARGETSR + 8 ... GICD_ITARGETSRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
+        if ( rank == NULL) goto write_ignore;
+        vgic_lock_rank(v, rank);
+        if ( dabt.size == DABT_WORD )
+            rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR,
+                                          DABT_WORD)] = *r;
+        else
+            vgic_byte_write(&rank->itargets[REG_RANK_INDEX(8,
+                       gicd_reg - GICD_ITARGETSR, DABT_WORD)], *r, gicd_reg);
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
+        if ( rank == NULL) goto write_ignore;
+        vgic_lock_rank(v, rank);
+        if ( dabt.size == DABT_WORD )
+            rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
+                                           DABT_WORD)] = *r;
+        else
+            vgic_byte_write(&rank->ipriority[REG_RANK_INDEX(8,
+                        gicd_reg - GICD_IPRIORITYR, DABT_WORD)], *r, gicd_reg);
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_ICFGR: /* SGIs */
+        goto write_ignore;
+    case GICD_ICFGR + 1: /* PPIs */
+        /* It is implementation defined if these are writeable. We chose not */
+        goto write_ignore;
+    case GICD_ICFGR + 2 ... GICD_ICFGRN: /* SPIs */
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD);
+        if ( rank == NULL) goto write_ignore;
+        vgic_lock_rank(v, rank);
+        rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)] = *r;
+        vgic_unlock_rank(v, rank);
+        return 1;
+
+    case GICD_NSACR ... GICD_NSACRN:
+        /* We do not implement security extensions for guests, write ignore */
+        goto write_ignore;
+
+    case GICD_SGIR:
+        if ( dabt.size != DABT_WORD ) goto bad_width;
+        return vgic_send_sgi(v, *r);
+
+    case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDSGIR%d\n",
+               dabt.size ? "word" : "byte", *r, gicd_reg - GICD_CPENDSGIR);
+        return 0;
+
+    case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
+        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
+        printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDSGIR%d\n",
+               dabt.size ? "word" : "byte", *r, gicd_reg - GICD_SPENDSGIR);
+        return 0;
+
+    /* Implementation defined -- write ignored */
+    case 0xfd0 ... 0xfe4:
+        goto write_ignore;
+
+    /* R/O -- write ignore */
+    case GICD_ICPIDR2:
+        goto write_ignore;
+
+    /* Implementation defined -- write ignored */
+    case 0xfec ... 0xffc:
+        goto write_ignore;
+
+    /* Reserved -- write ignored */
+    case 0x00c ... 0x01c:
+    case 0x040 ... 0x07c:
+    case 0x7fc:
+    case 0xbfc:
+    case 0xf04 ... 0xf0c:
+    case 0xf30 ... 0xfcc:
+        goto write_ignore;
+
+    default:
+        printk("vGICD: unhandled write r%d=%"PRIregister" offset %#08x\n",
+               dabt.reg, *r, gicd_reg);
+        return 0;
+    }
+
+bad_width:
+    printk("vGICD: bad write width %d r%d=%"PRIregister" offset %#08x\n",
+           dabt.size, dabt.reg, *r, gicd_reg);
+    domain_crash_synchronous();
+    return 0;
+
+write_ignore:
+    if ( dabt.size != DABT_WORD ) goto bad_width;
+    return 1;
+}
+
+const struct mmio_handler_ops vgic_v2_distr_mmio_handler = {
+    .read_handler  = vgic_v2_distr_mmio_read,
+    .write_handler = vgic_v2_distr_mmio_write,
+};
+
+static int vgic_v2_vcpu_init(struct vcpu *v)
+{
+    int i;
+
+    /* For SGI and PPI the target is always this CPU */
+    for ( i = 0 ; i < 8 ; i++ )
+        v->arch.vgic.private_irqs->itargets[i] =
+              (1<<(v->vcpu_id+0))
+            | (1<<(v->vcpu_id+8))
+            | (1<<(v->vcpu_id+16))
+            | (1<<(v->vcpu_id+24));
+
+    return 0;
+}
+
+static int vgic_v2_domain_init(struct domain *d)
+{
+    /* We rely on gicv_setup() to initialize dbase(vGIC distributor base) */
+    register_mmio_handler(d, &vgic_v2_distr_mmio_handler, d->arch.vgic.dbase,
+                          PAGE_SIZE);
+
+    return 0;
+}
+
+const static struct vgic_ops vgic_v2_ops = {
+    .vcpu_init   = vgic_v2_vcpu_init,
+    .domain_init = vgic_v2_domain_init,
+    .send_sgi    = vgic_v2_to_sgi,
+};
+
+int vgic_v2_init(struct domain *d)
+{
+    register_vgic_ops(d, &vgic_v2_ops);
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 78004b0..9f18347 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -31,14 +31,11 @@
 #include <asm/gic.h>
 #include <asm/vgic.h>
 
-static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info);
-static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info);
-
 /*
  * Returns rank corresponding to a GICD_<FOO><n> register for
  * GICD_<FOO> with <b>-bits-per-interrupt.
  */
-static struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n,
+struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n,
                                               int s)
 {
     int rank = REG_RANK_NR(b, (n >> s));
@@ -56,11 +53,6 @@ static struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq)
     return vgic_rank_offset(v, 8, irq, DABT_WORD);
 }
 
-static const struct mmio_handler_ops vgic_distr_mmio_handler = {
-    .read_handler  = vgic_distr_mmio_read,
-    .write_handler = vgic_distr_mmio_write,
-};
-
 int domain_vgic_init(struct domain *d)
 {
     int i;
@@ -75,6 +67,15 @@ int domain_vgic_init(struct domain *d)
     else
         d->arch.vgic.nr_lines = 0; /* We don't need SPIs for the guest */
 
+    switch ( gic_hw_version() )
+    {
+    case GIC_V2:
+        vgic_v2_init(d);
+        break;
+    default:
+        return -ENODEV;
+    }
+
     d->arch.vgic.shared_irqs =
         xzalloc_array(struct vgic_irq_rank, DOMAIN_NR_RANKS(d));
     if ( d->arch.vgic.shared_irqs == NULL )
@@ -96,15 +97,16 @@ int domain_vgic_init(struct domain *d)
     for (i=0; i<DOMAIN_NR_RANKS(d); i++)
         spin_lock_init(&d->arch.vgic.shared_irqs[i].lock);
 
-    /*
-     * We rely on gicv_setup() to initialize dbase(vGIC distributor base)
-     */
-    register_mmio_handler(d, &vgic_distr_mmio_handler,
-                          d->arch.vgic.dbase, PAGE_SIZE);
+    d->arch.vgic.handler->domain_init(d);
 
     return 0;
 }
 
+void register_vgic_ops(struct domain *d, const struct vgic_ops *ops)
+{
+   d->arch.vgic.handler = ops;
+}
+
 void domain_vgic_free(struct domain *d)
 {
     xfree(d->arch.vgic.shared_irqs);
@@ -121,6 +123,8 @@ int vcpu_vgic_init(struct vcpu *v)
 
     spin_lock_init(&v->arch.vgic.private_irqs->lock);
 
+    v->domain->arch.vgic.handler->vcpu_init(v);
+
     memset(&v->arch.vgic.pending_irqs, 0, sizeof(v->arch.vgic.pending_irqs));
     for (i = 0; i < 32; i++)
     {
@@ -128,13 +132,6 @@ int vcpu_vgic_init(struct vcpu *v)
         INIT_LIST_HEAD(&v->arch.vgic.pending_irqs[i].lr_queue);
     }
 
-    /* For SGI and PPI the target is always this CPU */
-    for ( i = 0 ; i < 8 ; i++ )
-        v->arch.vgic.private_irqs->itargets[i] =
-              (1<<(v->vcpu_id+0))
-            | (1<<(v->vcpu_id+8))
-            | (1<<(v->vcpu_id+16))
-            | (1<<(v->vcpu_id+24));
     INIT_LIST_HEAD(&v->arch.vgic.inflight_irqs);
     INIT_LIST_HEAD(&v->arch.vgic.lr_pending);
     spin_lock_init(&v->arch.vgic.lock);
@@ -148,205 +145,7 @@ int vcpu_vgic_free(struct vcpu *v)
     return 0;
 }
 
-static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
-{
-    struct hsr_dabt dabt = info->dabt;
-    struct cpu_user_regs *regs = guest_cpu_user_regs();
-    register_t *r = select_user_reg(regs, dabt.reg);
-    struct vgic_irq_rank *rank;
-    int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
-
-    switch ( gicd_reg )
-    {
-    case GICD_CTLR:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        vgic_lock(v);
-        *r = v->domain->arch.vgic.ctlr;
-        vgic_unlock(v);
-        return 1;
-    case GICD_TYPER:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        /* No secure world support for guests. */
-        vgic_lock(v);
-        *r = ( (v->domain->max_vcpus<<5) & GICD_TYPE_CPUS )
-            |( ((v->domain->arch.vgic.nr_lines/32)) & GICD_TYPE_LINES );
-        vgic_unlock(v);
-        return 1;
-    case GICD_IIDR:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        /*
-         * XXX Do we need a JEP106 manufacturer ID?
-         * Just use the physical h/w value for now
-         */
-        *r = 0x0000043b;
-        return 1;
-
-    /* Implementation defined -- read as zero */
-    case 0x020 ... 0x03c:
-        goto read_as_zero;
-
-    case GICD_IGROUPR ... GICD_IGROUPRN:
-        /* We do not implement security extensions for guests, read zero */
-        goto read_as_zero;
-
-    case GICD_ISENABLER ... GICD_ISENABLERN:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-        vgic_lock_rank(v, rank);
-        *r = rank->ienable;
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_ICENABLER ... GICD_ICENABLERN:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-        vgic_lock_rank(v, rank);
-        *r = rank->ienable;
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_ISPENDR ... GICD_ISPENDRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISPENDR, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-        vgic_lock_rank(v, rank);
-        *r = vgic_byte_read(rank->ipend, dabt.sign, gicd_reg);
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_ICPENDR ... GICD_ICPENDRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICPENDR, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-        vgic_lock_rank(v, rank);
-        *r = vgic_byte_read(rank->ipend, dabt.sign, gicd_reg);
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_ISACTIVER ... GICD_ISACTIVERN:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-        vgic_lock_rank(v, rank);
-        *r = rank->iactive;
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_ICACTIVER ... GICD_ICACTIVERN:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-        vgic_lock_rank(v, rank);
-        *r = rank->iactive;
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_ITARGETSR ... GICD_ITARGETSRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-
-        vgic_lock_rank(v, rank);
-        *r = rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR,
-                                           DABT_WORD)];
-        if ( dabt.size == DABT_BYTE )
-            *r = vgic_byte_read(*r, dabt.sign, gicd_reg);
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
-        if ( dabt.size != 0 && dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-
-        vgic_lock_rank(v, rank);
-        *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
-                                            DABT_WORD)];
-        if ( dabt.size == DABT_BYTE )
-            *r = vgic_byte_read(*r, dabt.sign, gicd_reg);
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_ICFGR ... GICD_ICFGRN:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-        vgic_lock_rank(v, rank);
-        *r = rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)];
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_NSACR ... GICD_NSACRN:
-        /* We do not implement security extensions for guests, read zero */
-        goto read_as_zero;
-
-    case GICD_SGIR:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        /* Write only -- read unknown */
-        *r = 0xdeadbeef;
-        return 1;
-
-    case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_CPENDSGIR, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-        vgic_lock_rank(v, rank);
-        *r = vgic_byte_read(rank->pendsgi, dabt.sign, gicd_reg);
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_SPENDSGIR, DABT_WORD);
-        if ( rank == NULL) goto read_as_zero;
-        vgic_lock_rank(v, rank);
-        *r = vgic_byte_read(rank->pendsgi, dabt.sign, gicd_reg);
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    /* Implementation defined -- read as zero */
-    case 0xfd0 ... 0xfe4:
-        goto read_as_zero;
-
-    case GICD_ICPIDR2:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        printk("vGICD: unhandled read from ICPIDR2\n");
-        return 0;
-
-    /* Implementation defined -- read as zero */
-    case 0xfec ... 0xffc:
-        goto read_as_zero;
-
-    /* Reserved -- read as zero */
-    case 0x00c ... 0x01c:
-    case 0x040 ... 0x07c:
-    case 0x7fc:
-    case 0xbfc:
-    case 0xf04 ... 0xf0c:
-    case 0xf30 ... 0xfcc:
-        goto read_as_zero;
-
-    default:
-        printk("vGICD: unhandled read r%d offset %#08x\n",
-               dabt.reg, gicd_reg);
-        return 0;
-    }
-
-bad_width:
-    printk("vGICD: bad read width %d r%d offset %#08x\n",
-           dabt.size, dabt.reg, gicd_reg);
-    domain_crash_synchronous();
-    return 0;
-
-read_as_zero:
-    if ( dabt.size != DABT_WORD ) goto bad_width;
-    *r = 0;
-    return 1;
-}
-
-static void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
+void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
 {
     const unsigned long mask = r;
     struct pending_irq *p;
@@ -369,7 +168,7 @@ static void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
     }
 }
 
-static void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
+void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
 {
     const unsigned long mask = r;
     struct pending_irq *p;
@@ -405,246 +204,58 @@ static void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
     }
 }
 
-static int vgic_to_sgi(struct vcpu *v, register_t sgir)
+/* TODO: unsigned long is used to fit vcpu_mask. Change to cpu_mask */
+int vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode, int virq,
+                unsigned long vcpu_mask)
 {
     struct domain *d = v->domain;
-    int virtual_irq;
-    int filter;
     int vcpuid;
     int i;
-    unsigned long vcpu_mask = 0;
 
     ASSERT(d->max_vcpus < 8*sizeof(vcpu_mask));
 
-    filter = (sgir & GICD_SGI_TARGET_LIST_MASK);
-    virtual_irq = (sgir & GICD_SGI_INTID_MASK);
-    ASSERT( virtual_irq < 16 );
+    ASSERT( virq < 16 );
 
-    switch ( filter )
+    switch ( irqmode )
     {
-        case GICD_SGI_TARGET_LIST:
-            vcpu_mask = (sgir & GICD_SGI_TARGET_MASK) >> GICD_SGI_TARGET_SHIFT;
-            break;
-        case GICD_SGI_TARGET_OTHERS:
-            for ( i = 0; i < d->max_vcpus; i++ )
-            {
-                if ( i != current->vcpu_id && is_vcpu_online(d, i) )
-                    set_bit(i, &vcpu_mask);
-            }
-            break;
-        case GICD_SGI_TARGET_SELF:
-            set_bit(current->vcpu_id, &vcpu_mask);
-            break;
-        default:
-            gdprintk(XENLOG_WARNING, "vGICD: unhandled GICD_SGIR write %"PRIregister" with wrong TargetListFilter field\n",
-                     sgir);
-            return 0;
+    case SGI_TARGET_LIST:
+        break;
+    case SGI_TARGET_OTHERS:
+        for ( i = 0; i < d->max_vcpus; i++ )
+        {
+            if ( i != current->vcpu_id && is_vcpu_online(d, i) )
+                set_bit(i, &vcpu_mask);
+        }
+        break;
+    case SGI_TARGET_SELF:
+        set_bit(current->vcpu_id, &vcpu_mask);
+        break;
+    default:
+        gdprintk(XENLOG_WARNING,
+                 "vGICD:unhandled GICD_SGIR write %"PRIregister" \
+                  with wrong mode\n", sgir);
+       return 0;
     }
 
     for_each_set_bit( vcpuid, &vcpu_mask, d->max_vcpus )
     {
         if ( !is_vcpu_online(d, vcpuid) )
         {
-            gdprintk(XENLOG_WARNING, "vGICD: GICD_SGIR write r=%"PRIregister" vcpu_mask=%lx, wrong CPUTargetList\n",
-                     sgir, vcpu_mask);
+            gdprintk(XENLOG_WARNING, "VGIC: write r=%"PRIregister" \
+                     vcpu_mask=%lx, wrong CPUTargetList\n", sgir, vcpu_mask);
             continue;
         }
-        vgic_vcpu_inject_irq(d->vcpu[vcpuid], virtual_irq);
+        vgic_vcpu_inject_irq(d->vcpu[vcpuid], virq);
     }
+
     return 1;
 }
 
-static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
+int vgic_send_sgi(struct vcpu *v, register_t sgir)
 {
-    struct hsr_dabt dabt = info->dabt;
-    struct cpu_user_regs *regs = guest_cpu_user_regs();
-    register_t *r = select_user_reg(regs, dabt.reg);
-    struct vgic_irq_rank *rank;
-    int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
-    uint32_t tr;
-
-    switch ( gicd_reg )
-    {
-    case GICD_CTLR:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        /* Ignore all but the enable bit */
-        v->domain->arch.vgic.ctlr = (*r) & GICD_CTL_ENABLE;
-        return 1;
-
-    /* R/O -- write ignored */
-    case GICD_TYPER:
-    case GICD_IIDR:
-        goto write_ignore;
-
-    /* Implementation defined -- write ignored */
-    case 0x020 ... 0x03c:
-        goto write_ignore;
-
-    case GICD_IGROUPR ... GICD_IGROUPRN:
-        /* We do not implement security extensions for guests, write ignore */
-        goto write_ignore;
-
-    case GICD_ISENABLER ... GICD_ISENABLERN:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD);
-        if ( rank == NULL) goto write_ignore;
-        vgic_lock_rank(v, rank);
-        tr = rank->ienable;
-        rank->ienable |= *r;
-        vgic_unlock_rank(v, rank);
-        vgic_enable_irqs(v, (*r) & (~tr),
-                         (gicd_reg - GICD_ISENABLER) >> DABT_WORD);
-        return 1;
-
-    case GICD_ICENABLER ... GICD_ICENABLERN:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD);
-        if ( rank == NULL) goto write_ignore;
-        vgic_lock_rank(v, rank);
-        tr = rank->ienable;
-        rank->ienable &= ~*r;
-        vgic_unlock_rank(v, rank);
-        vgic_disable_irqs(v, (*r) & tr,
-                          (gicd_reg - GICD_ICENABLER) >> DABT_WORD);
-        return 1;
-
-    case GICD_ISPENDR ... GICD_ISPENDRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDR%d\n",
-               dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ISPENDR);
-        return 0;
-
-    case GICD_ICPENDR ... GICD_ICPENDRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDR%d\n",
-               dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ICPENDR);
-        return 0;
-
-    case GICD_ISACTIVER ... GICD_ISACTIVERN:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER, DABT_WORD);
-        if ( rank == NULL) goto write_ignore;
-        vgic_lock_rank(v, rank);
-        rank->iactive &= ~*r;
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_ICACTIVER ... GICD_ICACTIVERN:
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER, DABT_WORD);
-        if ( rank == NULL) goto write_ignore;
-        vgic_lock_rank(v, rank);
-        rank->iactive &= ~*r;
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_ITARGETSR ... GICD_ITARGETSR + 7:
-        /* SGI/PPI target is read only */
-        goto write_ignore;
-
-    case GICD_ITARGETSR + 8 ... GICD_ITARGETSRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
-        if ( rank == NULL) goto write_ignore;
-        vgic_lock_rank(v, rank);
-        if ( dabt.size == DABT_WORD )
-            rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR,
-                                          DABT_WORD)] = *r;
-        else
-        {
-            tr = REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR, DABT_WORD);
-            vgic_byte_write(&rank->itargets[tr], *r, gicd_reg);
-        }
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
-        if ( rank == NULL) goto write_ignore;
-        vgic_lock_rank(v, rank);
-        if ( dabt.size == DABT_WORD )
-            rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
-                                           DABT_WORD)] = *r;
-        else
-        {
-            tr = REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
-            vgic_byte_write(&rank->ipriority[tr], *r, gicd_reg);
-        }
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_ICFGR: /* SGIs */
-        goto write_ignore;
-    case GICD_ICFGR + 1: /* PPIs */
-        /* It is implementation defined if these are writeable. We chose not */
-        goto write_ignore;
-    case GICD_ICFGR + 2 ... GICD_ICFGRN: /* SPIs */
-        if ( dabt.size != DABT_WORD ) goto bad_width;
-        rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD);
-        if ( rank == NULL) goto write_ignore;
-        vgic_lock_rank(v, rank);
-        rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)] = *r;
-        vgic_unlock_rank(v, rank);
-        return 1;
-
-    case GICD_NSACR ... GICD_NSACRN:
-        /* We do not implement security extensions for guests, write ignore */
-        goto write_ignore;
-
-    case GICD_SGIR:
-        if ( dabt.size != 2 )
-            goto bad_width;
-        return vgic_to_sgi(v, *r);
-
-    case GICD_CPENDSGIR ... GICD_CPENDSGIRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDSGIR%d\n",
-               dabt.size ? "word" : "byte", *r, gicd_reg - GICD_CPENDSGIR);
-        return 0;
-
-    case GICD_SPENDSGIR ... GICD_SPENDSGIRN:
-        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width;
-        printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDSGIR%d\n",
-               dabt.size ? "word" : "byte", *r, gicd_reg - GICD_SPENDSGIR);
-        return 0;
-
-    /* Implementation defined -- write ignored */
-    case 0xfd0 ... 0xfe4:
-        goto write_ignore;
-
-    /* R/O -- write ignore */
-    case GICD_ICPIDR2:
-        goto write_ignore;
-
-    /* Implementation defined -- write ignored */
-    case 0xfec ... 0xffc:
-        goto write_ignore;
-
-    /* Reserved -- write ignored */
-    case 0x00c ... 0x01c:
-    case 0x040 ... 0x07c:
-    case 0x7fc:
-    case 0xbfc:
-    case 0xf04 ... 0xf0c:
-    case 0xf30 ... 0xfcc:
-        goto write_ignore;
+    const struct domain *d = v->domain;
 
-    default:
-        printk("vGICD: unhandled write r%d=%"PRIregister" offset %#08x\n",
-               dabt.reg, *r, gicd_reg);
-        return 0;
-    }
-
-bad_width:
-    printk("vGICD: bad write width %d r%d=%"PRIregister" offset %#08x\n",
-           dabt.size, dabt.reg, *r, gicd_reg);
-    domain_crash_synchronous();
-    return 0;
-
-write_ignore:
-    if ( dabt.size != DABT_WORD ) goto bad_width;
-    return 1;
+    return d->arch.vgic.handler->send_sgi(v, sgir);
 }
 
 struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq)
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 2a1e976..32d0554 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -76,6 +76,8 @@ struct arch_domain
     } virt_timer_base;
 
     struct {
+        /* GIC HW version specific vGIC driver handler */
+        const struct vgic_ops *handler;
         /*
          * Covers access to other members of this struct _except_ for
          * shared_irqs where each member contains its own locking.
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 875729e..a0c07bf 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -53,8 +53,11 @@
 #define GICD_SGI_TARGET_LIST_SHIFT   (24)
 #define GICD_SGI_TARGET_LIST_MASK    (0x3UL << GICD_SGI_TARGET_LIST_SHIFT)
 #define GICD_SGI_TARGET_LIST         (0UL<<GICD_SGI_TARGET_LIST_SHIFT)
+#define GICD_SGI_TARGET_LIST_VAL     (0)
 #define GICD_SGI_TARGET_OTHERS       (1UL<<GICD_SGI_TARGET_LIST_SHIFT)
+#define GICD_SGI_TARGET_OTHERS_VAL   (1)
 #define GICD_SGI_TARGET_SELF         (2UL<<GICD_SGI_TARGET_LIST_SHIFT)
+#define GICD_SGI_TARGET_SELF_VAL     (2)
 #define GICD_SGI_TARGET_SHIFT        (16)
 #define GICD_SGI_TARGET_MASK         (0xFFUL<<GICD_SGI_TARGET_SHIFT)
 #define GICD_SGI_GROUP1              (1UL<<15)
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 7c71d16..b5c75a3 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -86,6 +86,15 @@ struct vgic_irq_rank {
     uint32_t itargets[8];
 };
 
+struct vgic_ops {
+    /* Initialize vGIC */
+    int (*vcpu_init)(struct vcpu *v);
+    /* Domain specific initialization of vGIC */
+    int (*domain_init)(struct domain *d);
+    /* SGI handler of vGIC */
+    int (*send_sgi)(struct vcpu *v, register_t sgir);
+};
+
 /* Number of ranks of interrupt registers for a domain */
 #define DOMAIN_NR_RANKS(d) (((d)->arch.vgic.nr_lines+31)/32)
 
@@ -133,6 +142,8 @@ static inline void vgic_byte_write(uint32_t *reg, uint32_t var, int offset)
     *reg |= var;
 }
 
+extern enum gic_sgi_mode irqmode;
+
 /*
  * Offset of GICD_<FOO><n> with its rank, for GICD_<FOO> size <s> with
  * <b>-bits-per-interrupt.
@@ -145,8 +156,17 @@ extern int vcpu_vgic_init(struct vcpu *v);
 extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq);
 extern void vgic_clear_pending_irqs(struct vcpu *v);
 extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
+extern struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n, int s);
+extern void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n);
+extern void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n);
+extern void register_vgic_ops(struct domain *d, const struct vgic_ops *ops);
+int vgic_v2_init(struct domain *d);
 
 extern int vcpu_vgic_free(struct vcpu *v);
+extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
+                       enum gic_sgi_mode irqmode, int virq,
+                       unsigned long vcpu_mask);
+extern int vgic_send_sgi(struct vcpu *v, register_t sgir);
 #endif /* __ASM_ARM_VGIC_H__ */
 
 /*
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v7a 14/14] xen/arm: Restrict saving of gic register for idle domain
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (12 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 13/14] xen/arm: split vgic driver into generic and vgic-v2 driver vijay.kilari
@ 2014-07-01  6:41 ` vijay.kilari
  2014-07-04 14:25   ` Stefano Stabellini
  2014-07-01 11:06 ` [PATCH v7a 00/14] GIC and VGIC code refactoring Julien Grall
  2014-07-02 11:41 ` Ian Campbell
  15 siblings, 1 reply; 28+ messages in thread
From: vijay.kilari @ 2014-07-01  6:41 UTC (permalink / raw)
  To: Ian.Campbell, julien.grall, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, Vijaya Kumar K, vijay.kilari

From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

Check for idle domain is missing before saving gic context.
Xen stays in hypervisor mode when idle vcpu is running.
So no need to save and restore context when switched to/from
idle domain

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
---
 xen/arch/arm/gic.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index e1e27b35..c0d70b8 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -70,6 +70,9 @@ void gic_save_state(struct vcpu *v)
 {
     ASSERT(!local_irq_is_enabled());
 
+    if ( is_idle_vcpu(v) )
+        return;
+
     /* No need for spinlocks here because interrupts are disabled around
      * this call and it only accesses struct vcpu fields that cannot be
      * accessed simultaneously by another pCPU.
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 09/14] xen/arm: move and rename is_vcpu_running function to sched.h
  2014-07-01  6:41 ` [PATCH v7a 09/14] xen/arm: move and rename is_vcpu_running function to sched.h vijay.kilari
@ 2014-07-01  7:55   ` Jan Beulich
  2014-07-01  9:32     ` George Dunlap
  2014-07-02 11:19     ` Ian Campbell
  0 siblings, 2 replies; 28+ messages in thread
From: Jan Beulich @ 2014-07-01  7:55 UTC (permalink / raw)
  To: vijay.kilari
  Cc: keir, Ian.Campbell, stefano.stabellini, Prasun.Kapoor,
	Vijaya Kumar K, julien.grall, tim, george.dunlap, xen-devel,
	stefano.stabellini

>>> On 01.07.14 at 08:41, <vijay.kilari@gmail.com> wrote:
> @@ -829,6 +829,20 @@ void watchdog_domain_destroy(struct domain *d);
>  #define need_iommu(d)    (0)
>  #endif
>  
> +static inline bool_t is_vcpu_online(const struct domain *d, unsigned int vcpuid)

I'm sorry for paying attention to this only now, but a function named
this way would ordinarily have a single const struct vcpu * parameter.
If the decoding of the (domain, vcpuid) tuple is to remain in the
function I guess it ought to be renamed to e.g. is_domain_vcpu_online()
(I'd further suggest to drop the is_ prefix, but I realize others may be
of different opinion).

Jan

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 09/14] xen/arm: move and rename is_vcpu_running function to sched.h
  2014-07-01  7:55   ` Jan Beulich
@ 2014-07-01  9:32     ` George Dunlap
  2014-07-02 11:19     ` Ian Campbell
  1 sibling, 0 replies; 28+ messages in thread
From: George Dunlap @ 2014-07-01  9:32 UTC (permalink / raw)
  To: Jan Beulich, vijay.kilari
  Cc: keir, Ian.Campbell, stefano.stabellini, Prasun.Kapoor,
	Vijaya Kumar K, julien.grall, tim, george.dunlap, xen-devel,
	stefano.stabellini

On 07/01/2014 08:55 AM, Jan Beulich wrote:
>>>> On 01.07.14 at 08:41, <vijay.kilari@gmail.com> wrote:
>> @@ -829,6 +829,20 @@ void watchdog_domain_destroy(struct domain *d);
>>   #define need_iommu(d)    (0)
>>   #endif
>>
>> +static inline bool_t is_vcpu_online(const struct domain *d, unsigned int vcpuid)
>
> I'm sorry for paying attention to this only now, but a function named
> this way would ordinarily have a single const struct vcpu * parameter.
> If the decoding of the (domain, vcpuid) tuple is to remain in the
> function I guess it ought to be renamed to e.g. is_domain_vcpu_online()

+1

> (I'd further suggest to drop the is_ prefix, but I realize others may be
> of different opinion).

I'd probably be of the "keep the is_" opinion. :-)

  -George

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 00/14] GIC and VGIC code refactoring
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (13 preceding siblings ...)
  2014-07-01  6:41 ` [PATCH v7a 14/14] xen/arm: Restrict saving of gic register for idle domain vijay.kilari
@ 2014-07-01 11:06 ` Julien Grall
  2014-07-02 11:41 ` Ian Campbell
  15 siblings, 0 replies; 28+ messages in thread
From: Julien Grall @ 2014-07-01 11:06 UTC (permalink / raw)
  To: vijay.kilari, Ian.Campbell, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, vijaya.kumar

Hi Vijay,

On 07/01/2014 07:41 AM, vijay.kilari@gmail.com wrote:
> Major changes in v7a:
>  - Made changes to send_SGI() to pass NULL as cpu_mask for 
>    sgi modes which does not require cpu mask
>  - Renamed update_cpu_lr_mask() clear_cpu_lr_mask()
>  - used writeb_relaxed() to access ITARGETR & IPRIORITYR 
>    registers
> 
> Major changes in v6a:
>  - Changed send_SGI parameters ordering
>  - coding styles and missing comments
>  - New patch (17) to check for idle domain before saving GIC context
>  - Introduced new callback in vgic handler for handling SGI
> 
> Major changes in v5:
>  - Introduced new patch for checking platform capability for gicv3
>  - Introduced more patches for vgic clean up and code movement
>  - Added synchronization barriers and clean up in GICv3 driver
>  - Rebase on top of master branch +
>    remotes/origin/no_maintenance_interrupts-v8 patch set
>  - Code base available in github
>    git clone https://github.com/vijaykilari/Xen-GICv3.git

It would be nice if you update your repo every time you send a new
series. It will avoid us to try to find your base version.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 01/14] xen/arm: make sgi handling generic
  2014-07-01  6:41 ` [PATCH v7a 01/14] xen/arm: make sgi handling generic vijay.kilari
@ 2014-07-01 11:13   ` Julien Grall
  2014-07-02 10:51     ` Ian Campbell
  0 siblings, 1 reply; 28+ messages in thread
From: Julien Grall @ 2014-07-01 11:13 UTC (permalink / raw)
  To: vijay.kilari, Ian.Campbell, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, vijaya.kumar

Hi Vijay,

On 07/01/2014 07:41 AM, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> 
> move all the hw specific sgi handling functionality
> to one function and use it.
> 
> -----------------------------------------

I've asked for 3 dashes (---) for a specific reason. Git will drop
everything after those 3 dashes. N dashes won't work here...

> changes in v6a: change send_SGI() parameter order
> changes in v7a: passed NULL as null for SGIs sent
>                 with SGI_TARGET_SELF and SGI_TARGET_OTHERS mode

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 03/14] xen/arm: segregate and split GIC low level functionality
  2014-07-01  6:41 ` [PATCH v7a 03/14] xen/arm: segregate and split GIC low level functionality vijay.kilari
@ 2014-07-01 11:32   ` Julien Grall
  0 siblings, 0 replies; 28+ messages in thread
From: Julien Grall @ 2014-07-01 11:32 UTC (permalink / raw)
  To: vijay.kilari, Ian.Campbell, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, vijaya.kumar

Hi Vijay,

On 07/01/2014 07:41 AM, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> 
> GIC driver contains both generic and hardware specific low
> level functionality in gic.c file.
> 
> With this patch, low level functionality is moved to separate
> file gic-v2.c and generic code is kept in gic.c file
> 
> Callbacks are registered by low level driver with generic driver
> and are called wherever required.
> 
> The locking mechanism is not changed.
> 
> This helps to separate generic and hardware functionality
> and implement future hardware version drivers.
> 
> -------------------------------------------------------------
> Changes in v7a:
>            -Renamed update_cpu_lr_mask() to clear_cpu_lr_mask().
>            -Reflected changes made to gic.c in patch 1 & 2
>             to gic-v2.c
> 
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

Acked-by: Julien Grall <julien.grall@linaro.org>
Tested-by: Julien Grall <julien.grall@linaro.org>

Regards,


-- 
Julien Grall

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 13/14] xen/arm: split vgic driver into generic and vgic-v2 driver
  2014-07-01  6:41 ` [PATCH v7a 13/14] xen/arm: split vgic driver into generic and vgic-v2 driver vijay.kilari
@ 2014-07-01 13:08   ` Julien Grall
  2014-07-02  6:39     ` Vijay Kilari
  0 siblings, 1 reply; 28+ messages in thread
From: Julien Grall @ 2014-07-01 13:08 UTC (permalink / raw)
  To: vijay.kilari, Ian.Campbell, stefano.stabellini,
	stefano.stabellini, tim, xen-devel
  Cc: Prasun.Kapoor, vijaya.kumar

Hi Vijay,

You continue to ignore my comments on this patch... Please explain why
you don't want to make those changes. Sending 3 times the same patch
without any change is a waste of time for both of us.

On 07/01/2014 07:41 AM, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> 
> Existing vGIC driver has both generic code and hw specific
> code. Segregate vGIC low level driver into vgic-v2.c and
> keep generic code in existing vgic.c file

Missing "." at the end?

> some static generic functions in vgic.c is made as non-static

Uppercase for the first letter of the first word.

s/is/are/

[..]

> +const struct mmio_handler_ops vgic_v2_distr_mmio_handler = {

There was a static on the previous location. You should keep it.

[..]

> +const static struct vgic_ops vgic_v2_ops = {
> +    .vcpu_init   = vgic_v2_vcpu_init,
> +    .domain_init = vgic_v2_domain_init,
> +    .send_sgi    = vgic_v2_to_sgi,
> +};

static const.

[..]

> diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
> index 78004b0..9f18347 100644
> --- a/xen/arch/arm/vgic.c
> +++ b/xen/arch/arm/vgic.c

[..]

>  int domain_vgic_init(struct domain *d)
>  {
>      int i;
> @@ -75,6 +67,15 @@ int domain_vgic_init(struct domain *d)
>      else
>          d->arch.vgic.nr_lines = 0; /* We don't need SPIs for the guest */
>  
> +    switch ( gic_hw_version() )
> +    {
> +    case GIC_V2:
> +        vgic_v2_init(d);

vgic_v2_init is returning an int to indicate if the initialization has
succeeded or not. Please check the return to see if an error occurred.

> -static int vgic_to_sgi(struct vcpu *v, register_t sgir)
> +/* TODO: unsigned long is used to fit vcpu_mask. Change to cpu_mask */
> +int vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode, int virq,
> +                unsigned long vcpu_mask)


[..]

> +    case SGI_TARGET_OTHERS:

[..]

> +        break;
> +    case SGI_TARGET_SELF:
> +        set_bit(current->vcpu_id, &vcpu_mask);

I already said it on V4, V5 and now V6a and don't see any change or
comment from you side.

For SGI_TARGET_{OTHERS,SELF}, you can't assume that vcpu_mask will be
equal to 0...

It comes directly guest write to GICD_SIGR. Please make sure to handle
it correctly or the guest could send SGI to the wrong VCPUs.

[..]

> +struct vgic_ops {
> +    /* Initialize vGIC */
> +    int (*vcpu_init)(struct vcpu *v);
> +    /* Domain specific initialization of vGIC */
> +    int (*domain_init)(struct domain *d);
> +    /* SGI handler of vGIC */
> +    int (*send_sgi)(struct vcpu *v, register_t sgir);

You've introduced vgic_send_sgi here, I'm not sure to understand why...
Can you give more input?

> +};
> +
>  /* Number of ranks of interrupt registers for a domain */
>  #define DOMAIN_NR_RANKS(d) (((d)->arch.vgic.nr_lines+31)/32)
>  
> @@ -133,6 +142,8 @@ static inline void vgic_byte_write(uint32_t *reg, uint32_t var, int offset)
>      *reg |= var;
>  }
>  
> +extern enum gic_sgi_mode irqmode;
> +

Hu? What is used for?

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 13/14] xen/arm: split vgic driver into generic and vgic-v2 driver
  2014-07-01 13:08   ` Julien Grall
@ 2014-07-02  6:39     ` Vijay Kilari
  2014-07-02  9:01       ` Julien Grall
  0 siblings, 1 reply; 28+ messages in thread
From: Vijay Kilari @ 2014-07-02  6:39 UTC (permalink / raw)
  To: Julien Grall
  Cc: Ian Campbell, Stefano Stabellini, Prasun Kapoor, Vijaya Kumar K,
	Tim Deegan, xen-devel, Stefano Stabellini

Hi Julien,


On Tue, Jul 1, 2014 at 6:38 PM, Julien Grall <julien.grall@linaro.org> wrote:

>> -static int vgic_to_sgi(struct vcpu *v, register_t sgir)
>> +/* TODO: unsigned long is used to fit vcpu_mask. Change to cpu_mask */
>> +int vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode, int virq,
>> +                unsigned long vcpu_mask)
>
>
> [..]
>
>> +    case SGI_TARGET_OTHERS:
>
> [..]
>
>> +        break;
>> +    case SGI_TARGET_SELF:
>> +        set_bit(current->vcpu_id, &vcpu_mask);
>
> I already said it on V4, V5 and now V6a and don't see any change or
> comment from you side.
>
> For SGI_TARGET_{OTHERS,SELF}, you can't assume that vcpu_mask will be
> equal to 0...
>
> It comes directly guest write to GICD_SIGR. Please make sure to handle
> it correctly or the guest could send SGI to the wrong VCPUs.

Sorry I missed this patch to fix the comments.

First, if Guest uses this series of patches, mask is not written to GICD_SGIR
for OTHERS & SELF case in v2 driver

static void gicv2_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
                           const cpumask_t *cpu_mask)
{
    unsigned int mask = 0;

    switch ( irqmode )
    {
    case SGI_TARGET_OTHERS:
        writel_relaxed(GICD_SGI_TARGET_OTHERS | sgi, GICD + GICD_SGIR);
        break;
    case SGI_TARGET_SELF:
        writel_relaxed(GICD_SGI_TARGET_SELF | sgi, GICD + GICD_SGIR);
        break;

Even if Guest writes some values to mask, then only way I check is to forcefully
make vcpu_mask as 0 for OTHERS & SELF case before using it with warning


>
> [..]
>
>> +struct vgic_ops {
>> +    /* Initialize vGIC */
>> +    int (*vcpu_init)(struct vcpu *v);
>> +    /* Domain specific initialization of vGIC */
>> +    int (*domain_init)(struct domain *d);
>> +    /* SGI handler of vGIC */
>> +    int (*send_sgi)(struct vcpu *v, register_t sgir);
>
> You've introduced vgic_send_sgi here, I'm not sure to understand why...
> Can you give more input?

    You have asked me make sending sgi as a callback.
So I have introduced the following way

On GICD_SGIR write by guest, vgic-v2.c calls vgic_send_sgi()
which will call the registered callback (*send_sgi).
Here send_sgi is registered with vgic_v2_to_sgi() which will inject
sgi

>
>> +};
>> +
>>  /* Number of ranks of interrupt registers for a domain */
>>  #define DOMAIN_NR_RANKS(d) (((d)->arch.vgic.nr_lines+31)/32)
>>
>> @@ -133,6 +142,8 @@ static inline void vgic_byte_write(uint32_t *reg, uint32_t var, int offset)
>>      *reg |= var;
>>  }
>>
>> +extern enum gic_sgi_mode irqmode;
>> +
>
> Hu? What is used for?

   This is forward declaration for below function in vgic.h file. May
be extern is not required here
   extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
                       enum gic_sgi_mode irqmode, int virq,
                       unsigned long vcpu_mask);

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 13/14] xen/arm: split vgic driver into generic and vgic-v2 driver
  2014-07-02  6:39     ` Vijay Kilari
@ 2014-07-02  9:01       ` Julien Grall
  0 siblings, 0 replies; 28+ messages in thread
From: Julien Grall @ 2014-07-02  9:01 UTC (permalink / raw)
  To: Vijay Kilari
  Cc: Ian Campbell, Stefano Stabellini, Prasun Kapoor, Vijaya Kumar K,
	Tim Deegan, xen-devel, Stefano Stabellini



On 02/07/14 07:39, Vijay Kilari wrote:
> On Tue, Jul 1, 2014 at 6:38 PM, Julien Grall <julien.grall@linaro.org> wrote:
>
>>> -static int vgic_to_sgi(struct vcpu *v, register_t sgir)
>>> +/* TODO: unsigned long is used to fit vcpu_mask. Change to cpu_mask */
>>> +int vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode, int virq,
>>> +                unsigned long vcpu_mask)
>>
>>
>> [..]
>>
>>> +    case SGI_TARGET_OTHERS:
>>
>> [..]
>>
>>> +        break;
>>> +    case SGI_TARGET_SELF:
>>> +        set_bit(current->vcpu_id, &vcpu_mask);
>>
>> I already said it on V4, V5 and now V6a and don't see any change or
>> comment from you side.
>>
>> For SGI_TARGET_{OTHERS,SELF}, you can't assume that vcpu_mask will be
>> equal to 0...
>>
>> It comes directly guest write to GICD_SIGR. Please make sure to handle
>> it correctly or the guest could send SGI to the wrong VCPUs.
>
> Sorry I missed this patch to fix the comments.
>
> First, if Guest uses this series of patches, mask is not written to GICD_SGIR
> for OTHERS & SELF case in v2 driver

That's not a reason to make buggy assumption. You will have to fix some 
day for another GIC driver. It's better to fix it today otherwise we 
will forget it later.

> static void gicv2_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
>                             const cpumask_t *cpu_mask)
> {
>      unsigned int mask = 0;
>
>      switch ( irqmode )
>      {
>      case SGI_TARGET_OTHERS:
>          writel_relaxed(GICD_SGI_TARGET_OTHERS | sgi, GICD + GICD_SGIR);
>          break;
>      case SGI_TARGET_SELF:
>          writel_relaxed(GICD_SGI_TARGET_SELF | sgi, GICD + GICD_SGIR);
>          break;
>
> Even if Guest writes some values to mask, then only way I check is to forcefully
> make vcpu_mask as 0 for OTHERS & SELF case before using it with warning

For the GICv2 POV it's perfectly valid to write garbage in CPUTargetList 
while we send an SGI to ourself. I'm fine with vcpu_mask = 0, but the 
warning is not useful as it's not a bug.

>>
>> [..]
>>
>>> +struct vgic_ops {
>>> +    /* Initialize vGIC */
>>> +    int (*vcpu_init)(struct vcpu *v);
>>> +    /* Domain specific initialization of vGIC */
>>> +    int (*domain_init)(struct domain *d);
>>> +    /* SGI handler of vGIC */
>>> +    int (*send_sgi)(struct vcpu *v, register_t sgir);
>>
>> You've introduced vgic_send_sgi here, I'm not sure to understand why...
>> Can you give more input?
>
>      You have asked me make sending sgi as a callback.
> So I have introduced the following way
>
> On GICD_SGIR write by guest, vgic-v2.c calls vgic_send_sgi()
> which will call the registered callback (*send_sgi).
> Here send_sgi is registered with vgic_v2_to_sgi() which will inject
> sgi

IIRC, I've asked this change for the SGI support on VGICv3 to handle 
sysreg per vGIC.
IHMO, here it's as no-sense because the usage looks useless. I would 
like to see your GICv3 series before saying this is OK.

>>
>>> +};
>>> +
>>>   /* Number of ranks of interrupt registers for a domain */
>>>   #define DOMAIN_NR_RANKS(d) (((d)->arch.vgic.nr_lines+31)/32)
>>>
>>> @@ -133,6 +142,8 @@ static inline void vgic_byte_write(uint32_t *reg, uint32_t var, int offset)
>>>       *reg |= var;
>>>   }
>>>
>>> +extern enum gic_sgi_mode irqmode;
>>> +
>>
>> Hu? What is used for?
>
>     This is forward declaration for below function in vgic.h file. May
> be extern is not required here
>     extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
>                         enum gic_sgi_mode irqmode, int virq,
>                         unsigned long vcpu_mask);

Forward declaration of what? Here, you are defining an external variable 
"irqmode" which is never used.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 01/14] xen/arm: make sgi handling generic
  2014-07-01 11:13   ` Julien Grall
@ 2014-07-02 10:51     ` Ian Campbell
  0 siblings, 0 replies; 28+ messages in thread
From: Ian Campbell @ 2014-07-02 10:51 UTC (permalink / raw)
  To: Julien Grall
  Cc: vijay.kilari, stefano.stabellini, Prasun.Kapoor, vijaya.kumar,
	tim, xen-devel, stefano.stabellini

On Tue, 2014-07-01 at 12:13 +0100, Julien Grall wrote:
> Hi Vijay,
> 
> On 07/01/2014 07:41 AM, vijay.kilari@gmail.com wrote:
> > From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> > 
> > move all the hw specific sgi handling functionality
> > to one function and use it.
> > 
> > -----------------------------------------
> 
> I've asked for 3 dashes (---) for a specific reason. Git will drop
> everything after those 3 dashes. N dashes won't work here...

Please see
http://article.gmane.org/gmane.comp.emulators.xen.devel/205573 for an
example of the correct placement of these between-versions changelogs.

I'll fix these up this time.

Ian.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 09/14] xen/arm: move and rename is_vcpu_running function to sched.h
  2014-07-01  7:55   ` Jan Beulich
  2014-07-01  9:32     ` George Dunlap
@ 2014-07-02 11:19     ` Ian Campbell
  2014-07-02 13:03       ` Vijay Kilari
  1 sibling, 1 reply; 28+ messages in thread
From: Ian Campbell @ 2014-07-02 11:19 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, vijay.kilari, stefano.stabellini, Prasun.Kapoor,
	Vijaya Kumar K, julien.grall, tim, george.dunlap, xen-devel,
	stefano.stabellini

On Tue, 2014-07-01 at 08:55 +0100, Jan Beulich wrote:
> >>> On 01.07.14 at 08:41, <vijay.kilari@gmail.com> wrote:
> > @@ -829,6 +829,20 @@ void watchdog_domain_destroy(struct domain *d);
> >  #define need_iommu(d)    (0)
> >  #endif
> >  
> > +static inline bool_t is_vcpu_online(const struct domain *d, unsigned int vcpuid)
> 
> I'm sorry for paying attention to this only now, but a function named
> this way would ordinarily have a single const struct vcpu * parameter.
> If the decoding of the (domain, vcpuid) tuple is to remain in the
> function I guess it ought to be renamed to e.g. is_domain_vcpu_online()

Looking at the callers it doesn't seem unreasonable to me to push the
indexing of d->vcpus into them.

d is used for the d->max_vcpus check -- which the callers all have
already or are naturally avoiding and the check for d->vcpus == NULL,
which I suspect is out of the question for the existing callers (but
would need checking)

> (I'd further suggest to drop the is_ prefix, but I realize others may be
> of different opinion).
> 
> Jan
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 00/14] GIC and VGIC code refactoring
  2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
                   ` (14 preceding siblings ...)
  2014-07-01 11:06 ` [PATCH v7a 00/14] GIC and VGIC code refactoring Julien Grall
@ 2014-07-02 11:41 ` Ian Campbell
  15 siblings, 0 replies; 28+ messages in thread
From: Ian Campbell @ 2014-07-02 11:41 UTC (permalink / raw)
  To: vijay.kilari
  Cc: stefano.stabellini, Prasun.Kapoor, vijaya.kumar, julien.grall,
	tim, xen-devel, stefano.stabellini

On Tue, 2014-07-01 at 12:11 +0530, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

I've applied up to and including patch #8 "xen/arm: move vgic defines to
vgic header file". Jan had a comment on #9 so I stopped there for now.

Ian.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 09/14] xen/arm: move and rename is_vcpu_running function to sched.h
  2014-07-02 11:19     ` Ian Campbell
@ 2014-07-02 13:03       ` Vijay Kilari
  0 siblings, 0 replies; 28+ messages in thread
From: Vijay Kilari @ 2014-07-02 13:03 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Keir (Xen.org),
	Stefano Stabellini, Prasun Kapoor, Vijaya Kumar K, Julien Grall,
	Tim Deegan, george.dunlap, xen-devel, Stefano Stabellini,
	Jan Beulich

On Wed, Jul 2, 2014 at 4:49 PM, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Tue, 2014-07-01 at 08:55 +0100, Jan Beulich wrote:
>> >>> On 01.07.14 at 08:41, <vijay.kilari@gmail.com> wrote:
>> > @@ -829,6 +829,20 @@ void watchdog_domain_destroy(struct domain *d);
>> >  #define need_iommu(d)    (0)
>> >  #endif
>> >
>> > +static inline bool_t is_vcpu_online(const struct domain *d, unsigned int vcpuid)
>>
>> I'm sorry for paying attention to this only now, but a function named
>> this way would ordinarily have a single const struct vcpu * parameter.
>> If the decoding of the (domain, vcpuid) tuple is to remain in the
>> function I guess it ought to be renamed to e.g. is_domain_vcpu_online()
>
> Looking at the callers it doesn't seem unreasonable to me to push the
> indexing of d->vcpus into them.
>
> d is used for the d->max_vcpus check -- which the callers all have
> already or are naturally avoiding and the check for d->vcpus == NULL,
> which I suspect is out of the question for the existing callers (but
> would need checking)

Yes, check for d->max_vcpus is already taken care by for_each_set_bit
and check for d->vcpus == NULL can be done by caller and
with this, is_vcpu_online() can take vcpu is parameter

>
>> (I'd further suggest to drop the is_ prefix, but I realize others may be
>> of different opinion).
>>
>> Jan
>>
>
>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v7a 14/14] xen/arm: Restrict saving of gic register for idle domain
  2014-07-01  6:41 ` [PATCH v7a 14/14] xen/arm: Restrict saving of gic register for idle domain vijay.kilari
@ 2014-07-04 14:25   ` Stefano Stabellini
  0 siblings, 0 replies; 28+ messages in thread
From: Stefano Stabellini @ 2014-07-04 14:25 UTC (permalink / raw)
  To: vijay.kilari
  Cc: Ian.Campbell, stefano.stabellini, Prasun.Kapoor, Vijaya Kumar K,
	julien.grall, tim, xen-devel, stefano.stabellini

On Tue, 1 Jul 2014, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> 
> Check for idle domain is missing before saving gic context.
> Xen stays in hypervisor mode when idle vcpu is running.
> So no need to save and restore context when switched to/from
> idle domain
> 
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>

Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>



>  xen/arch/arm/gic.c |    3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index e1e27b35..c0d70b8 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -70,6 +70,9 @@ void gic_save_state(struct vcpu *v)
>  {
>      ASSERT(!local_irq_is_enabled());
>  
> +    if ( is_idle_vcpu(v) )
> +        return;
> +
>      /* No need for spinlocks here because interrupts are disabled around
>       * this call and it only accesses struct vcpu fields that cannot be
>       * accessed simultaneously by another pCPU.
> -- 
> 1.7.9.5
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2014-07-04 14:25 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-01  6:41 [PATCH v7a 00/14] GIC and VGIC code refactoring vijay.kilari
2014-07-01  6:41 ` [PATCH v7a 01/14] xen/arm: make sgi handling generic vijay.kilari
2014-07-01 11:13   ` Julien Grall
2014-07-02 10:51     ` Ian Campbell
2014-07-01  6:41 ` [PATCH v7a 02/14] xen/arm: use ioremap to map gic-v2 registers vijay.kilari
2014-07-01  6:41 ` [PATCH v7a 03/14] xen/arm: segregate and split GIC low level functionality vijay.kilari
2014-07-01 11:32   ` Julien Grall
2014-07-01  6:41 ` [PATCH v7a 04/14] xen/arm: move GIC context data structure to gic driver vijay.kilari
2014-07-01  6:41 ` [PATCH v7a 05/14] xen/arm: use device api to detect GIC version vijay.kilari
2014-07-01  6:41 ` [PATCH v7a 06/14] xen/arm: switch to dynamic allocation of vgic rank vijay.kilari
2014-07-01  6:41 ` [PATCH v7a 07/14] xen/arm: prefix byte_read and byte_write functions with vgic vijay.kilari
2014-07-01  6:41 ` [PATCH v7a 08/14] xen/arm: move vgic defines to vgic header file vijay.kilari
2014-07-01  6:41 ` [PATCH v7a 09/14] xen/arm: move and rename is_vcpu_running function to sched.h vijay.kilari
2014-07-01  7:55   ` Jan Beulich
2014-07-01  9:32     ` George Dunlap
2014-07-02 11:19     ` Ian Campbell
2014-07-02 13:03       ` Vijay Kilari
2014-07-01  6:41 ` [PATCH v7a 10/14] xen/arm: move pending_irq structure to vgic header file vijay.kilari
2014-07-01  6:41 ` [PATCH v7a 11/14] xen/arm: calculate vgic irq rank based on register size vijay.kilari
2014-07-01  6:41 ` [PATCH v7a 12/14] xen/arm: Remove REG macro in vgic driver vijay.kilari
2014-07-01  6:41 ` [PATCH v7a 13/14] xen/arm: split vgic driver into generic and vgic-v2 driver vijay.kilari
2014-07-01 13:08   ` Julien Grall
2014-07-02  6:39     ` Vijay Kilari
2014-07-02  9:01       ` Julien Grall
2014-07-01  6:41 ` [PATCH v7a 14/14] xen/arm: Restrict saving of gic register for idle domain vijay.kilari
2014-07-04 14:25   ` Stefano Stabellini
2014-07-01 11:06 ` [PATCH v7a 00/14] GIC and VGIC code refactoring Julien Grall
2014-07-02 11:41 ` Ian Campbell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.