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

[Xen-devel] [PATCH v5 14/25] arm: driver for CoreLink GIC-400 Generic Interrupt Controller



From: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

- GICC, GICD and GICH initialization;

- interrupts routing, acking and EOI;

- interrupt injection into guests;

- maintenance interrupt handler, that takes care of EOI physical
  interrupts on behalf of the guest;

- a function to remap the virtual cpu interface into the guest address
  space, where the guest expect the GICC to be.

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
---
 xen/arch/arm/domain.c |    2 +
 xen/arch/arm/gic.c    |  473 +++++++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/gic.h    |  151 ++++++++++++++++
 3 files changed, 626 insertions(+), 0 deletions(-)
 create mode 100644 xen/arch/arm/gic.c
 create mode 100644 xen/arch/arm/gic.h

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 4bb54ca..26f2d49 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -11,6 +11,8 @@
 #include <asm/p2m.h>
 #include <asm/irq.h>
 
+#include "gic.h"
+
 DEFINE_PER_CPU(struct vcpu *, curr_vcpu);
 
 static void continue_idle_domain(struct vcpu *v)
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
new file mode 100644
index 0000000..adc10bb
--- /dev/null
+++ b/xen/arch/arm/gic.c
@@ -0,0 +1,473 @@
+/*
+ * xen/arch/arm/gic.c
+ *
+ * ARM Generic Interrupt Controller support
+ *
+ * Tim Deegan <tim@xxxxxxx>
+ * 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 <asm/p2m.h>
+#include <asm/domain.h>
+
+#include "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)  \
+                                     + (GIC_CR_OFFSET & 0xfff)))
+#define GICH ((volatile uint32_t *) (FIXMAP_ADDR(FIXMAP_GICH)  \
+                                     + (GIC_HR_OFFSET & 0xfff)))
+
+/* Global state */
+static struct {
+    paddr_t dbase;       /* Address of distributor registers */
+    paddr_t cbase;       /* Address of CPU interface registers */
+    paddr_t hbase;       /* Address of virtual interface registers */
+    unsigned int lines;
+    unsigned int cpus;
+    spinlock_t lock;
+} gic;
+
+irq_desc_t irq_desc[NR_IRQS];
+unsigned nr_lrs;
+
+static unsigned int gic_irq_startup(struct irq_desc *desc)
+{
+    uint32_t enabler;
+    int irq = desc->irq;
+
+    /* Enable routing */
+    enabler = GICD[GICD_ISENABLER + irq / 32];
+    GICD[GICD_ISENABLER + irq / 32] = enabler | (1u << (irq % 32));
+
+    return 0;
+}
+
+static void gic_irq_shutdown(struct irq_desc *desc)
+{
+    uint32_t enabler;
+    int irq = desc->irq;
+
+    /* Disable routing */
+    enabler = GICD[GICD_ICENABLER + irq / 32];
+    GICD[GICD_ICENABLER + irq / 32] = enabler | (1u << (irq % 32));
+}
+
+static void gic_irq_enable(struct irq_desc *desc)
+{
+
+}
+
+static void gic_irq_disable(struct irq_desc *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 */
+    GICC[GICC_EOIR] = irq;
+    /* Deactivate */
+    GICC[GICC_DIR] = irq;
+}
+
+static void gic_guest_irq_end(struct irq_desc *desc)
+{
+    int irq = desc->irq;
+    /* Lower the priority of the IRQ */
+    GICC[GICC_EOIR] = irq;
+    /* 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,
+};
+
+/* Program the GIC to route an interrupt */
+static int gic_route_irq(unsigned int irq, bool_t level,
+                         unsigned int cpu_mask, unsigned int priority)
+{
+    volatile unsigned char *bytereg;
+    uint32_t cfg, edgebit;
+    struct irq_desc *desc = irq_to_desc(irq);
+    unsigned long flags;
+
+    ASSERT(!(cpu_mask & ~0xff));  /* Targets bitmap only supports 8 CPUs */
+    ASSERT(priority <= 0xff);     /* Only 8 bits of priority */
+    ASSERT(irq < gic.lines + 32); /* Can't route interrupts that don't exist */
+
+    spin_lock_irqsave(&desc->lock, flags);
+    spin_lock(&gic.lock);
+
+    if ( desc->action != NULL )
+    {
+        spin_unlock(&desc->lock);
+        return -EBUSY;
+    }
+
+    desc->handler = &gic_host_irq_type;
+
+    /* Disable interrupt */
+    desc->handler->shutdown(desc);
+
+    /* Set edge / level */
+    cfg = GICD[GICD_ICFGR + irq / 16];
+    edgebit = 2u << (2 * (irq % 16));
+    if ( level )
+        cfg &= ~edgebit;
+    else
+        cfg |= edgebit;
+    GICD[GICD_ICFGR + irq / 16] = cfg;
+
+    /* Set target CPU mask (RAZ/WI on uniprocessor) */
+    bytereg = (unsigned char *) (GICD + GICD_ITARGETSR);
+    bytereg[irq] = cpu_mask;
+
+    /* Set priority */
+    bytereg = (unsigned char *) (GICD + GICD_IPRIORITYR);
+    bytereg[irq] = priority;
+
+    spin_unlock(&gic.lock);
+    spin_unlock_irqrestore(&desc->lock, flags);
+    return 0;
+}
+
+static void __init gic_dist_init(void)
+{
+    uint32_t type;
+    uint32_t cpumask = 1 << smp_processor_id();
+    int i;
+
+    cpumask |= cpumask << 8;
+    cpumask |= cpumask << 16;
+
+    /* Disable the distributor */
+    GICD[GICD_CTLR] = 0;
+
+    type = GICD[GICD_TYPER];
+    gic.lines = 32 * (type & GICD_TYPE_LINES);
+    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]);
+
+    /* Default all global IRQs to level, active low */
+    for ( i = 32; i < gic.lines; i += 16 )
+        GICD[GICD_ICFGR + i / 16] = 0x0;
+
+    /* Route all global IRQs to this CPU */
+    for ( i = 32; i < gic.lines; i += 4 )
+        GICD[GICD_ICFGR + i / 4] = cpumask;
+
+    /* Default priority for global interrupts */
+    for ( i = 32; i < gic.lines; i += 4 )
+        GICD[GICD_IPRIORITYR + i / 4] = 0xa0a0a0a0;
+
+    /* Disable all global interrupts */
+    for ( i = 32; i < gic.lines; i += 32 )
+        GICD[GICD_ICENABLER + i / 32] = ~0ul;
+
+    /* Turn on the distributor */
+    GICD[GICD_CTLR] = GICD_CTL_ENABLE;
+}
+
+static void __cpuinit gic_cpu_init(void)
+{
+    int i;
+
+    /* Disable all PPI and enable all SGI */
+    GICD[GICD_ICENABLER] = 0xffff0000; /* Disable all PPI */
+    GICD[GICD_ISENABLER] = 0x0000ffff; /* Enable all SGI */
+    /* Set PPI and SGI priorities */
+    for (i = 0; i < 32; i += 4)
+        GICD[GICD_IPRIORITYR + i / 4] = 0xa0a0a0a0;
+
+    /* 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 */
+}
+
+static void __cpuinit gic_hyp_init(void)
+{
+    uint32_t vtr;
+
+    vtr = GICH[GICH_VTR];
+    nr_lrs  = (vtr & GICH_VTR_NRLRGS) + 1;
+    printk("GICH: %d list registers available\n", nr_lrs);
+
+    GICH[GICH_HCR] = GICH_HCR_EN;
+    GICH[GICH_MISR] = GICH_MISR_EOI;
+}
+
+/* Set up the GIC */
+void gic_init(void)
+{
+    /* XXX FIXME get this from devicetree */
+    gic.dbase = GIC_BASE_ADDRESS + GIC_DR_OFFSET;
+    gic.cbase = GIC_BASE_ADDRESS + GIC_CR_OFFSET;
+    gic.hbase = GIC_BASE_ADDRESS + GIC_HR_OFFSET;
+    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);
+    set_fixmap(FIXMAP_GICC2, (gic.cbase >> PAGE_SHIFT) + 1, DEV_SHARED);
+    set_fixmap(FIXMAP_GICH, gic.hbase >> PAGE_SHIFT, DEV_SHARED);
+
+    /* 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);
+}
+
+void gic_route_irqs(void)
+{
+    /* XXX should get these from DT */
+    /* GIC maintenance */
+    gic_route_irq(25, 1, 1u << smp_processor_id(), 0xa0);
+    /* Hypervisor Timer */
+    gic_route_irq(26, 1, 1u << smp_processor_id(), 0xa0);
+    /* Timer */
+    gic_route_irq(30, 1, 1u << smp_processor_id(), 0xa0);
+    /* UART */
+    gic_route_irq(37, 0, 1u << smp_processor_id(), 0xa0);
+}
+
+void __init release_irq(unsigned int irq)
+{
+    struct irq_desc *desc;
+    unsigned long flags;
+   struct irqaction *action;
+
+    desc = irq_to_desc(irq);
+
+    spin_lock_irqsave(&desc->lock,flags);
+    action = desc->action;
+    desc->action  = NULL;
+    desc->status |= IRQ_DISABLED;
+
+    spin_lock(&gic.lock);
+    desc->handler->shutdown(desc);
+    spin_unlock(&gic.lock);
+
+    spin_unlock_irqrestore(&desc->lock,flags);
+
+    /* Wait to make sure it's not being used on another CPU */
+    do { smp_mb(); } while ( desc->status & IRQ_INPROGRESS );
+
+    if (action && action->free_on_release)
+        xfree(action);
+}
+
+static int __setup_irq(struct irq_desc *desc, unsigned int irq,
+                       struct irqaction *new)
+{
+    if ( desc->action != NULL )
+        return -EBUSY;
+
+    desc->action  = new;
+    desc->status &= ~IRQ_DISABLED;
+    dsb();
+
+    desc->handler->startup(desc);
+
+    return 0;
+}
+
+int __init setup_irq(unsigned int irq, struct irqaction *new)
+{
+    int rc;
+    unsigned long flags;
+    struct irq_desc *desc;
+
+    desc = irq_to_desc(irq);
+
+    spin_lock_irqsave(&desc->lock, flags);
+
+    rc = __setup_irq(desc, irq, new);
+
+    spin_unlock_irqrestore(&desc->lock,flags);
+
+    return rc;
+}
+
+void gic_set_guest_irq(unsigned int virtual_irq,
+        unsigned int state, unsigned int priority)
+{
+    BUG_ON(virtual_irq > nr_lrs);
+    GICH[GICH_LR + virtual_irq] = state |
+        GICH_LR_MAINTENANCE_IRQ |
+        ((priority >> 3) << GICH_LR_PRIORITY_SHIFT) |
+        ((virtual_irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT);
+}
+
+void gic_inject_irq_start(void)
+{
+    uint32_t hcr;
+    hcr = READ_CP32(HCR);
+    WRITE_CP32(hcr | HCR_VI, HCR);
+    isb();
+}
+
+void gic_inject_irq_stop(void)
+{
+    uint32_t hcr;
+    hcr = READ_CP32(HCR);
+    if (hcr & HCR_VI) {
+        WRITE_CP32(hcr & ~HCR_VI, HCR);
+        isb();
+    }
+}
+
+int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
+                           const char * devname)
+{
+    struct irqaction *action;
+    struct irq_desc *desc = irq_to_desc(irq);
+    unsigned long flags;
+    int retval;
+
+    action = xmalloc(struct irqaction);
+    if (!action)
+        return -ENOMEM;
+
+    action->dev_id = d;
+    action->name = devname;
+
+    spin_lock_irqsave(&desc->lock, flags);
+
+    desc->handler = &gic_guest_irq_type;
+    desc->status |= IRQ_GUEST;
+
+    retval = __setup_irq(desc, irq, action);
+    if (retval) {
+        xfree(action);
+        goto out;
+    }
+
+out:
+    spin_unlock_irqrestore(&desc->lock, flags);
+    return retval;
+}
+
+/* Accept an interrupt from the GIC and dispatch its handler */
+void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
+{
+    uint32_t intack = GICC[GICC_IAR];
+    unsigned int irq = intack & GICC_IA_IRQ;
+
+    if ( irq == 1023 )
+        /* Spurious interrupt */
+        return;
+
+    do_IRQ(regs, irq, is_fiq);
+}
+
+void gicv_setup(struct domain *d)
+{
+    /* map the gic virtual cpu interface in the gic cpu interface region of
+     * the guest */
+    printk("mapping GICC at %#"PRIx32" to %#"PRIx32"\n",
+           GIC_BASE_ADDRESS + GIC_CR_OFFSET,
+           GIC_BASE_ADDRESS + GIC_VR_OFFSET);
+    map_mmio_regions(d, GIC_BASE_ADDRESS + GIC_CR_OFFSET,
+                        GIC_BASE_ADDRESS + GIC_CR_OFFSET + (2 * PAGE_SIZE) - 1,
+                        GIC_BASE_ADDRESS + GIC_VR_OFFSET);
+}
+
+static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs 
*regs)
+{
+    int i, virq;
+    uint32_t lr;
+    uint64_t eisr = GICH[GICH_EISR0] | (((uint64_t) GICH[GICH_EISR1]) << 32);
+
+    for ( i = 0; i < 64; i++ ) {
+        if ( eisr & ((uint64_t)1 << i) ) {
+            struct pending_irq *p;
+
+            lr = GICH[GICH_LR + i];
+            virq = lr & GICH_LR_VIRTUAL_MASK;
+            GICH[GICH_LR + i] = 0;
+
+            spin_lock(&current->arch.vgic.lock);
+            p = irq_to_pending(current, virq);
+            if ( p->desc != NULL ) {
+                p->desc->status &= ~IRQ_INPROGRESS;
+                GICC[GICC_DIR] = virq;
+            }
+            gic_inject_irq_stop();
+            list_del(&p->link);
+            INIT_LIST_HEAD(&p->link);
+            cpu_raise_softirq(current->processor, VGIC_SOFTIRQ);
+            spin_unlock(&current->arch.vgic.lock);
+        }
+    }
+}
+
+void __cpuinit init_maintenance_interrupt(void)
+{
+    request_irq(25, maintenance_interrupt, 0, "irq-maintenance", NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/gic.h b/xen/arch/arm/gic.h
new file mode 100644
index 0000000..63b6648
--- /dev/null
+++ b/xen/arch/arm/gic.h
@@ -0,0 +1,151 @@
+/*
+ * xen/arch/arm/gic.h
+ *
+ * ARM Generic Interrupt Controller support
+ *
+ * Tim Deegan <tim@xxxxxxx>
+ * 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 __ARCH_ARM_GIC_H__
+#define __ARCH_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_ICPIDR2    (0xFE8/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 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_ELRSR0     (0x30/4)
+#define GICH_ELRSR1     (0x34/4)
+#define GICH_APR        (0xF0/4)
+#define GICH_LR         (0x100/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     0x1c00
+
+#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_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_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
+
+extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
+
+extern void gic_route_irqs(void);
+
+extern void __cpuinit init_maintenance_interrupt(void);
+extern void gic_set_guest_irq(unsigned int irq,
+        unsigned int state, unsigned int priority);
+extern void gic_inject_irq_start(void);
+extern void gic_inject_irq_stop(void);
+extern int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
+                                  const char * devname);
+
+/* Accept an interrupt from the GIC and dispatch its handler */
+extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq);
+/* Bring up the interrupt controller */
+extern void gic_init(void);
+/* setup the gic virtual interface for a guest */
+extern void gicv_setup(struct domain *d);
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.2.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

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