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

[Xen-devel] [RFC PATCH v1 08/10] xen/arm: Add support for GIC v3



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

Add support for GIC v3 specification.
This driver assumes that ARE and SRE
is enable by default.

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>
---
 xen/arch/arm/Makefile             |    2 +-
 xen/arch/arm/gic-v3.c             |  944 +++++++++++++++++++++++++++++++++++++
 xen/arch/arm/gic.c                |   12 +
 xen/include/asm-arm/domain.h      |    4 +
 xen/include/asm-arm/gic.h         |    9 +
 xen/include/asm-arm/gic_v3_defs.h |  211 +++++++++
 6 files changed, 1181 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 20f59f4..a11c699 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 gic-v2.o
+obj-y += gic.o gic-v2.o gic-v3.o
 obj-y += io.o
 obj-y += irq.o
 obj-y += kernel.o
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
new file mode 100644
index 0000000..81a36ba
--- /dev/null
+++ b/xen/arch/arm/gic-v3.c
@@ -0,0 +1,944 @@
+/*
+ * xen/arch/arm/gic-v3.c
+ *
+ * ARM Generic Interrupt Controller support v3 version
+ * based on xen/arch/arm/gic-v2.c
+ * 
+ * Vijaya Kumar K <vijaya.kumar@xxxxxxxxxxxxxxxxxx>
+ * Copyright (c) 2014 Cavium Inc.
+ * 
+ * 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/cpu.h>
+#include <xen/mm.h>
+#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>
+#include <asm/p2m.h>
+#include <asm/domain.h>
+#include <asm/platform.h>
+
+#include <asm/gic_v3_defs.h>
+#include <asm/gic.h>
+#include <asm/io.h>
+
+struct rdist_region {
+    paddr_t rdist_base;
+    paddr_t rdist_base_size;
+    void __iomem *map_rdist_base;
+};
+       
+/* Global state */
+static struct {
+    paddr_t dbase;            /* Address of distributor registers */
+    paddr_t dbase_size;
+    void __iomem *map_dbase;  /* Mapped address of distributor registers */
+    struct rdist_region *rdist_regions;
+    u32  rdist_stride;
+    unsigned int rdist_count; /* Number of rdist regions count */
+    unsigned int lines;       /* Number of interrupts (SPIs + PPIs + SGIs) */
+    struct dt_irq maintenance;
+    unsigned int cpus;
+    int hw_version;
+    spinlock_t lock;
+} gic;
+
+struct gic_state_data {
+    uint32_t gic_hcr, gic_vmcr;
+    uint32_t gic_apr0[4];
+    uint32_t gic_apr1[4];
+    uint64_t gic_lr[16];
+};
+
+#define GICD ((volatile unsigned char *) gic.map_dbase)
+/* Only one region is implemented which is enough for 0-31 cpus */
+#define GICR ((volatile unsigned char *) gic.rdist_regions[0].map_rdist_base)
+
+/* per-cpu re-distributor base */
+static DEFINE_PER_CPU(paddr_t, rbase);
+static DEFINE_PER_CPU(paddr_t, phy_rbase);
+
+static unsigned nr_lrs;
+static uint32_t nr_priorities;
+
+/* The GIC mapping of CPU interfaces does not necessarily match the
+ * logical CPU numbering. Let's use mapping as returned by the GIC
+ * itself
+ */
+
+#define gic_data_rdist_rd_base()        (this_cpu(rbase))
+#define gic_data_rdist_sgi_base()       (gic_data_rdist_rd_base() + SZ_64K)
+
+static inline u64 read_cpuid_mpidr(void)
+{
+   return READ_SYSREG(MPIDR_EL1);
+}
+
+static u64 gich_read_lr(int lr)
+{
+    switch (lr) 
+    {
+        case 0: /* ICH_LRn is 64 bit */
+            return READ_SYSREG(ICH_LR0_EL2);
+            break;
+        case 1:
+            return READ_SYSREG(ICH_LR1_EL2);
+            break;
+        case 2:
+            return READ_SYSREG(ICH_LR2_EL2);
+            break;
+        case 3:
+            return READ_SYSREG(ICH_LR3_EL2);
+            break;
+        case 4:
+            return READ_SYSREG(ICH_LR4_EL2);
+            break;
+        case 5:
+            return READ_SYSREG(ICH_LR5_EL2);
+            break;
+        case 6:
+            return READ_SYSREG(ICH_LR6_EL2);
+            break;
+        case 7:
+            return READ_SYSREG(ICH_LR7_EL2);
+            break;
+        case 8:
+            return READ_SYSREG(ICH_LR8_EL2);
+            break;
+        case 9:
+            return READ_SYSREG(ICH_LR9_EL2);
+            break;
+        case 10:
+            return READ_SYSREG(ICH_LR10_EL2);
+            break;
+        case 11:
+            return READ_SYSREG(ICH_LR11_EL2);
+            break;
+        case 12:
+            return READ_SYSREG(ICH_LR12_EL2);
+            break;
+        case 13:
+            return READ_SYSREG(ICH_LR13_EL2);
+            break;
+        case 14:
+            return READ_SYSREG(ICH_LR14_EL2);
+            break;
+        case 15:
+            return READ_SYSREG(ICH_LR15_EL2);
+            break;
+        default:
+            return 0;
+    }
+}
+
+static void gich_write_lr(int lr, u64 val)
+{
+    switch (lr) 
+    {
+        case 0:
+           WRITE_SYSREG(val, ICH_LR0_EL2);
+           break;
+        case 1:
+           WRITE_SYSREG(val, ICH_LR1_EL2);
+           break;
+        case 2:
+           WRITE_SYSREG(val, ICH_LR2_EL2);
+           break;
+        case 3:
+           WRITE_SYSREG(val, ICH_LR3_EL2);
+           break;
+        case 4:
+           WRITE_SYSREG(val, ICH_LR4_EL2);
+           break;
+        case 5:
+           WRITE_SYSREG(val, ICH_LR5_EL2);
+           break;
+        case 6:
+           WRITE_SYSREG(val, ICH_LR6_EL2);
+           break;
+        case 7:
+           WRITE_SYSREG(val, ICH_LR7_EL2);
+           break;
+        case 8:
+           WRITE_SYSREG(val, ICH_LR8_EL2);
+           break;
+        case 9:
+           WRITE_SYSREG(val, ICH_LR9_EL2);
+           break;
+        case 10:
+           WRITE_SYSREG(val, ICH_LR10_EL2);
+           break;
+        case 11:
+           WRITE_SYSREG(val, ICH_LR11_EL2);
+           break;
+        case 12:
+           WRITE_SYSREG(val, ICH_LR12_EL2);
+           break;
+        case 13:
+           WRITE_SYSREG(val, ICH_LR13_EL2);
+           break;
+        case 14:
+           WRITE_SYSREG(val, ICH_LR14_EL2);
+           break;
+        case 15:
+           WRITE_SYSREG(val, ICH_LR15_EL2);
+           break;
+        default:
+           return;
+    }
+}
+
+static void gic_enable_sre(void)
+{
+    uint32_t val;
+
+    val = READ_SYSREG32(ICC_SRE_EL2);
+    val |= GICC_SRE_EL2_SRE | GICC_SRE_EL2_ENEL1 | GICC_SRE_EL2_DFB | 
GICC_SRE_EL2_DIB;
+    WRITE_SYSREG32(val, ICC_SRE_EL2);
+    isb();
+}
+
+/* Wait for completion of a distributor change */
+static void gic_do_wait_for_rwp(paddr_t base)
+{
+    u32 val;
+    do {
+        val = readl_relaxed((void *)base + GICD_CTLR);
+        val = readl_relaxed(GICD + GICD_CTLR);
+        val = GICD[GICD_CTLR];
+        cpu_relax();
+    } while (val & GICD_CTLR_RWP);
+}
+
+static void gic_dist_wait_for_rwp(void)
+{
+    gic_do_wait_for_rwp((paddr_t)GICD);
+}
+
+static void gic_redist_wait_for_rwp(void)
+{
+    gic_do_wait_for_rwp(gic_data_rdist_rd_base());
+}
+
+static void gic_wait_for_rwp(int irq)
+{
+    if (irq < 32)
+         gic_redist_wait_for_rwp();
+    else
+         gic_dist_wait_for_rwp();
+}
+
+static unsigned int gic_mask_cpu(const cpumask_t *cpumask)
+{
+    unsigned int cpu;
+    cpumask_t possible_mask;
+
+    cpumask_and(&possible_mask, cpumask, &cpu_possible_map);
+    cpu = cpumask_any(&possible_mask);
+    return cpu;
+}
+
+static unsigned int gic_nr_lines(void)
+{
+    return gic.lines;
+}
+
+static unsigned int gic_nr_lrs(void)
+{
+    return nr_lrs;
+}
+
+static void write_aprn_regs(struct gic_state_data *d)
+{
+    switch(nr_priorities)
+    {
+        case 7:
+            WRITE_SYSREG32(d->gic_apr0[2], ICH_AP0R2_EL2);
+            WRITE_SYSREG32(d->gic_apr1[2], ICH_AP1R2_EL2);
+        case 6:
+            WRITE_SYSREG32(d->gic_apr0[1], ICH_AP0R1_EL2);
+            WRITE_SYSREG32(d->gic_apr1[1], ICH_AP1R1_EL2);
+        case 5:
+            WRITE_SYSREG32(d->gic_apr0[0], ICH_AP0R0_EL2);
+            WRITE_SYSREG32(d->gic_apr1[0], ICH_AP1R0_EL2);
+            break;
+        default:
+          panic("Write Undefined active priorities \n");
+    }
+}
+
+static void read_aprn_regs(struct gic_state_data *d)
+{
+    switch(nr_priorities)
+    {
+        case 7:
+            d->gic_apr0[2] = READ_SYSREG32(ICH_AP0R2_EL2);
+            d->gic_apr1[2] = READ_SYSREG32(ICH_AP1R2_EL2);
+        case 6:
+            d->gic_apr0[1] = READ_SYSREG32(ICH_AP0R1_EL2);
+            d->gic_apr1[1] = READ_SYSREG32(ICH_AP1R1_EL2);
+        case 5:
+            d->gic_apr0[0] = READ_SYSREG32(ICH_AP0R0_EL2);
+            d->gic_apr1[0] = READ_SYSREG32(ICH_AP1R0_EL2);
+            break;
+        default:
+          panic("Read Undefined active priorities \n");
+    }
+}
+
+static int gic_state_init(struct vcpu *v)
+{
+     v->arch.gic_state = (struct gic_state_data *)xzalloc(struct 
gic_state_data);
+     if(!v->arch.gic_state)
+        return -ENOMEM;
+     return 0; 
+}
+
+static void save_state(struct vcpu *v)
+{
+    int i;
+    struct gic_state_data *d;
+    d = (struct gic_state_data *)v->arch.gic_state;
+
+    /* 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++)
+        d->gic_lr[i] = gich_read_lr(i);
+
+    read_aprn_regs(d); 
+
+    d->gic_vmcr = READ_SYSREG32(ICH_VMCR_EL2);
+}
+
+static void restore_state(struct vcpu *v)
+{
+    int i;
+    struct gic_state_data *d;
+    d = (struct gic_state_data *)v->arch.gic_state;
+
+    for ( i=0; i<nr_lrs; i++)
+        gich_write_lr(i, d->gic_lr[i]);
+
+    write_aprn_regs(d);
+
+    WRITE_SYSREG32(d->gic_vmcr, ICH_VMCR_EL2);
+}
+
+static void gic_dump_state(struct vcpu *v)
+{
+    int i;
+    struct gic_state_data *d;
+    d = (struct gic_state_data *)v->arch.gic_state;
+    if ( v == current )
+    {
+        for ( i = 0; i < nr_lrs; i++ )
+            printk("   HW_LR[%d]=%lx\n", i, gich_read_lr(i));
+    }
+    else
+    {
+        for ( i = 0; i < nr_lrs; i++ )
+            printk("   VCPU_LR[%d]=%lx\n", i, d->gic_lr[i]);
+    }
+}
+ 
+static void gic_enable_irq(int irq)
+{
+    uint32_t enabler;
+
+    /* Enable routing */
+    if(irq > 31)
+    {
+        enabler = readl_relaxed(GICD + GICD_ISENABLER + (irq / 32) * 4);
+        writel_relaxed(enabler | (1u << (irq % 32)), GICD + GICD_ISENABLER + 
(irq / 32) * 4);
+    }
+    else
+    {
+        enabler = readl_relaxed((void *)gic_data_rdist_sgi_base() + 
GICR_ISENABLER0);
+        writel_relaxed(enabler | (1u << irq), (void 
*)gic_data_rdist_sgi_base() + GICR_ISENABLER0);
+    }
+    gic_wait_for_rwp(irq);
+}
+
+static void gic_disable_irq(int irq)
+{
+    /* Disable routing */
+    if(irq > 31)
+        writel_relaxed(1u << (irq % 32), GICD + GICD_ICENABLER + ((irq / 32) * 
4));
+    else
+        writel_relaxed(1u << irq, (void *)gic_data_rdist_sgi_base() + 
GICR_ICENABLER0);
+}
+
+static void gic_eoi_irq(int irq)
+{
+    /* Lower the priority */
+    WRITE_SYSREG32(irq, ICC_EOIR1_EL1);
+}
+
+static void gic_dir_irq(int irq)
+{
+    /* Deactivate */
+    WRITE_SYSREG32(irq, ICC_DIR_EL1);
+}
+
+static unsigned int gic_ack_irq(void)
+{
+    return (READ_SYSREG32(ICC_IAR1_EL1) & GICC_IA_IRQ);
+}
+
+static u64 gic_mpidr_to_affinity(u64 mpidr)
+{
+    /* Make sure we don't broadcast the interrupt */
+    return mpidr & ~GICD_IROUTER_SPI_MODE_ANY;
+}
+
+/*
+ * - needs to be called with gic.lock held
+ * - needs to be called with a valid cpu_mask, ie each cpu in the mask has
+ * already called gic_cpu_init
+ */
+static void gic_set_irq_property(unsigned int irq, bool_t level,
+                                   const cpumask_t *cpu_mask,
+                                   unsigned int priority)
+{
+    uint32_t cfg, edgebit;
+    u64 affinity;
+    unsigned int cpu = gic_mask_cpu(cpu_mask);
+    paddr_t rebase;
+
+
+    /* Set edge / level */
+    if (irq < 16)
+       /* SGI's are always edge-triggered not need to call GICD_ICFGR0 */
+       cfg = readl_relaxed((void *)gic_data_rdist_sgi_base() + GICR_ICFGR0);
+    else if (irq < 32)
+       cfg = readl_relaxed((void *)gic_data_rdist_sgi_base() + GICR_ICFGR1);
+    else
+       cfg = readl_relaxed(GICD + GICD_ICFGR + (irq / 16) * 4);
+
+    edgebit = 2u << (2 * (irq % 16));
+    if ( level )
+        cfg &= ~edgebit;
+    else
+        cfg |= edgebit;
+
+    if (irq < 16)
+       writel_relaxed(cfg, (void *)gic_data_rdist_sgi_base() + GICR_ICFGR0);
+    else if (irq < 32)
+       writel_relaxed(cfg, (void *)gic_data_rdist_sgi_base() + GICR_ICFGR1);
+    else
+       writel_relaxed(cfg, GICD + GICD_ICFGR + (irq / 16) * 4);
+
+
+    /* need to check if ARE is set to access IROUTER */
+    affinity = gic_mpidr_to_affinity(cpu_logical_map(cpu));
+    if (irq > 31)
+        writeq_relaxed(affinity, (GICD + GICD_IROUTER + irq * 8));
+
+    /* Set priority */
+    if (irq < 32)
+    {
+       rebase = gic_data_rdist_sgi_base();
+        writeb_relaxed(priority, (void *)rebase + GICR_IPRIORITYR0 + irq);
+    }
+    else 
+    {
+        writeb_relaxed(priority, GICD + GICD_IPRIORITYR + irq);
+
+    }
+}
+
+static void __init gic_dist_init(void)
+{
+    uint32_t type;
+    u64 affinity;
+    int i;
+
+    /* Disable the distributor */
+    writel_relaxed(0, GICD + GICD_CTLR);
+
+    type = readl_relaxed(GICD + GICD_TYPER);
+    gic.lines = 32 * ((type & GICD_TYPE_LINES) + 1);
+
+    printk("GIC: %d lines, (IID %8.8x).\n",
+           gic.lines, readl_relaxed(GICD + GICD_IIDR));
+
+    /* Default all global IRQs to level, active low */
+    for ( i = 32; i < gic.lines; i += 16 )
+        writel_relaxed(0, GICD + GICD_ICFGR + (i / 16) * 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(0xffffffff, GICD + GICD_ICENABLER + (i / 32) * 4);
+
+    gic_dist_wait_for_rwp();
+
+    /* Turn on the distributor */
+    writel_relaxed(GICD_CTL_ENABLE | GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | 
GICD_CTLR_ENABLE_G1, GICD + GICD_CTLR);
+ 
+    /* Route all global IRQs to this CPU */
+    affinity = gic_mpidr_to_affinity(read_cpuid_mpidr());
+    for ( i = 31; i < gic.lines; i++ )
+        writeq_relaxed(affinity, GICD + GICD_IROUTER + i * 8);
+}
+
+static void gic_enable_redist(void)
+{
+    paddr_t rbase;
+    u32 val;
+
+    rbase = this_cpu(rbase);
+
+    /* Wake up this CPU redistributor */
+    val = readl_relaxed((void *)rbase + GICR_WAKER);
+    val &= ~GICR_WAKER_ProcessorSleep;
+    writel_relaxed(val, (void *)rbase + GICR_WAKER);
+
+    do {
+         val = readl_relaxed((void *)rbase + GICR_WAKER);
+         cpu_relax();
+    } while (val & GICR_WAKER_ChildrenAsleep);
+}
+
+static int __init gic_populate_rdist(void)
+{
+    u64 mpidr = cpu_logical_map(smp_processor_id());
+    u64 typer;
+    u64 aff;
+    int i;
+    uint32_t reg;
+
+    aff  = mpidr & ((1 << 24) - 1);
+    aff |= (mpidr >> 8) & (0xffUL << 24);
+
+    for (i = 0; i < gic.rdist_count; i++) {
+        uint32_t ptr = 0;
+
+        reg = readl_relaxed(GICR + ptr + GICR_PIDR0);
+        if ((reg & 0xff) != GICR_PIDR0_GICv3) { /* We're in trouble... */
+            printk("No redistributor present @%x\n", ptr);
+            break;
+        }
+
+        do {
+            typer = readq_relaxed(GICR + ptr + GICR_TYPER);
+            if ((typer >> 32) == aff) {
+                              
+                this_cpu(rbase) = (u64)GICR + ptr;
+                this_cpu(phy_rbase) = gic.rdist_regions[i].rdist_base + ptr;
+
+                printk("CPU%d: found redistributor %llx region %d\n",
+                            smp_processor_id(), (unsigned long long) mpidr, i);
+                return 0;
+            }
+
+            if (gic.rdist_stride) {
+                ptr += gic.rdist_stride;
+            } else {
+                ptr += SZ_64K * 2; /* Skip RD_base + SGI_base */
+                if (typer & GICR_TYPER_VLPIS)
+                    ptr += SZ_64K * 2; /* Skip VLPI_base + reserved page */
+                }
+            } while (!(typer & GICR_TYPER_LAST));
+        }
+
+        /* We couldn't even deal with ourselves... */
+        printk("CPU%d: mpidr %lx has no re-distributor!\n",
+                  smp_processor_id(), (unsigned long)mpidr);
+        return -ENODEV;
+}
+
+static void __cpuinit gic_cpu_init(void)
+{
+    int i;
+    paddr_t rbase_sgi;
+
+    /* Register ourselves with the rest of the world */
+    if (gic_populate_rdist())
+        return;
+
+    gic_enable_redist();
+
+    rbase_sgi = gic_data_rdist_sgi_base();
+
+    /*
+     * Set priority on PPI and SGI interrupts
+     */
+    for (i = 0; i < 16; i += 4)
+        writel_relaxed((GIC_PRI_IPI<<24 | GIC_PRI_IPI<<16 | GIC_PRI_IPI<<8 | 
GIC_PRI_IPI), (void *)rbase_sgi + GICR_IPRIORITYR0 + (i / 4) * 4);
+        //writel_relaxed(0x0, (void *)rbase + GICR_IPRIORITYR0 + (i / 4) * 4);
+        //writel_relaxed(0xa0a0a0a0, (void *)rbase + GICR_IPRIORITYR0 + (i / 
4) * 4);
+
+    for (i = 16; i < 32; i += 4)
+        writel_relaxed((GIC_PRI_IRQ<<24 | GIC_PRI_IRQ<<16 | GIC_PRI_IRQ<<8 | 
GIC_PRI_IRQ), (void *)rbase_sgi + GICR_IPRIORITYR0 + (i / 4) * 4);
+
+    /*
+     * Disable all PPI interrupts, ensure all SGI interrupts are
+     * enabled.
+     */
+    writel_relaxed(0xffff0000, (void *)rbase_sgi + GICR_ICENABLER0);
+    writel_relaxed(0x0000ffff, (void *)rbase_sgi + GICR_ISENABLER0);
+
+    gic_redist_wait_for_rwp();
+
+    /* Enable system registers */
+    gic_enable_sre();
+
+    WRITE_SYSREG32(0, ICC_BPR1_EL1);
+    /* Set priority mask register */
+    WRITE_SYSREG32(DEFAULT_PMR_VALUE, ICC_PMR_EL1);
+
+    /* EOI drops priority too (mode 0) */
+    WRITE_SYSREG32(GICC_CTLR_EL1_EOImode_drop, ICC_CTLR_EL1);
+
+    WRITE_SYSREG32(1, ICC_IGRPEN1_EL1);
+}
+
+static void gic_cpu_disable(void)
+{
+    WRITE_SYSREG32(0, ICC_CTLR_EL1);
+}
+
+static void __cpuinit gic_hyp_init(void)
+{
+    uint32_t vtr;
+
+    vtr = READ_SYSREG32(ICH_VTR_EL2);
+    nr_lrs  = (vtr & GICH_VTR_NRLRGS) + 1;
+    nr_priorities = ((vtr >> GICH_VTR_PRIBITS_SHIFT) & GICH_VTR_PRIBITS_MASK) 
+ 1;
+
+    WRITE_SYSREG32(GICH_VMCR_EOI | GICH_VMCR_VENG1, ICH_VMCR_EL2);
+    WRITE_SYSREG32(GICH_HCR_VGRP1EIE | GICH_HCR_EN, ICH_HCR_EL2);
+
+    update_cpu_lr_mask();
+    vtr = READ_SYSREG32(ICH_HCR_EL2);
+}
+
+/* Set up the per-CPU parts of the GIC for a secondary CPU */
+static int __cpuinit gic_init_secondary_cpu(struct notifier_block *nfb,
+                                       unsigned long action, void *hcpu)
+{
+    if (action == CPU_STARTING)
+    {
+        spin_lock(&gic.lock);
+        gic_cpu_init();
+        gic_hyp_init();
+        spin_unlock(&gic.lock);
+    }
+    return NOTIFY_DONE;
+}
+
+static struct notifier_block gic_cpu_nb = {
+    .notifier_call = gic_init_secondary_cpu,
+    .priority = 100
+};
+
+static void gic_smp_init(void)
+{
+   register_cpu_notifier(&gic_cpu_nb);
+}
+
+static void __cpuinit gic_hyp_disable(void)
+{
+    uint32_t vtr;
+    vtr = READ_SYSREG32(ICH_HCR_EL2);
+    vtr &= ~0x1;
+    WRITE_SYSREG32( vtr, ICH_HCR_EL2);
+}
+
+static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
+                                   u64 cluster_id)
+{
+    int cpu = *base_cpu;
+    u64 mpidr = cpu_logical_map(cpu);
+    u16 tlist = 0;
+
+    while (cpu < nr_cpu_ids) {
+        /*
+         * If we ever get a cluster of more than 16 CPUs, just
+         * scream and skip that CPU.
+         */
+        tlist |= 1 << (mpidr & 0xf);
+
+        cpu = cpumask_next(cpu, mask);
+        mpidr = cpu_logical_map(cpu);
+
+        if (cluster_id != (mpidr & ~0xffUL)) {
+            cpu--;
+            goto out;
+        }
+    }
+out:
+    *base_cpu = cpu;
+    return tlist;
+}
+
+static void send_sgi(u64 cluster_id, u16 tlist, unsigned int irq)
+{
+    u64 val;
+
+    val  = (cluster_id & 0xff00ff0000UL) << 16; /* Aff3 + Aff2 */
+    val |= (cluster_id & 0xff00) << 8;          /* Aff1 */
+    val |= irq << 24;
+    val |= tlist;
+
+    WRITE_SYSREG(val, ICC_SGI1R_EL1);   
+}
+
+static void gic_send_sgi(const cpumask_t *cpumask, enum gic_sgi sgi)
+{
+    int cpu = 0;
+
+    dsb();
+
+    for_each_cpu(cpu, cpumask) {
+        u64 cluster_id = cpu_logical_map(cpu) & ~0xffUL;
+        u16 tlist;
+
+        tlist = gic_compute_target_list(&cpu, cpumask, cluster_id);
+        send_sgi(cluster_id, tlist, sgi);
+    }
+}
+
+/* Shut down the per-CPU GIC interface */
+static void gic_disable_interface(void)
+{
+    ASSERT(!local_irq_is_enabled());
+
+    spin_lock(&gic.lock);
+    gic_cpu_disable();
+    gic_hyp_disable();
+    spin_unlock(&gic.lock);
+}
+
+static void gic_update_lr(int lr, unsigned int virtual_irq,
+        unsigned int state, unsigned int priority)
+{
+    u64 maintenance_int = GICH_LR_MAINTENANCE_IRQ;
+    u64 grp = GICH_LR_GRP1;
+    u64 val = 0;
+
+    BUG_ON(lr >= nr_lrs);
+    BUG_ON(lr < 0);
+
+    val =  ((((u64)state) & 0x3) << GICH_LR_STATE_SHIFT) | grp | 
maintenance_int |
+        ((((u64)priority) & 0xff) << GICH_LR_PRIORITY_SHIFT) |
+        (((u64)virtual_irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT) |
+        (((u64)virtual_irq & GICH_LR_PHYSICAL_MASK) << GICH_LR_PHYSICAL_SHIFT);
+
+    gich_write_lr(lr, val);
+}
+
+int gicv_init(struct domain *d)
+{
+    /*
+     * Domain 0 gets the hardware address.
+     * Guests get the virtual platform layout.
+     */
+    if ( d->domain_id == 0 )
+    {
+        d->arch.vgic.dbase = gic.dbase;
+        d->arch.vgic.dbase_size = gic.dbase_size;
+        d->arch.vgic.rbase = gic.rdist_regions[0].rdist_base;
+        d->arch.vgic.rbase_size = gic.rdist_regions[0].rdist_base_size;
+        d->arch.vgic.rdist_stride = gic.rdist_stride;
+    }
+    else
+    {
+        d->arch.vgic.dbase = GUEST_GICD_BASE;
+    }
+
+    d->arch.vgic.nr_lines = 0;
+
+    return 0;
+
+}
+
+static unsigned long gic_read_eisr(void)
+{
+    return (unsigned long)READ_SYSREG32(ICH_EISR_EL2);
+}
+
+static unsigned int gic_update_lr_for_mi(int lr)
+{
+    u64 val;
+    uint32_t virq;
+
+    spin_lock_irq(&gic.lock);
+    val = gich_read_lr(lr);
+    virq = val & GICH_LR_VIRTUAL_MASK;
+
+    gich_write_lr(lr, 0);
+
+    spin_unlock_irq(&gic.lock);
+    return virq;
+}
+
+static unsigned long gic_rdist_rd_base(void)
+{
+   return this_cpu(phy_rbase);
+}
+
+static unsigned long gic_rdist_sgi_base(void)
+{
+   return this_cpu(phy_rbase) + SZ_64K;
+}
+
+static int gic_hw_type(void)
+{
+    return gic.hw_version;
+}
+
+static struct dt_irq * gic_maintenance_irq(void)
+{
+    return &gic.maintenance;
+}
+
+static struct gic_hw_operations gic_ops = {
+    .gic_type            = gic_hw_type,
+    .nr_lines            = gic_nr_lines,
+    .nr_lrs              = gic_nr_lrs,
+    .get_maintenance_irq = gic_maintenance_irq,
+    .state_init          = gic_state_init,
+    .save_state          = save_state,
+    .restore_state       = restore_state,
+    .dump_state          = gic_dump_state,
+    .gicv_setup          = gicv_init,
+    .enable_irq          = gic_enable_irq,
+    .disable_irq         = gic_disable_irq,
+    .eoi_irq             = gic_eoi_irq,
+    .deactivate_irq      = gic_dir_irq,
+    .ack_irq             = gic_ack_irq,
+    .set_irq_property    = gic_set_irq_property,
+    .send_sgi            = gic_send_sgi,
+    .disable_interface   = gic_disable_interface,
+    .update_lr           = gic_update_lr,
+    .update_lr_for_mi    = gic_update_lr_for_mi,
+    .read_eisr           = gic_read_eisr,
+    .read_cpu_rbase      = gic_rdist_rd_base,
+    .read_cpu_sgi_rbase  = gic_rdist_sgi_base,
+};
+
+/* Set up the GIC */
+void __init gicv3_init(void)
+{
+    static const struct dt_device_match gic_ids[] __initconst =
+    {
+        DT_MATCH_GIC_V3,
+        { /* sentinel */ },
+    };
+    struct dt_device_node *node;
+    struct rdist_region *rdist_regs;
+    int res, i;
+    uint32_t reg;
+
+    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, &gic.dbase_size);
+    if ( res || !gic.dbase  || (gic.dbase & ~PAGE_MASK) || (gic.dbase_size & 
~PAGE_MASK) )
+        panic("GIC: Cannot find a valid address for the distributor");
+
+    gic.map_dbase = ioremap_nocache(gic.dbase, gic.dbase_size);
+
+    reg = readl_relaxed(GICD + GICD_PIDR0);
+    if ((reg & 0xff) != GICD_PIDR0_GICv3)
+        panic("GIC: no distributor detected, giving up\n"); 
+
+    gic.hw_version = GIC_VERSION_V3;
+ 
+    if (!dt_property_read_u32(node, "#redistributor-regions", 
&gic.rdist_count))
+        gic.rdist_count = 1;
+
+    rdist_regs = xzalloc_array(struct rdist_region, gic.rdist_count);
+    if (!rdist_regs)
+        panic("GIC: no distributor detected, giving up\n");
+
+    for (i = 0; i < gic.rdist_count; i++) {
+       u64 rdist_base, rdist_size;
+
+        res = dt_device_get_address(node, 1 + i, &rdist_base, &rdist_size);
+        if ( res || !rdist_base)
+               printk("No rdist base found\n");
+               
+        rdist_regs[i].rdist_base = rdist_base;
+        rdist_regs[i].rdist_base_size = rdist_size;
+    }
+
+    if(!dt_property_read_u32(node, "redistributor-stride", &gic.rdist_stride))
+        gic.rdist_stride = 0x0;
+
+    gic.rdist_regions= rdist_regs;
+ 
+    res = dt_device_get_irq(node, 0, &gic.maintenance);
+    if ( res )
+        panic("GIC: Cannot find the maintenance IRQ");
+
+    /* Set the GIC as the primary interrupt controller */
+    dt_interrupt_controller = node;
+
+    /* map dbase & rdist regions */
+    gic.rdist_regions[0].map_rdist_base = ioremap_nocache(gic.rdist_regions[0].
+                             rdist_base, gic.rdist_regions[0].rdist_base_size);
+
+    printk("GIC initialization:\n"
+              "        gic_dist_addr=%"PRIpaddr"\n"
+              "        gic_dist_size=%"PRIpaddr"\n"
+              "        gic_dist_mapaddr=%"PRIpaddr"\n"
+              "        gic_rdist_regions=%d\n"
+              "        gic_rdist_stride=%x\n"
+              "        gic_rdist_base=%"PRIpaddr"\n"
+              "        gic_rdist_base_size=%"PRIpaddr"\n"
+              "        gic_rdist_base_mapaddr=%"PRIpaddr"\n"
+              "        gic_maintenance_irq=%u\n",
+              gic.dbase, gic.dbase_size, (u64)gic.map_dbase, gic.rdist_count,
+              gic.rdist_stride, gic.rdist_regions[0].rdist_base,
+              gic.rdist_regions[0].rdist_base_size,
+              (u64)gic.rdist_regions[0].map_rdist_base, gic.maintenance.irq);
+
+    /* Global settings: interrupt distributor */
+    spin_lock_init(&gic.lock);
+    spin_lock(&gic.lock);
+
+    gic_smp_init();
+    gic_dist_init();
+    gic_cpu_init();
+    gic_hyp_init();
+
+    /* Register hw ops*/
+    register_gic_ops(&gic_ops);
+    spin_unlock(&gic.lock);
+}
+
+/*
+ * 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 e0859ae..291e34c 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -688,6 +688,11 @@ static void maintenance_interrupt(int irq, void *dev_id, 
struct cpu_user_regs *r
 /* Set up the GIC */
 void __init gic_init(void)
 {
+    static const struct dt_device_match gicv3_ids[] __initconst =
+    {
+        DT_MATCH_GIC_V3,
+        { /* sentinel */ },
+    };
     static const struct dt_device_match gicv2_ids[] __initconst =
     {
         DT_MATCH_GIC,
@@ -698,6 +703,13 @@ void __init gic_init(void)
     spin_lock_init(&gic_lock);
 
     spin_lock(&gic_lock);
+    node = dt_find_interrupt_controller(gicv3_ids);
+    if ( node )
+    {
+        gicv3_init();
+        spin_unlock(&gic_lock);
+        return;
+    }
     node = dt_find_interrupt_controller(gicv2_ids);
     if ( node )
     {
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 38df789..15e83e8 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -142,6 +142,10 @@ struct arch_domain
         /* Base address for guest GIC */
         paddr_t dbase; /* Distributor base address */
         paddr_t cbase; /* CPU base address */
+        paddr_t dbase_size; /* Distributor base size */
+        paddr_t rbase;      /* Re-Distributor base address */
+        paddr_t rbase_size; /* Re-Distributor size */
+        uint32_t rdist_stride;
     } vgic;
 
     struct vuart {
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 2de6c6a..b6fbd5e 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -18,6 +18,8 @@
 #ifndef __ASM_ARM_GIC_H__
 #define __ASM_ARM_GIC_H__
 
+#define SZ_64K  0x00010000
+
 /*
  * 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
@@ -48,6 +50,8 @@
 #define DT_MATCH_GIC    DT_MATCH_COMPATIBLE("arm,cortex-a15-gic"), \
                         DT_MATCH_COMPATIBLE("arm,cortex-a7-gic")
 
+#define DT_MATCH_GIC_V3 DT_MATCH_COMPATIBLE("arm,gic-v3")
+
 extern int gic_hw_version(void);
 extern int domain_vgic_init(struct domain *d);
 extern void domain_vgic_free(struct domain *d);
@@ -58,6 +62,7 @@ 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 int vgic_v2_init(struct domain *d);
 
+extern void gicv3_init(void);
 extern void gicv2_init(void);
 
 extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq,int virtual);
@@ -96,6 +101,7 @@ extern int gicv_setup(struct domain *d);
 extern void gic_save_state(struct vcpu *v);
 extern void gic_restore_state(struct vcpu *v);
 
+#define GIC_VERSION_V3 0x3
 #define GIC_VERSION_V2 0x2
 
 /* SGI (AKA IPIs) */
@@ -156,6 +162,9 @@ extern unsigned int gic_number_lines(void);
 int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
                   unsigned int *out_hwirq, unsigned int *out_type);
 
+extern unsigned long gic_data_rdist_rd_base(void);
+extern unsigned long gic_data_rdist_sgi_base(void);
+
 #endif /* __ASSEMBLY__ */
 #endif
 
diff --git a/xen/include/asm-arm/gic_v3_defs.h 
b/xen/include/asm-arm/gic_v3_defs.h
new file mode 100644
index 0000000..24242ea
--- /dev/null
+++ b/xen/include/asm-arm/gic_v3_defs.h
@@ -0,0 +1,211 @@
+/*
+ * ARM Generic Interrupt Controller support
+ *
+ * Vijaya Kumar K <vijaya.kumar@xxxxxxxxxxxxxxxxxx>
+ * Copyright (c) 2014 Cavium Inc.
+ *
+ * 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.
+ */
+
+#define SZ_64K  0x00010000
+
+#define GICD_CTLR       (0x000)
+#define GICD_TYPER      (0x004)
+#define GICD_IIDR       (0x008)
+#define GICD_STATUSR    (0x010)
+#define GICD_SETSPI_NSR (0x040)
+#define GICD_CLRSPI_NSR (0x048)
+#define GICD_SETSPI_SR  (0x050)
+#define GICD_CLRSPI_SR  (0x058)
+#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_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_IROUTER    (0x6000)
+#define GICD_IROUTERN   (0x7FF8)
+#define GICD_PIDR0      (0xFFE0)
+#define GICD_PIDR7      (0xFFDC)
+
+#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_OTHERS       (1UL<<GICD_SGI_TARGET_LIST_SHIFT)
+#define GICD_SGI_TARGET_SELF         (2UL<<GICD_SGI_TARGET_LIST_SHIFT)
+#define GICD_SGI_TARGET_SHIFT        (16)
+#define GICD_SGI_TARGET_MASK         (0xFFUL<<GICD_SGI_TARGET_SHIFT)
+#define GICD_SGI_GROUP1              (1UL<<15)
+#define GICD_SGI_INTID_MASK          (0xFUL)
+
+#define GICC_SRE_EL2_SRE             (1UL << 0)
+#define GICC_SRE_EL2_DFB             (1UL << 1)
+#define GICC_SRE_EL2_DIB             (1UL << 2)
+#define GICC_SRE_EL2_ENEL1           (1UL << 3)
+
+#define GICD_PIDR0_GICv3                0x92
+
+#define GICD_CTLR_RWP                (1UL << 31)
+#define GICD_CTLR_ARE_NS                (1U << 4)
+#define GICD_CTLR_ENABLE_G1A            (1U << 1)
+#define GICD_CTLR_ENABLE_G1             (1U << 0)
+#define GICD_IROUTER_SPI_MODE_ONE    (0UL << 31)
+#define GICD_IROUTER_SPI_MODE_ANY    (1UL << 31)
+
+#define GICH_HCR_EN                  (1 << 0)
+
+#define GICC_CTLR_EL1_EOImode_drop_dir  (0U << 1)
+#define GICC_CTLR_EL1_EOImode_drop      (1U << 1)
+
+#define GICR_WAKER_ProcessorSleep       (1U << 1)
+#define GICR_WAKER_ChildrenAsleep       (1U << 2)
+#define GICR_PIDR0_GICv3                0x93
+
+#define GICR_CTLR       (0x0000)
+#define GICR_IIDR       (0x0004)
+#define GICR_TYPER      (0x0008)
+#define GICR_STATUSR    (0x0010)
+#define GICR_WAKER      (0x0014)
+#define GICR_SETLPIR    (0x0040)
+#define GICR_CLRLPIR    (0x0048)
+#define GICR_PROPBASER  (0x0070)
+#define GICR_PENDBASER  (0x0078)
+#define GICR_INVLPIR    (0x00A0)
+#define GICR_INVALLR    (0x00B0)
+#define GICR_SYNCR      (0x00C0)
+#define GICR_MOVLPIR    (0x100)
+#define GICR_MOVALLR    (0x0110)
+#define GICR_PIDR0      GICD_PIDR0
+#define GICR_PIDR7      GICD_PIDR7
+
+/* GICR for SGI's & PPI's */
+
+#define GICR_IGROUPR0    (0x0080)
+#define GICR_IGRPMODR0   (0x0F80)
+#define GICR_ISENABLER0  (0x0100)
+#define GICR_ICENABLER0  (0x0180)
+#define GICR_ISPENDR0    (0x0200)
+#define GICR_ICPENDR0    (0x0280)
+#define GICR_ISACTIVER0  (0x0300)
+#define GICR_ICACTIVER0  (0x0380)
+#define GICR_IPRIORITYR0 (0x0400)
+#define GICR_IPRIORITYR7 (0x041C)
+#define GICR_ICFGR0      (0x0C00)
+#define GICR_ICFGR1      (0x0C04)
+#define GICR_NSACR       (0x0E00)
+
+#define GICR_TYPER_PLPIS                (1U << 0)
+#define GICR_TYPER_VLPIS                (1U << 1)
+#define GICR_TYPER_LAST                 (1U << 4)
+
+/* Register bits */
+#define GICD_CTL_ENABLE 0x1
+
+#define GICD_TYPE_LINES 0x01f
+#define GICD_TYPE_CPUS  0x0e0
+#define GICD_TYPE_SEC   0x400
+
+#define GICC_CTL_ENABLE 0x1
+#define GICC_CTL_EOI    (0x1 << 9)
+
+#define GICC_IA_IRQ       0x03ff
+#define GICC_IA_CPU_MASK  0x1c00
+#define GICC_IA_CPU_SHIFT 10
+
+#define DEFAULT_PMR_VALUE       0xff
+
+#define GICH_HCR_EN       (1 << 0)
+#define GICH_HCR_UIE      (1 << 1)
+#define GICH_HCR_LRENPIE  (1 << 2)
+#define GICH_HCR_NPIE     (1 << 3)
+#define GICH_HCR_VGRP0EIE (1 << 4)
+#define GICH_HCR_VGRP0DIE (1 << 5)
+#define GICH_HCR_VGRP1EIE (1 << 6)
+#define GICH_HCR_VGRP1DIE (1 << 7)
+#define GICH_HCR_TC       (1 << 10)
+
+#define GICH_MISR_EOI     (1 << 0)
+#define GICH_MISR_U       (1 << 1)
+#define GICH_MISR_LRENP   (1 << 2)
+#define GICH_MISR_NP      (1 << 3)
+#define GICH_MISR_VGRP0E  (1 << 4)
+#define GICH_MISR_VGRP0D  (1 << 5)
+#define GICH_MISR_VGRP1E  (1 << 6)
+#define GICH_MISR_VGRP1D  (1 << 7)
+
+#define GICH_VMCR_EOI     (1 << 9)
+#define GICH_VMCR_VENG1    (1 << 1)
+
+#define GICH_LR_VIRTUAL_MASK    0xffff
+#define GICH_LR_VIRTUAL_SHIFT   0
+#define GICH_LR_PHYSICAL_MASK   0x3ff
+#define GICH_LR_PHYSICAL_SHIFT  32
+#define GICH_LR_STATE_MASK      0x3
+#define GICH_LR_STATE_SHIFT     62
+#define GICH_LR_PRIORITY_SHIFT  48
+#define GICH_LR_MAINTENANCE_IRQ (1UL<<41)
+#define GICH_LR_PENDING         1
+#define GICH_LR_ACTIVE          2
+#define GICH_LR_GRP1            (1UL<<60)
+#define GICH_LR_HW              (1UL<<61)
+
+#define GICH_VTR_NRLRGS         0x3f
+#define GICH_VTR_PRIBITS_MASK   0x7
+#define GICH_VTR_PRIBITS_SHIFT  29
+
+/*
+ * 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
+ * can rely on premption between the following ranges:
+ * 0xf0..0xff
+ * 0xe0..0xdf
+ * 0xc0..0xcf
+ * 0xb0..0xbf
+ * 0xa0..0xaf
+ * 0x90..0x9f
+ * 0x80..0x8f
+ *
+ * Priorities within a range will not preempt each other.
+ *
+ * A GIC must support a mimimum of 16 priority levels.
+ */
+#define GIC_PRI_LOWEST 0xf0
+#define GIC_PRI_IRQ 0xa0
+#define GIC_PRI_IPI 0x90 /* IPIs must preempt normal interrupts */
+#define GIC_PRI_HIGHEST 0x80 /* Higher priorities belong to Secure-World */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.9.5


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


 


Rackspace

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