* [PATCH v8 0/4] xen/arm: Add support for Huawei hip04-d01 platform
@ 2015-03-03 11:19 Frediano Ziglio
2015-03-03 11:19 ` [PATCH v8 1/4] xen/arm: Duplicate gic-v2.c file to support hip04 platform version Frediano Ziglio
` (3 more replies)
0 siblings, 4 replies; 18+ messages in thread
From: Frediano Ziglio @ 2015-03-03 11:19 UTC (permalink / raw)
To: Ian Campbell, Stefano Stabellini, Tim Deegan, Julien Grall,
frediano.ziglio
Cc: zoltan.kiss, xen-devel
This set of patches add Xen support for hip04-d01 platform (see
https://wiki.linaro.org/Boards/D01 for details).
Changes from v7:
- updated patches;
- moved interrupt controller check in a separate patch (Ian Campbell);
- changed conditional include of gic-hip04.c in Makefile (Ian Campbell);
- added MAINTAINERS update (Ian Campbell).
Changes from v6:
- collapsed some patch (Julien Grall);
- remove useless check for irq values;
- test interrupt controller not using DT compatibility;
- remove non standard drivers flag (Ian Campbell).
Changes from V5.99.1:
- removed RFC again;
- use different constants for hip04 instead of redefine standard ones;
- comment compatible string change;
- add an option to ARM to enable non standard drivers;
- rename gicv2 to hip04gic to make clear this is not a standard gic.
Changes from v5:
- do not change gic-v2.c code but use a copy.
To be considered RFC, to see if better to use copy or other techniques.
Changes from v4:
- rebased to new version;
- removed patch for computing GIC addresses as it apply to all platforms;
- removed patches to platform (cpu and system operations) as now they can
use a bootwrapper which provide them.
Changes from v3:
- change the way regs property is computed for GICv2 (Julien Grall);
- revert order of compaible names for GIC (Julien Grall).
Changes from v2:
- rewrote DTS fix patch (Ian Campbell);
- use is_hip04 macro instead of doing explicit test (Julien Grall);
- do not use quirks to distinguish this platform (Ian Cambell);
- move some GIC constants to C files instead of header (Julien Grall);
- minor changes (Julien Grall).
Changes from v1:
- style (Julien Grall);
- make gicv2_send_SGI faster (Julien Grall);
- cleanup correctly if hip04_smp_init fails (Julien Grall);
- remove quirks using compatibility (Ian Campbell);
- other minor suggestions by Julien Grall.
Frediano Ziglio (4):
xen/arm: Duplicate gic-v2.c file to support hip04 platform version
xen/arm: Check for interrupt controller directly
xen/arm: Make gic-v2 code handle hip04-d01 platform
xen/arm: Force dom0 to use normal GICv2 driver on Hip04 platform
MAINTAINERS | 5 +
xen/arch/arm/Makefile | 1 +
xen/arch/arm/domain_build.c | 2 +-
xen/arch/arm/gic-hip04.c | 815 ++++++++++++++++++++++++++++++++++++++++++++
xen/include/asm-arm/gic.h | 4 +-
5 files changed, 825 insertions(+), 2 deletions(-)
create mode 100644 xen/arch/arm/gic-hip04.c
--
1.9.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v8 1/4] xen/arm: Duplicate gic-v2.c file to support hip04 platform version
2015-03-03 11:19 [PATCH v8 0/4] xen/arm: Add support for Huawei hip04-d01 platform Frediano Ziglio
@ 2015-03-03 11:19 ` Frediano Ziglio
2015-03-03 11:19 ` [PATCH v8 2/4] xen/arm: Check for interrupt controller directly Frediano Ziglio
` (2 subsequent siblings)
3 siblings, 0 replies; 18+ messages in thread
From: Frediano Ziglio @ 2015-03-03 11:19 UTC (permalink / raw)
To: Ian Campbell, Stefano Stabellini, Tim Deegan, Julien Grall,
frediano.ziglio
Cc: zoltan.kiss, xen-devel
HiSilison Hip04 platform use a slightly different version.
This is just a verbatim copy of the file to workaround git
not fully supporting copy operation.
Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
---
xen/arch/arm/gic-hip04.c | 801 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 801 insertions(+)
create mode 100644 xen/arch/arm/gic-hip04.c
diff --git a/xen/arch/arm/gic-hip04.c b/xen/arch/arm/gic-hip04.c
new file mode 100644
index 0000000..20cdbc9
--- /dev/null
+++ b/xen/arch/arm/gic-hip04.c
@@ -0,0 +1,801 @@
+/*
+ * 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 <xen/libfdt/libfdt.h>
+#include <asm/p2m.h>
+#include <asm/domain.h>
+#include <asm/platform.h>
+#include <asm/device.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
+
+/* 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[2]; /* 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 inline void writeb_gicd(uint8_t val, unsigned int offset)
+{
+ writeb_relaxed(val, gicv2.map_dbase + offset);
+}
+
+static inline void writel_gicd(uint32_t val, unsigned int offset)
+{
+ writel_relaxed(val, gicv2.map_dbase + offset);
+}
+
+static inline uint32_t readl_gicd(unsigned int offset)
+{
+ return readl_relaxed(gicv2.map_dbase + offset);
+}
+
+static inline void writel_gicc(uint32_t val, unsigned int offset)
+{
+ unsigned int page = offset >> PAGE_SHIFT;
+ offset &= ~PAGE_MASK;
+ writel_relaxed(val, gicv2.map_cbase[page] + offset);
+}
+
+static inline uint32_t readl_gicc(unsigned int offset)
+{
+ unsigned int page = offset >> PAGE_SHIFT;
+ offset &= ~PAGE_MASK;
+ return readl_relaxed(gicv2.map_cbase[page] + offset);
+}
+
+static inline void writel_gich(uint32_t val, unsigned int offset)
+{
+ writel_relaxed(val, gicv2.map_hbase + offset);
+}
+
+static inline uint32_t readl_gich(int unsigned offset)
+{
+ return readl_relaxed(gicv2.map_hbase + offset);
+}
+
+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.v2.lr[i] = readl_gich(GICH_LR + i * 4);
+
+ v->arch.gic.v2.apr = readl_gich(GICH_APR);
+ v->arch.gic.v2.vmcr = readl_gich(GICH_VMCR);
+ /* Disable until next VCPU scheduled */
+ writel_gich(0, GICH_HCR);
+}
+
+static void gicv2_restore_state(const struct vcpu *v)
+{
+ int i;
+
+ for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+ writel_gich(v->arch.gic.v2.lr[i], GICH_LR + i * 4);
+
+ writel_gich(v->arch.gic.v2.apr, GICH_APR);
+ writel_gich(v->arch.gic.v2.vmcr, GICH_VMCR);
+ writel_gich(GICH_HCR_EN, 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_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.v2.lr[i]);
+ }
+}
+
+static void gicv2_eoi_irq(struct irq_desc *irqd)
+{
+ int irq = irqd->irq;
+ /* Lower the priority */
+ writel_gicc(irq, GICC_EOIR);
+}
+
+static void gicv2_dir_irq(struct irq_desc *irqd)
+{
+ /* Deactivate */
+ writel_gicc(irqd->irq, GICC_DIR);
+}
+
+static unsigned int gicv2_read_irq(void)
+{
+ return (readl_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, actual, 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_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_gicd(cfg, GICD_ICFGR + (irq / 16) * 4);
+
+ actual = readl_gicd(GICD_ICFGR + (irq / 16) * 4);
+ if ( ( cfg & edgebit ) ^ ( actual & edgebit ) )
+ {
+ printk(XENLOG_WARNING "GICv2: WARNING: "
+ "CPU%d: Failed to configure IRQ%u as %s-triggered. "
+ "H/w forces to %s-triggered.\n",
+ smp_processor_id(), desc->irq,
+ cfg & edgebit ? "Edge" : "Level",
+ actual & edgebit ? "Edge" : "Level");
+ desc->arch.type = actual & edgebit ?
+ DT_IRQ_TYPE_EDGE_RISING :
+ DT_IRQ_TYPE_LEVEL_HIGH;
+ }
+
+ /* Set target CPU mask (RAZ/WI on uniprocessor) */
+ writeb_gicd(mask, GICD_ITARGETSR + irq);
+ /* Set priority */
+ writeb_gicd(priority, 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_gicd(GICD_ITARGETSR) & 0xff;
+ cpumask |= cpumask << 8;
+ cpumask |= cpumask << 16;
+
+ /* Disable the distributor */
+ writel_gicd(0, GICD_CTLR);
+
+ type = readl_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_gicd(GICD_IIDR));
+
+ /* Default all global IRQs to level, active low */
+ for ( i = 32; i < gicv2_info.nr_lines; i += 16 )
+ writel_gicd(0x0, GICD_ICFGR + (i / 16) * 4);
+
+ /* Route all global IRQs to this CPU */
+ for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
+ writel_gicd(cpumask, GICD_ITARGETSR + (i / 4) * 4);
+
+ /* Default priority for global interrupts */
+ for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
+ writel_gicd(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
+ GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
+ GICD_IPRIORITYR + (i / 4) * 4);
+
+ /* Disable all global interrupts */
+ for ( i = 32; i < gicv2_info.nr_lines; i += 32 )
+ writel_gicd(~0x0, GICD_ICENABLER + (i / 32) * 4);
+
+ /* Turn on the distributor */
+ writel_gicd(GICD_CTL_ENABLE, GICD_CTLR);
+}
+
+static void __cpuinit gicv2_cpu_init(void)
+{
+ int i;
+
+ this_cpu(gic_cpu_id) = readl_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_gicd(0xffff0000, GICD_ICENABLER); /* Disable all PPI */
+ writel_gicd(0x0000ffff, GICD_ISENABLER); /* Enable all SGI */
+
+ /* Set SGI priorities */
+ for ( i = 0; i < 16; i += 4 )
+ writel_gicd(GIC_PRI_IPI << 24 | GIC_PRI_IPI << 16 |
+ GIC_PRI_IPI << 8 | GIC_PRI_IPI,
+ GICD_IPRIORITYR + (i / 4) * 4);
+
+ /* Set PPI priorities */
+ for ( i = 16; i < 32; i += 4 )
+ writel_gicd(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
+ GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
+ GICD_IPRIORITYR + (i / 4) * 4);
+
+ /* Local settings: interface controller */
+ /* Don't mask by priority */
+ writel_gicc(0xff, GICC_PMR);
+ /* Finest granularity of priority */
+ writel_gicc(0x0, GICC_BPR);
+ /* Turn on delivery */
+ writel_gicc(GICC_CTL_ENABLE|GICC_CTL_EOI, GICC_CTLR);
+}
+
+static void gicv2_cpu_disable(void)
+{
+ writel_gicc(0x0, GICC_CTLR);
+}
+
+static void __cpuinit gicv2_hyp_init(void)
+{
+ uint32_t vtr;
+ uint8_t nr_lrs;
+
+ vtr = readl_gich(GICH_VTR);
+ nr_lrs = (vtr & GICH_V2_VTR_NRLRGS) + 1;
+ gicv2_info.nr_lrs = nr_lrs;
+
+ writel_gich(GICH_MISR_EOI, GICH_MISR);
+}
+
+static void __cpuinit gicv2_hyp_disable(void)
+{
+ writel_gich(0, 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_gicd(GICD_SGI_TARGET_OTHERS | sgi, GICD_SGIR);
+ break;
+ case SGI_TARGET_SELF:
+ writel_gicd(GICD_SGI_TARGET_SELF | sgi, GICD_SGIR);
+ break;
+ case SGI_TARGET_LIST:
+ cpumask_and(&online_mask, cpu_mask, &cpu_online_map);
+ mask = gicv2_cpu_mask(&online_mask);
+ writel_gicd(GICD_SGI_TARGET_LIST |
+ (mask << GICD_SGI_TARGET_SHIFT) | sgi,
+ 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 )
+ {
+ if ( platform_has_quirk(PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI) )
+ lr_reg |= GICH_V2_LR_MAINTENANCE_IRQ;
+ else
+ lr_reg |= GICH_V2_LR_HW | ((p->desc->irq & GICH_V2_LR_PHYSICAL_MASK )
+ << GICH_V2_LR_PHYSICAL_SHIFT);
+ }
+
+ writel_gich(lr_reg, GICH_LR + lr * 4);
+}
+
+static void gicv2_clear_lr(int lr)
+{
+ writel_gich(0, GICH_LR + lr * 4);
+}
+
+static int gicv2v_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 = gicv2.dbase;
+ d->arch.vgic.cbase = gicv2.cbase;
+ }
+ else
+ {
+ d->arch.vgic.dbase = GUEST_GICD_BASE;
+ d->arch.vgic.cbase = GUEST_GICC_BASE;
+ }
+
+ /*
+ * 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, paddr_to_pfn(d->arch.vgic.cbase), 1,
+ paddr_to_pfn(gicv2.vbase));
+ if ( ret )
+ return ret;
+
+ if ( !platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
+ ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase + PAGE_SIZE),
+ 2, paddr_to_pfn(gicv2.vbase + PAGE_SIZE));
+ else
+ ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase + PAGE_SIZE),
+ 2, paddr_to_pfn(gicv2.vbase + 16*PAGE_SIZE));
+
+ return ret;
+}
+
+static void gicv2_read_lr(int lr, struct gic_lr *lr_reg)
+{
+ uint32_t lrv;
+
+ lrv = readl_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_gich(lrv, GICH_LR + lr * 4);
+}
+
+static void gicv2_hcr_status(uint32_t flag, bool_t status)
+{
+ uint32_t hcr = readl_gich(GICH_HCR);
+
+ if ( status )
+ hcr |= flag;
+ else
+ hcr &= (~flag);
+
+ writel_gich(hcr, GICH_HCR);
+}
+
+static unsigned int gicv2_read_vmcr_priority(void)
+{
+ return ((readl_gich(GICH_VMCR) >> GICH_V2_VMCR_PRIORITY_SHIFT)
+ & GICH_V2_VMCR_PRIORITY_MASK);
+}
+
+static unsigned int gicv2_read_apr(int apr_reg)
+{
+ return readl_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);
+ clear_bit(_IRQ_DISABLED, &desc->status);
+ dsb(sy);
+ /* Enable routing */
+ writel_gicd((1u << (irq % 32)), 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_gicd(1u << (irq % 32), GICD_ICENABLER + (irq / 32) * 4);
+ set_bit(_IRQ_DISABLED, &desc->status);
+ 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 *cpu_mask)
+{
+ unsigned int mask;
+
+ ASSERT(!cpumask_empty(cpu_mask));
+
+ spin_lock(&gicv2.lock);
+
+ mask = gicv2_cpu_mask(cpu_mask);
+
+ /* Set target CPU mask (RAZ/WI on uniprocessor) */
+ writeb_gicd(mask, GICD_ITARGETSR + desc->irq);
+
+ spin_unlock(&gicv2.lock);
+}
+
+static int gicv2_make_dt_node(const struct domain *d,
+ const struct dt_device_node *node, void *fdt)
+{
+ const struct dt_device_node *gic = dt_interrupt_controller;
+ const void *compatible = NULL;
+ u32 len;
+ const __be32 *regs;
+ int res = 0;
+
+ compatible = dt_get_property(gic, "compatible", &len);
+ if ( !compatible )
+ {
+ dprintk(XENLOG_ERR, "Can't find compatible property for the gic node\n");
+ return -FDT_ERR_XEN(ENOENT);
+ }
+
+ res = fdt_begin_node(fdt, "interrupt-controller");
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "compatible", compatible, len);
+ if ( res )
+ return res;
+
+ res = fdt_property_cell(fdt, "#interrupt-cells", 3);
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "interrupt-controller", NULL, 0);
+
+ if ( res )
+ return res;
+
+ /*
+ * DTB provides up to 4 regions to handle virtualization
+ * (in order GICD, GICC, GICH and GICV interfaces)
+ * however dom0 just needs GICD and GICC provided by Xen.
+ */
+ regs = dt_get_property(gic, "reg", &len);
+ if ( !regs )
+ {
+ dprintk(XENLOG_ERR, "Can't find reg property for the gic node\n");
+ return -FDT_ERR_XEN(ENOENT);
+ }
+
+ len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node));
+ len *= 2;
+
+ res = fdt_property(fdt, "reg", regs, len);
+
+ return res;
+}
+
+/* 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 = gicv2v_setup,
+ .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,
+ .make_dt_node = gicv2_make_dt_node,
+};
+
+/* Set up the GIC */
+static int __init gicv2_init(struct dt_device_node *node, const void *data)
+{
+ int res;
+
+ 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");
+
+ gicv2.map_cbase[0] = ioremap_nocache(gicv2.cbase, PAGE_SIZE);
+
+ if ( platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
+ gicv2.map_cbase[1] = ioremap_nocache(gicv2.cbase + PAGE_SIZE * 0x10,
+ PAGE_SIZE);
+ else
+ gicv2.map_cbase[1] = ioremap_nocache(gicv2.cbase + PAGE_SIZE, PAGE_SIZE);
+
+ if ( !gicv2.map_cbase[0] || !gicv2.map_cbase[1] )
+ 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);
+
+ return 0;
+}
+
+static const struct dt_device_match gicv2_dt_match[] __initconst =
+{
+ DT_MATCH_GIC_V2,
+ { /* sentinel */ },
+};
+
+DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
+ .dt_match = gicv2_dt_match,
+ .init = gicv2_init,
+DT_DEVICE_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
1.9.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v8 2/4] xen/arm: Check for interrupt controller directly
2015-03-03 11:19 [PATCH v8 0/4] xen/arm: Add support for Huawei hip04-d01 platform Frediano Ziglio
2015-03-03 11:19 ` [PATCH v8 1/4] xen/arm: Duplicate gic-v2.c file to support hip04 platform version Frediano Ziglio
@ 2015-03-03 11:19 ` Frediano Ziglio
2015-03-03 14:45 ` Julien Grall
2015-03-03 11:19 ` [PATCH v8 3/4] xen/arm: Make gic-v2 code handle hip04-d01 platform Frediano Ziglio
2015-03-03 11:19 ` [PATCH v8 4/4] xen/arm: Force dom0 to use normal GICv2 driver on Hip04 platform Frediano Ziglio
3 siblings, 1 reply; 18+ messages in thread
From: Frediano Ziglio @ 2015-03-03 11:19 UTC (permalink / raw)
To: Ian Campbell, Stefano Stabellini, Tim Deegan, Julien Grall,
frediano.ziglio
Cc: zoltan.kiss, xen-devel
This check allow to detect mail interrupt controller even if it does
not match one of the standard ones.
This allow boards with non standard controllers to be handled correctly
without having to manually edit the global list every time.
Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
---
xen/arch/arm/domain_build.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 9f1f59f..83951a3 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1069,7 +1069,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
/* Replace these nodes with our own. Note that the original may be
* used_by DOMID_XEN so this check comes first. */
- if ( dt_match_node(gic_matches, node) )
+ if ( node == dt_interrupt_controller || dt_match_node(gic_matches, node) )
return make_gic_node(d, kinfo->fdt, node);
if ( dt_match_node(timer_matches, node) )
return make_timer_node(d, kinfo->fdt, node);
--
1.9.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v8 3/4] xen/arm: Make gic-v2 code handle hip04-d01 platform
2015-03-03 11:19 [PATCH v8 0/4] xen/arm: Add support for Huawei hip04-d01 platform Frediano Ziglio
2015-03-03 11:19 ` [PATCH v8 1/4] xen/arm: Duplicate gic-v2.c file to support hip04 platform version Frediano Ziglio
2015-03-03 11:19 ` [PATCH v8 2/4] xen/arm: Check for interrupt controller directly Frediano Ziglio
@ 2015-03-03 11:19 ` Frediano Ziglio
2015-03-03 15:07 ` Julien Grall
2015-03-03 11:19 ` [PATCH v8 4/4] xen/arm: Force dom0 to use normal GICv2 driver on Hip04 platform Frediano Ziglio
3 siblings, 1 reply; 18+ messages in thread
From: Frediano Ziglio @ 2015-03-03 11:19 UTC (permalink / raw)
To: Ian Campbell, Stefano Stabellini, Tim Deegan, Julien Grall,
frediano.ziglio
Cc: zoltan.kiss, xen-devel
The GIC in this platform is mainly compatible with the standard
GICv2 beside:
- ITARGET is extended to 16 bit to support 16 CPUs;
- SGI mask is extended to support 16 CPUs;
- maximum supported interrupt is 510;
- GICH APR and LR register offsets.
Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
Signed-off-by: Zoltan Kiss <zoltan.kiss@huawei.com>
---
MAINTAINERS | 5 +
xen/arch/arm/Makefile | 1 +
xen/arch/arm/gic-hip04.c | 396 ++++++++++++++++++++++++-----------------------
3 files changed, 209 insertions(+), 193 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 0f04742..b17aab1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -138,6 +138,11 @@ F: xen/drivers/char/omap-uart.c
F: xen/drivers/char/pl011.c
F: xen/drivers/passthrough/arm/
+HISILICON HIP04 SUPPORT
+M: Frediano Ziglio <frediano.ziglio@huawei.com>
+S: Supported
+F: xen/arch/arm/git-hip04.c
+
CPU POOLS
M: Juergen Gross <jgross@suse.com>
S: Supported
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 41aba2e..935999e 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -12,6 +12,7 @@ obj-y += domctl.o
obj-y += sysctl.o
obj-y += domain_build.o
obj-y += gic.o gic-v2.o
+obj-$(CONFIG_ARM_32) += gic-hip04.o
obj-$(CONFIG_ARM_64) += gic-v3.o
obj-y += io.o
obj-y += irq.o
diff --git a/xen/arch/arm/gic-hip04.c b/xen/arch/arm/gic-hip04.c
index 20cdbc9..94abdc4 100644
--- a/xen/arch/arm/gic-hip04.c
+++ b/xen/arch/arm/gic-hip04.c
@@ -1,7 +1,8 @@
/*
- * xen/arch/arm/gic-v2.c
+ * xen/arch/arm/gic-hip04.c
*
- * ARM Generic Interrupt Controller support v2
+ * Generic Interrupt Controller for HiSilicon Hip04 platform
+ * Based heavily from gic-v2.c
*
* Tim Deegan <tim@xen.org>
* Copyright (c) 2011 Citrix Systems.
@@ -71,59 +72,69 @@ static struct {
void __iomem * map_hbase; /* IO Address of virtual interface registers */
paddr_t vbase; /* Address of virtual cpu interface registers */
spinlock_t lock;
-} gicv2;
+} hip04gic;
-static struct gic_info gicv2_info;
+static struct gic_info hip04gic_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);
+static DEFINE_PER_CPU(u16, gic_cpu_id);
/* Maximum cpu interface per GIC */
-#define NR_GIC_CPU_IF 8
+#define NR_GIC_CPU_IF 16
+
+#define HIP04_GICD_SGI_TARGET_SHIFT 8
+
+#define HIP04_GICH_APR 0x70
+#define HIP04_GICH_LR 0x80
static inline void writeb_gicd(uint8_t val, unsigned int offset)
{
- writeb_relaxed(val, gicv2.map_dbase + offset);
+ writeb_relaxed(val, hip04gic.map_dbase + offset);
+}
+
+static inline void writew_gicd(uint16_t val, unsigned int offset)
+{
+ writew_relaxed(val, hip04gic.map_dbase + offset);
}
static inline void writel_gicd(uint32_t val, unsigned int offset)
{
- writel_relaxed(val, gicv2.map_dbase + offset);
+ writel_relaxed(val, hip04gic.map_dbase + offset);
}
static inline uint32_t readl_gicd(unsigned int offset)
{
- return readl_relaxed(gicv2.map_dbase + offset);
+ return readl_relaxed(hip04gic.map_dbase + offset);
}
static inline void writel_gicc(uint32_t val, unsigned int offset)
{
unsigned int page = offset >> PAGE_SHIFT;
offset &= ~PAGE_MASK;
- writel_relaxed(val, gicv2.map_cbase[page] + offset);
+ writel_relaxed(val, hip04gic.map_cbase[page] + offset);
}
static inline uint32_t readl_gicc(unsigned int offset)
{
unsigned int page = offset >> PAGE_SHIFT;
offset &= ~PAGE_MASK;
- return readl_relaxed(gicv2.map_cbase[page] + offset);
+ return readl_relaxed(hip04gic.map_cbase[page] + offset);
}
static inline void writel_gich(uint32_t val, unsigned int offset)
{
- writel_relaxed(val, gicv2.map_hbase + offset);
+ writel_relaxed(val, hip04gic.map_hbase + offset);
}
static inline uint32_t readl_gich(int unsigned offset)
{
- return readl_relaxed(gicv2.map_hbase + offset);
+ return readl_relaxed(hip04gic.map_hbase + offset);
}
-static unsigned int gicv2_cpu_mask(const cpumask_t *cpumask)
+static unsigned int hip04gic_cpu_mask(const cpumask_t *cpumask)
{
unsigned int cpu;
unsigned int mask = 0;
@@ -139,7 +150,7 @@ static unsigned int gicv2_cpu_mask(const cpumask_t *cpumask)
return mask;
}
-static void gicv2_save_state(struct vcpu *v)
+static void hip04gic_save_state(struct vcpu *v)
{
int i;
@@ -147,58 +158,58 @@ static void gicv2_save_state(struct vcpu *v)
* 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.v2.lr[i] = readl_gich(GICH_LR + i * 4);
+ for ( i = 0; i < hip04gic_info.nr_lrs; i++ )
+ v->arch.gic.v2.lr[i] = readl_gich(HIP04_GICH_LR + i * 4);
- v->arch.gic.v2.apr = readl_gich(GICH_APR);
+ v->arch.gic.v2.apr = readl_gich(HIP04_GICH_APR);
v->arch.gic.v2.vmcr = readl_gich(GICH_VMCR);
/* Disable until next VCPU scheduled */
writel_gich(0, GICH_HCR);
}
-static void gicv2_restore_state(const struct vcpu *v)
+static void hip04gic_restore_state(const struct vcpu *v)
{
int i;
- for ( i = 0; i < gicv2_info.nr_lrs; i++ )
- writel_gich(v->arch.gic.v2.lr[i], GICH_LR + i * 4);
+ for ( i = 0; i < hip04gic_info.nr_lrs; i++ )
+ writel_gich(v->arch.gic.v2.lr[i], HIP04_GICH_LR + i * 4);
- writel_gich(v->arch.gic.v2.apr, GICH_APR);
+ writel_gich(v->arch.gic.v2.apr, HIP04_GICH_APR);
writel_gich(v->arch.gic.v2.vmcr, GICH_VMCR);
writel_gich(GICH_HCR_EN, GICH_HCR);
}
-static void gicv2_dump_state(const struct vcpu *v)
+static void hip04gic_dump_state(const struct vcpu *v)
{
int i;
if ( v == current )
{
- for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+ for ( i = 0; i < hip04gic_info.nr_lrs; i++ )
printk(" HW_LR[%d]=%x\n", i,
- readl_gich(GICH_LR + i * 4));
+ readl_gich(HIP04_GICH_LR + i * 4));
}
else
{
- for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+ for ( i = 0; i < hip04gic_info.nr_lrs; i++ )
printk(" VCPU_LR[%d]=%x\n", i, v->arch.gic.v2.lr[i]);
}
}
-static void gicv2_eoi_irq(struct irq_desc *irqd)
+static void hip04gic_eoi_irq(struct irq_desc *irqd)
{
int irq = irqd->irq;
/* Lower the priority */
writel_gicc(irq, GICC_EOIR);
}
-static void gicv2_dir_irq(struct irq_desc *irqd)
+static void hip04gic_dir_irq(struct irq_desc *irqd)
{
/* Deactivate */
writel_gicc(irqd->irq, GICC_DIR);
}
-static unsigned int gicv2_read_irq(void)
+static unsigned int hip04gic_read_irq(void)
{
return (readl_gicc(GICC_IAR) & GICC_IA_IRQ);
}
@@ -207,19 +218,19 @@ static unsigned int gicv2_read_irq(void)
* 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,
+static void hip04gic_set_irq_properties(struct irq_desc *desc,
const cpumask_t *cpu_mask,
unsigned int priority)
{
uint32_t cfg, actual, edgebit;
- unsigned int mask = gicv2_cpu_mask(cpu_mask);
+ unsigned int mask = hip04gic_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);
+ spin_lock(&hip04gic.lock);
/* Set edge / level */
cfg = readl_gicd(GICD_ICFGR + (irq / 16) * 4);
edgebit = 2u << (2 * (irq % 16));
@@ -232,7 +243,7 @@ static void gicv2_set_irq_properties(struct irq_desc *desc,
actual = readl_gicd(GICD_ICFGR + (irq / 16) * 4);
if ( ( cfg & edgebit ) ^ ( actual & edgebit ) )
{
- printk(XENLOG_WARNING "GICv2: WARNING: "
+ printk(XENLOG_WARNING "GIC-HIP04: WARNING: "
"CPU%d: Failed to configure IRQ%u as %s-triggered. "
"H/w forces to %s-triggered.\n",
smp_processor_id(), desc->irq,
@@ -244,62 +255,61 @@ static void gicv2_set_irq_properties(struct irq_desc *desc,
}
/* Set target CPU mask (RAZ/WI on uniprocessor) */
- writeb_gicd(mask, GICD_ITARGETSR + irq);
+ writew_gicd(mask, GICD_ITARGETSR + irq * 2);
/* Set priority */
writeb_gicd(priority, GICD_IPRIORITYR + irq);
- spin_unlock(&gicv2.lock);
+ spin_unlock(&hip04gic.lock);
}
-static void __init gicv2_dist_init(void)
+static void __init hip04gic_dist_init(void)
{
uint32_t type;
uint32_t cpumask;
uint32_t gic_cpus;
int i;
- cpumask = readl_gicd(GICD_ITARGETSR) & 0xff;
- cpumask |= cpumask << 8;
+ cpumask = readl_gicd(GICD_ITARGETSR) & 0xffff;
cpumask |= cpumask << 16;
/* Disable the distributor */
writel_gicd(0, GICD_CTLR);
type = readl_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",
+ hip04gic_info.nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1);
+ gic_cpus = 16;
+ printk("GIC-HIP04: %d lines, %d cpu%s%s (IID %8.8x).\n",
+ hip04gic_info.nr_lines, gic_cpus, (gic_cpus == 1) ? "" : "s",
(type & GICD_TYPE_SEC) ? ", secure" : "",
readl_gicd(GICD_IIDR));
/* Default all global IRQs to level, active low */
- for ( i = 32; i < gicv2_info.nr_lines; i += 16 )
+ for ( i = 32; i < hip04gic_info.nr_lines; i += 16 )
writel_gicd(0x0, GICD_ICFGR + (i / 16) * 4);
/* Route all global IRQs to this CPU */
- for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
- writel_gicd(cpumask, GICD_ITARGETSR + (i / 4) * 4);
+ for ( i = 32; i < hip04gic_info.nr_lines; i += 2 )
+ writel_gicd(cpumask, GICD_ITARGETSR + (i / 2) * 4);
/* Default priority for global interrupts */
- for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
+ for ( i = 32; i < hip04gic_info.nr_lines; i += 4 )
writel_gicd(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
GICD_IPRIORITYR + (i / 4) * 4);
/* Disable all global interrupts */
- for ( i = 32; i < gicv2_info.nr_lines; i += 32 )
+ for ( i = 32; i < hip04gic_info.nr_lines; i += 32 )
writel_gicd(~0x0, GICD_ICENABLER + (i / 32) * 4);
/* Turn on the distributor */
writel_gicd(GICD_CTL_ENABLE, GICD_CTLR);
}
-static void __cpuinit gicv2_cpu_init(void)
+static void __cpuinit hip04gic_cpu_init(void)
{
int i;
- this_cpu(gic_cpu_id) = readl_gicd(GICD_ITARGETSR) & 0xff;
+ this_cpu(gic_cpu_id) = readl_gicd(GICD_ITARGETSR) & 0xffff;
/* The first 32 interrupts (PPI and SGI) are banked per-cpu, so
* even though they are controlled with GICD registers, they must
@@ -328,41 +338,41 @@ static void __cpuinit gicv2_cpu_init(void)
writel_gicc(GICC_CTL_ENABLE|GICC_CTL_EOI, GICC_CTLR);
}
-static void gicv2_cpu_disable(void)
+static void hip04gic_cpu_disable(void)
{
writel_gicc(0x0, GICC_CTLR);
}
-static void __cpuinit gicv2_hyp_init(void)
+static void __cpuinit hip04gic_hyp_init(void)
{
uint32_t vtr;
uint8_t nr_lrs;
vtr = readl_gich(GICH_VTR);
nr_lrs = (vtr & GICH_V2_VTR_NRLRGS) + 1;
- gicv2_info.nr_lrs = nr_lrs;
+ hip04gic_info.nr_lrs = nr_lrs;
writel_gich(GICH_MISR_EOI, GICH_MISR);
}
-static void __cpuinit gicv2_hyp_disable(void)
+static void __cpuinit hip04gic_hyp_disable(void)
{
writel_gich(0, GICH_HCR);
}
-static int gicv2_secondary_cpu_init(void)
+static int hip04gic_secondary_cpu_init(void)
{
- spin_lock(&gicv2.lock);
+ spin_lock(&hip04gic.lock);
- gicv2_cpu_init();
- gicv2_hyp_init();
+ hip04gic_cpu_init();
+ hip04gic_hyp_init();
- spin_unlock(&gicv2.lock);
+ spin_unlock(&hip04gic.lock);
return 0;
}
-static void gicv2_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
+static void hip04gic_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
const cpumask_t *cpu_mask)
{
unsigned int mask = 0;
@@ -378,9 +388,9 @@ static void gicv2_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
break;
case SGI_TARGET_LIST:
cpumask_and(&online_mask, cpu_mask, &cpu_online_map);
- mask = gicv2_cpu_mask(&online_mask);
+ mask = hip04gic_cpu_mask(&online_mask);
writel_gicd(GICD_SGI_TARGET_LIST |
- (mask << GICD_SGI_TARGET_SHIFT) | sgi,
+ (mask << HIP04_GICD_SGI_TARGET_SHIFT) | sgi,
GICD_SGIR);
break;
default:
@@ -389,20 +399,20 @@ static void gicv2_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
}
/* Shut down the per-CPU GIC interface */
-static void gicv2_disable_interface(void)
+static void hip04gic_disable_interface(void)
{
- spin_lock(&gicv2.lock);
- gicv2_cpu_disable();
- gicv2_hyp_disable();
- spin_unlock(&gicv2.lock);
+ spin_lock(&hip04gic.lock);
+ hip04gic_cpu_disable();
+ hip04gic_hyp_disable();
+ spin_unlock(&hip04gic.lock);
}
-static void gicv2_update_lr(int lr, const struct pending_irq *p,
+static void hip04gic_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 >= hip04gic_info.nr_lrs);
BUG_ON(lr < 0);
lr_reg = (((state & GICH_V2_LR_STATE_MASK) << GICH_V2_LR_STATE_SHIFT) |
@@ -419,15 +429,15 @@ static void gicv2_update_lr(int lr, const struct pending_irq *p,
<< GICH_V2_LR_PHYSICAL_SHIFT);
}
- writel_gich(lr_reg, GICH_LR + lr * 4);
+ writel_gich(lr_reg, HIP04_GICH_LR + lr * 4);
}
-static void gicv2_clear_lr(int lr)
+static void hip04gic_clear_lr(int lr)
{
- writel_gich(0, GICH_LR + lr * 4);
+ writel_gich(0, HIP04_GICH_LR + lr * 4);
}
-static int gicv2v_setup(struct domain *d)
+static int hip04gicv_setup(struct domain *d)
{
int ret;
@@ -437,8 +447,8 @@ static int gicv2v_setup(struct domain *d)
*/
if ( is_hardware_domain(d) )
{
- d->arch.vgic.dbase = gicv2.dbase;
- d->arch.vgic.cbase = gicv2.cbase;
+ d->arch.vgic.dbase = hip04gic.dbase;
+ d->arch.vgic.cbase = hip04gic.cbase;
}
else
{
@@ -454,25 +464,25 @@ static int gicv2v_setup(struct domain *d)
* GIC_64K_STRIDE quirk. The DTB passed to the guest reflects this.
*/
ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase), 1,
- paddr_to_pfn(gicv2.vbase));
+ paddr_to_pfn(hip04gic.vbase));
if ( ret )
return ret;
if ( !platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase + PAGE_SIZE),
- 2, paddr_to_pfn(gicv2.vbase + PAGE_SIZE));
+ 2, paddr_to_pfn(hip04gic.vbase + PAGE_SIZE));
else
ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase + PAGE_SIZE),
- 2, paddr_to_pfn(gicv2.vbase + 16*PAGE_SIZE));
+ 2, paddr_to_pfn(hip04gic.vbase + 16*PAGE_SIZE));
return ret;
}
-static void gicv2_read_lr(int lr, struct gic_lr *lr_reg)
+static void hip04gic_read_lr(int lr, struct gic_lr *lr_reg)
{
uint32_t lrv;
- lrv = readl_gich(GICH_LR + lr * 4);
+ lrv = readl_gich(HIP04_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;
@@ -481,7 +491,7 @@ static void gicv2_read_lr(int lr, struct gic_lr *lr_reg)
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)
+static void hip04gic_write_lr(int lr, const struct gic_lr *lr_reg)
{
uint32_t lrv = 0;
@@ -495,10 +505,10 @@ static void gicv2_write_lr(int lr, const struct gic_lr *lr_reg)
<< GICH_V2_LR_HW_SHIFT) |
((uint32_t)(lr_reg->grp & GICH_V2_LR_GRP_MASK) << GICH_V2_LR_GRP_SHIFT) );
- writel_gich(lrv, GICH_LR + lr * 4);
+ writel_gich(lrv, HIP04_GICH_LR + lr * 4);
}
-static void gicv2_hcr_status(uint32_t flag, bool_t status)
+static void hip04gic_hcr_status(uint32_t flag, bool_t status)
{
uint32_t hcr = readl_gich(GICH_HCR);
@@ -510,95 +520,95 @@ static void gicv2_hcr_status(uint32_t flag, bool_t status)
writel_gich(hcr, GICH_HCR);
}
-static unsigned int gicv2_read_vmcr_priority(void)
+static unsigned int hip04gic_read_vmcr_priority(void)
{
return ((readl_gich(GICH_VMCR) >> GICH_V2_VMCR_PRIORITY_SHIFT)
& GICH_V2_VMCR_PRIORITY_MASK);
}
-static unsigned int gicv2_read_apr(int apr_reg)
+static unsigned int hip04gic_read_apr(int apr_reg)
{
- return readl_gich(GICH_APR);
+ return readl_gich(HIP04_GICH_APR);
}
-static void gicv2_irq_enable(struct irq_desc *desc)
+static void hip04gic_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);
+ spin_lock_irqsave(&hip04gic.lock, flags);
clear_bit(_IRQ_DISABLED, &desc->status);
dsb(sy);
/* Enable routing */
writel_gicd((1u << (irq % 32)), GICD_ISENABLER + (irq / 32) * 4);
- spin_unlock_irqrestore(&gicv2.lock, flags);
+ spin_unlock_irqrestore(&hip04gic.lock, flags);
}
-static void gicv2_irq_disable(struct irq_desc *desc)
+static void hip04gic_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);
+ spin_lock_irqsave(&hip04gic.lock, flags);
/* Disable routing */
writel_gicd(1u << (irq % 32), GICD_ICENABLER + (irq / 32) * 4);
set_bit(_IRQ_DISABLED, &desc->status);
- spin_unlock_irqrestore(&gicv2.lock, flags);
+ spin_unlock_irqrestore(&hip04gic.lock, flags);
}
-static unsigned int gicv2_irq_startup(struct irq_desc *desc)
+static unsigned int hip04gic_irq_startup(struct irq_desc *desc)
{
- gicv2_irq_enable(desc);
+ hip04gic_irq_enable(desc);
return 0;
}
-static void gicv2_irq_shutdown(struct irq_desc *desc)
+static void hip04gic_irq_shutdown(struct irq_desc *desc)
{
- gicv2_irq_disable(desc);
+ hip04gic_irq_disable(desc);
}
-static void gicv2_irq_ack(struct irq_desc *desc)
+static void hip04gic_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)
+static void hip04gic_host_irq_end(struct irq_desc *desc)
{
/* Lower the priority */
- gicv2_eoi_irq(desc);
+ hip04gic_eoi_irq(desc);
/* Deactivate */
- gicv2_dir_irq(desc);
+ hip04gic_dir_irq(desc);
}
-static void gicv2_guest_irq_end(struct irq_desc *desc)
+static void hip04gic_guest_irq_end(struct irq_desc *desc)
{
/* Lower the priority of the IRQ */
- gicv2_eoi_irq(desc);
+ hip04gic_eoi_irq(desc);
/* Deactivation happens in maintenance interrupt / via GICV */
}
-static void gicv2_irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask)
+static void hip04gic_irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask)
{
unsigned int mask;
ASSERT(!cpumask_empty(cpu_mask));
- spin_lock(&gicv2.lock);
+ spin_lock(&hip04gic.lock);
- mask = gicv2_cpu_mask(cpu_mask);
+ mask = hip04gic_cpu_mask(cpu_mask);
/* Set target CPU mask (RAZ/WI on uniprocessor) */
- writeb_gicd(mask, GICD_ITARGETSR + desc->irq);
+ writew_gicd(mask, GICD_ITARGETSR + desc->irq * 2);
- spin_unlock(&gicv2.lock);
+ spin_unlock(&hip04gic.lock);
}
-static int gicv2_make_dt_node(const struct domain *d,
+static int hip04gic_make_dt_node(const struct domain *d,
const struct dt_device_node *node, void *fdt)
{
const struct dt_device_node *gic = dt_interrupt_controller;
@@ -652,143 +662,143 @@ static int gicv2_make_dt_node(const struct domain *d,
}
/* 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 hip04gic_host_irq_type = {
+ .typename = "gic-hip04",
+ .startup = hip04gic_irq_startup,
+ .shutdown = hip04gic_irq_shutdown,
+ .enable = hip04gic_irq_enable,
+ .disable = hip04gic_irq_disable,
+ .ack = hip04gic_irq_ack,
+ .end = hip04gic_host_irq_end,
+ .set_affinity = hip04gic_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,
+static hw_irq_controller hip04gic_guest_irq_type = {
+ .typename = "gic-hip04",
+ .startup = hip04gic_irq_startup,
+ .shutdown = hip04gic_irq_shutdown,
+ .enable = hip04gic_irq_enable,
+ .disable = hip04gic_irq_disable,
+ .ack = hip04gic_irq_ack,
+ .end = hip04gic_guest_irq_end,
+ .set_affinity = hip04gic_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 = gicv2v_setup,
- .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,
- .make_dt_node = gicv2_make_dt_node,
+const static struct gic_hw_operations hip04gic_ops = {
+ .info = &hip04gic_info,
+ .secondary_init = hip04gic_secondary_cpu_init,
+ .save_state = hip04gic_save_state,
+ .restore_state = hip04gic_restore_state,
+ .dump_state = hip04gic_dump_state,
+ .gicv_setup = hip04gicv_setup,
+ .gic_host_irq_type = &hip04gic_host_irq_type,
+ .gic_guest_irq_type = &hip04gic_guest_irq_type,
+ .eoi_irq = hip04gic_eoi_irq,
+ .deactivate_irq = hip04gic_dir_irq,
+ .read_irq = hip04gic_read_irq,
+ .set_irq_properties = hip04gic_set_irq_properties,
+ .send_SGI = hip04gic_send_SGI,
+ .disable_interface = hip04gic_disable_interface,
+ .update_lr = hip04gic_update_lr,
+ .update_hcr_status = hip04gic_hcr_status,
+ .clear_lr = hip04gic_clear_lr,
+ .read_lr = hip04gic_read_lr,
+ .write_lr = hip04gic_write_lr,
+ .read_vmcr_priority = hip04gic_read_vmcr_priority,
+ .read_apr = hip04gic_read_apr,
+ .make_dt_node = hip04gic_make_dt_node,
};
/* Set up the GIC */
-static int __init gicv2_init(struct dt_device_node *node, const void *data)
+static int __init hip04gic_init(struct dt_device_node *node, const void *data)
{
int res;
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, 0, &hip04gic.dbase, NULL);
+ if ( res || !hip04gic.dbase || (hip04gic.dbase & ~PAGE_MASK) )
+ panic("GIC-HIP04: 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, 1, &hip04gic.cbase, NULL);
+ if ( res || !hip04gic.cbase || (hip04gic.cbase & ~PAGE_MASK) )
+ panic("GIC-HIP04: 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, 2, &hip04gic.hbase, NULL);
+ if ( res || !hip04gic.hbase || (hip04gic.hbase & ~PAGE_MASK) )
+ panic("GIC-HIP04: 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 = dt_device_get_address(node, 3, &hip04gic.vbase, NULL);
+ if ( res || !hip04gic.vbase || (hip04gic.vbase & ~PAGE_MASK) )
+ panic("GIC-HIP04: 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;
+ panic("GIC-HIP04: Cannot find the maintenance IRQ");
+ hip04gic_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"
+ printk("GIC-HIP04 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);
+ hip04gic.dbase, hip04gic.cbase, hip04gic.hbase, hip04gic.vbase,
+ hip04gic_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");
+ if ( (hip04gic.dbase & ~PAGE_MASK) || (hip04gic.cbase & ~PAGE_MASK) ||
+ (hip04gic.hbase & ~PAGE_MASK) || (hip04gic.vbase & ~PAGE_MASK) )
+ panic("GIC-HIP04 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");
+ hip04gic.map_dbase = ioremap_nocache(hip04gic.dbase, PAGE_SIZE);
+ if ( !hip04gic.map_dbase )
+ panic("GIC-HIP04: Failed to ioremap for GIC distributor\n");
- gicv2.map_cbase[0] = ioremap_nocache(gicv2.cbase, PAGE_SIZE);
+ hip04gic.map_cbase[0] = ioremap_nocache(hip04gic.cbase, PAGE_SIZE);
if ( platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
- gicv2.map_cbase[1] = ioremap_nocache(gicv2.cbase + PAGE_SIZE * 0x10,
+ hip04gic.map_cbase[1] = ioremap_nocache(hip04gic.cbase + PAGE_SIZE * 0x10,
PAGE_SIZE);
else
- gicv2.map_cbase[1] = ioremap_nocache(gicv2.cbase + PAGE_SIZE, PAGE_SIZE);
+ hip04gic.map_cbase[1] = ioremap_nocache(hip04gic.cbase + PAGE_SIZE, PAGE_SIZE);
- if ( !gicv2.map_cbase[0] || !gicv2.map_cbase[1] )
- panic("GICv2: Failed to ioremap for GIC CPU interface\n");
+ if ( !hip04gic.map_cbase[0] || !hip04gic.map_cbase[1] )
+ panic("GIC-HIP04: 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");
+ hip04gic.map_hbase = ioremap_nocache(hip04gic.hbase, PAGE_SIZE);
+ if ( !hip04gic.map_hbase )
+ panic("GIC-HIP04: Failed to ioremap for GIC Virtual interface\n");
/* Global settings: interrupt distributor */
- spin_lock_init(&gicv2.lock);
- spin_lock(&gicv2.lock);
+ spin_lock_init(&hip04gic.lock);
+ spin_lock(&hip04gic.lock);
- gicv2_dist_init();
- gicv2_cpu_init();
- gicv2_hyp_init();
+ hip04gic_dist_init();
+ hip04gic_cpu_init();
+ hip04gic_hyp_init();
- spin_unlock(&gicv2.lock);
+ spin_unlock(&hip04gic.lock);
- gicv2_info.hw_version = GIC_V2;
- register_gic_ops(&gicv2_ops);
+ hip04gic_info.hw_version = GIC_V2;
+ register_gic_ops(&hip04gic_ops);
return 0;
}
-static const struct dt_device_match gicv2_dt_match[] __initconst =
+static const struct dt_device_match hip04gic_dt_match[] __initconst =
{
- DT_MATCH_GIC_V2,
+ DT_MATCH_COMPATIBLE("hisilicon,hip04-intc"),
{ /* sentinel */ },
};
-DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
- .dt_match = gicv2_dt_match,
- .init = gicv2_init,
+DT_DEVICE_START(hip04gic, "GIC-HIP04", DEVICE_GIC)
+ .dt_match = hip04gic_dt_match,
+ .init = hip04gic_init,
DT_DEVICE_END
/*
--
1.9.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v8 4/4] xen/arm: Force dom0 to use normal GICv2 driver on Hip04 platform
2015-03-03 11:19 [PATCH v8 0/4] xen/arm: Add support for Huawei hip04-d01 platform Frediano Ziglio
` (2 preceding siblings ...)
2015-03-03 11:19 ` [PATCH v8 3/4] xen/arm: Make gic-v2 code handle hip04-d01 platform Frediano Ziglio
@ 2015-03-03 11:19 ` Frediano Ziglio
3 siblings, 0 replies; 18+ messages in thread
From: Frediano Ziglio @ 2015-03-03 11:19 UTC (permalink / raw)
To: Ian Campbell, Stefano Stabellini, Tim Deegan, Julien Grall,
frediano.ziglio
Cc: zoltan.kiss, xen-devel
Until vGIC support is not implemented and tested, this will prevent
guest kernels to use their Hip04 driver, or crash when they don't
have any.
Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
---
xen/arch/arm/gic-hip04.c | 18 +++++++++++-------
xen/include/asm-arm/gic.h | 4 +++-
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/xen/arch/arm/gic-hip04.c b/xen/arch/arm/gic-hip04.c
index 94abdc4..9388350 100644
--- a/xen/arch/arm/gic-hip04.c
+++ b/xen/arch/arm/gic-hip04.c
@@ -612,17 +612,21 @@ static int hip04gic_make_dt_node(const struct domain *d,
const struct dt_device_node *node, void *fdt)
{
const struct dt_device_node *gic = dt_interrupt_controller;
- const void *compatible = NULL;
+ const void *compatible;
u32 len;
const __be32 *regs;
int res = 0;
- compatible = dt_get_property(gic, "compatible", &len);
- if ( !compatible )
- {
- dprintk(XENLOG_ERR, "Can't find compatible property for the gic node\n");
- return -FDT_ERR_XEN(ENOENT);
- }
+ /*
+ * Replace compatibility string with a standard one.
+ * dom0 will see a compatible GIC. This as GICC is compatible
+ * with standard one and GICD (emulated by Xen) is compatible
+ * to standard. Otherwise we should implement HIP04 GICD in
+ * the virtual GIC.
+ * This actually limit CPU number to 8 for dom0.
+ */
+ compatible = DT_COMPAT_GIC_CORTEX_A15;
+ len = strlen((char*) compatible) + 1;
res = fdt_begin_node(fdt, "interrupt-controller");
if ( res )
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 6f5767f..89a9b6f 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -153,8 +153,10 @@
#include <xen/irq.h>
#include <asm-arm/vgic.h>
+#define DT_COMPAT_GIC_CORTEX_A15 "arm,cortex-a15-gic"
+
#define DT_MATCH_GIC_V2 \
- DT_MATCH_COMPATIBLE("arm,cortex-a15-gic"), \
+ DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_CORTEX_A15), \
DT_MATCH_COMPATIBLE("arm,cortex-a7-gic"), \
DT_MATCH_COMPATIBLE("arm,gic-400")
--
1.9.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v8 2/4] xen/arm: Check for interrupt controller directly
2015-03-03 11:19 ` [PATCH v8 2/4] xen/arm: Check for interrupt controller directly Frediano Ziglio
@ 2015-03-03 14:45 ` Julien Grall
2015-03-03 15:07 ` Frediano Ziglio
2015-03-05 16:36 ` Ian Campbell
0 siblings, 2 replies; 18+ messages in thread
From: Julien Grall @ 2015-03-03 14:45 UTC (permalink / raw)
To: Frediano Ziglio, Ian Campbell, Stefano Stabellini, Tim Deegan
Cc: zoltan.kiss, xen-devel
Hello Frediano,
On 03/03/15 11:19, Frediano Ziglio wrote:
> This check allow to detect mail interrupt controller even if it does
main
> not match one of the standard ones.
> This allow boards with non standard controllers to be handled correctly
> without having to manually edit the global list every time.
>
> Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
> ---
> xen/arch/arm/domain_build.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 9f1f59f..83951a3 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1069,7 +1069,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
>
> /* Replace these nodes with our own. Note that the original may be
> * used_by DOMID_XEN so this check comes first. */
> - if ( dt_match_node(gic_matches, node) )
> + if ( node == dt_interrupt_controller || dt_match_node(gic_matches, node) )
> return make_gic_node(d, kinfo->fdt, node);
What about if the device tree exposes multiple GICs? By mistake we will
expose the secondaries GIC if they are not standard.
As I suggested on a previous mail, I would prefer to introduce a new
callback to check if the node is a GIC.
Regards,
--
Julien Grall
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 2/4] xen/arm: Check for interrupt controller directly
2015-03-03 14:45 ` Julien Grall
@ 2015-03-03 15:07 ` Frediano Ziglio
2015-03-03 15:10 ` Julien Grall
2015-03-05 16:36 ` Ian Campbell
1 sibling, 1 reply; 18+ messages in thread
From: Frediano Ziglio @ 2015-03-03 15:07 UTC (permalink / raw)
To: Julien Grall
Cc: Zoltan Kiss, Ian Campbell, Tim Deegan, Xen-devel, Frediano Ziglio,
Stefano Stabellini
2015-03-03 14:45 GMT+00:00 Julien Grall <julien.grall@linaro.org>:
> Hello Frediano,
>
> On 03/03/15 11:19, Frediano Ziglio wrote:
>> This check allow to detect mail interrupt controller even if it does
>
> main
>
>> not match one of the standard ones.
>> This allow boards with non standard controllers to be handled correctly
>> without having to manually edit the global list every time.
>>
>> Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
>> ---
>> xen/arch/arm/domain_build.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>> index 9f1f59f..83951a3 100644
>> --- a/xen/arch/arm/domain_build.c
>> +++ b/xen/arch/arm/domain_build.c
>> @@ -1069,7 +1069,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
>>
>> /* Replace these nodes with our own. Note that the original may be
>> * used_by DOMID_XEN so this check comes first. */
>> - if ( dt_match_node(gic_matches, node) )
>> + if ( node == dt_interrupt_controller || dt_match_node(gic_matches, node) )
>> return make_gic_node(d, kinfo->fdt, node);
>
> What about if the device tree exposes multiple GICs? By mistake we will
> expose the secondaries GIC if they are not standard.
>
> As I suggested on a previous mail, I would prefer to introduce a new
> callback to check if the node is a GIC.
>
I think something like this would make all happy (I hope, I tested and
works correctly on my board):
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 9f1f59f..aaa3b97 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1035,12 +1035,6 @@ static int handle_node(struct domain *d, struct
kernel_info *kinfo,
DT_MATCH_COMPATIBLE("arm,armv7-timer-mem"),
{ /* sentinel */ },
};
- static const struct dt_device_match gic_matches[] __initconst =
- {
- DT_MATCH_GIC_V2,
- DT_MATCH_GIC_V3,
- { /* sentinel */ },
- };
static const struct dt_device_match timer_matches[] __initconst =
{
DT_MATCH_TIMER,
@@ -1069,7 +1063,7 @@ static int handle_node(struct domain *d, struct
kernel_info *kinfo,
/* Replace these nodes with our own. Note that the original may be
* used_by DOMID_XEN so this check comes first. */
- if ( dt_match_node(gic_matches, node) )
+ if ( device_get_class(node) == DEVICE_GIC )
return make_gic_node(d, kinfo->fdt, node);
if ( dt_match_node(timer_matches, node) )
return make_timer_node(d, kinfo->fdt, node);
--
1.9.1
Frediano
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v8 3/4] xen/arm: Make gic-v2 code handle hip04-d01 platform
2015-03-03 11:19 ` [PATCH v8 3/4] xen/arm: Make gic-v2 code handle hip04-d01 platform Frediano Ziglio
@ 2015-03-03 15:07 ` Julien Grall
2015-03-03 15:36 ` Frediano Ziglio
0 siblings, 1 reply; 18+ messages in thread
From: Julien Grall @ 2015-03-03 15:07 UTC (permalink / raw)
To: Frediano Ziglio, Ian Campbell, Stefano Stabellini, Tim Deegan
Cc: zoltan.kiss, xen-devel
Hello Frediano,
On 03/03/15 11:19, Frediano Ziglio wrote:
> The GIC in this platform is mainly compatible with the standard
> GICv2 beside:
> - ITARGET is extended to 16 bit to support 16 CPUs;
> - SGI mask is extended to support 16 CPUs;
> - maximum supported interrupt is 510;
510 is not a multiple of 32. Is it normal?
This will result to having nr_lines = 512. What happen is we are trying
to access IRQ 510 and 511?
Also, is it possible to have GICH.VirtualID >= 510?
> - GICH APR and LR register offsets.
>
> Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
> Signed-off-by: Zoltan Kiss <zoltan.kiss@huawei.com>
> ---
> MAINTAINERS | 5 +
> xen/arch/arm/Makefile | 1 +
> xen/arch/arm/gic-hip04.c | 396 ++++++++++++++++++++++++-----------------------
> 3 files changed, 209 insertions(+), 193 deletions(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0f04742..b17aab1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -138,6 +138,11 @@ F: xen/drivers/char/omap-uart.c
> F: xen/drivers/char/pl011.c
> F: xen/drivers/passthrough/arm/
>
> +HISILICON HIP04 SUPPORT
> +M: Frediano Ziglio <frediano.ziglio@huawei.com>
It might be good to have 2 maintainers form Huawei on this file. Ian any
though?
> +S: Supported
> +F: xen/arch/arm/git-hip04.c
gic-hip04.c
> +
> CPU POOLS
> M: Juergen Gross <jgross@suse.com>
> S: Supported
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 41aba2e..935999e 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -12,6 +12,7 @@ obj-y += domctl.o
> obj-y += sysctl.o
> obj-y += domain_build.o
> obj-y += gic.o gic-v2.o
> +obj-$(CONFIG_ARM_32) += gic-hip04.o
> obj-$(CONFIG_ARM_64) += gic-v3.o
> obj-y += io.o
> obj-y += irq.o
> diff --git a/xen/arch/arm/gic-hip04.c b/xen/arch/arm/gic-hip04.c
> index 20cdbc9..94abdc4 100644
> --- a/xen/arch/arm/gic-hip04.c
> +++ b/xen/arch/arm/gic-hip04.c
> @@ -1,7 +1,8 @@
> /*
> - * xen/arch/arm/gic-v2.c
> + * xen/arch/arm/gic-hip04.c
> *
> - * ARM Generic Interrupt Controller support v2
> + * Generic Interrupt Controller for HiSilicon Hip04 platform
> + * Based heavily from gic-v2.c
Please add a commit ID. It would help you to keep track of the GIC.
> *
> * Tim Deegan <tim@xen.org>
> * Copyright (c) 2011 Citrix Systems.
> @@ -71,59 +72,69 @@ static struct {
> void __iomem * map_hbase; /* IO Address of virtual interface registers */
> paddr_t vbase; /* Address of virtual cpu interface registers */
> spinlock_t lock;
> -} gicv2;
> +} hip04gic;
>
> -static struct gic_info gicv2_info;
> +static struct gic_info hip04gic_info;
I think the renaming of gicv2 and gicv2_info is pointless here. Instead
of function name, it doesn't help for debugging.
It would also reduce the diff of this patch.
[..]
> -DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
> - .dt_match = gicv2_dt_match,
> - .init = gicv2_init,
> +DT_DEVICE_START(hip04gic, "GIC-HIP04", DEVICE_GIC)
> + .dt_match = hip04gic_dt_match,
> + .init = hip04gic_init,
> DT_DEVICE_END
Please keep the same indentation as before.
Regards,
--
Julien Grall
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 2/4] xen/arm: Check for interrupt controller directly
2015-03-03 15:07 ` Frediano Ziglio
@ 2015-03-03 15:10 ` Julien Grall
0 siblings, 0 replies; 18+ messages in thread
From: Julien Grall @ 2015-03-03 15:10 UTC (permalink / raw)
To: Frediano Ziglio
Cc: Zoltan Kiss, Ian Campbell, Tim Deegan, Xen-devel, Frediano Ziglio,
Stefano Stabellini
On 03/03/15 15:07, Frediano Ziglio wrote:
> 2015-03-03 14:45 GMT+00:00 Julien Grall <julien.grall@linaro.org>:
>> Hello Frediano,
>>
>> On 03/03/15 11:19, Frediano Ziglio wrote:
>>> This check allow to detect mail interrupt controller even if it does
>>
>> main
>>
>>> not match one of the standard ones.
>>> This allow boards with non standard controllers to be handled correctly
>>> without having to manually edit the global list every time.
>>>
>>> Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
>>> ---
>>> xen/arch/arm/domain_build.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>>> index 9f1f59f..83951a3 100644
>>> --- a/xen/arch/arm/domain_build.c
>>> +++ b/xen/arch/arm/domain_build.c
>>> @@ -1069,7 +1069,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
>>>
>>> /* Replace these nodes with our own. Note that the original may be
>>> * used_by DOMID_XEN so this check comes first. */
>>> - if ( dt_match_node(gic_matches, node) )
>>> + if ( node == dt_interrupt_controller || dt_match_node(gic_matches, node) )
>>> return make_gic_node(d, kinfo->fdt, node);
>>
>> What about if the device tree exposes multiple GICs? By mistake we will
>> expose the secondaries GIC if they are not standard.
>>
>> As I suggested on a previous mail, I would prefer to introduce a new
>> callback to check if the node is a GIC.
>>
>
> I think something like this would make all happy (I hope, I tested and
> works correctly on my board):
This looks good to me.
Regards,
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 9f1f59f..aaa3b97 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1035,12 +1035,6 @@ static int handle_node(struct domain *d, struct
> kernel_info *kinfo,
> DT_MATCH_COMPATIBLE("arm,armv7-timer-mem"),
> { /* sentinel */ },
> };
> - static const struct dt_device_match gic_matches[] __initconst =
> - {
> - DT_MATCH_GIC_V2,
> - DT_MATCH_GIC_V3,
> - { /* sentinel */ },
> - };
> static const struct dt_device_match timer_matches[] __initconst =
> {
> DT_MATCH_TIMER,
> @@ -1069,7 +1063,7 @@ static int handle_node(struct domain *d, struct
> kernel_info *kinfo,
>
> /* Replace these nodes with our own. Note that the original may be
> * used_by DOMID_XEN so this check comes first. */
> - if ( dt_match_node(gic_matches, node) )
> + if ( device_get_class(node) == DEVICE_GIC )
> return make_gic_node(d, kinfo->fdt, node);
> if ( dt_match_node(timer_matches, node) )
> return make_timer_node(d, kinfo->fdt, node);
>
--
Julien Grall
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 3/4] xen/arm: Make gic-v2 code handle hip04-d01 platform
2015-03-03 15:07 ` Julien Grall
@ 2015-03-03 15:36 ` Frediano Ziglio
2015-03-03 15:42 ` Julien Grall
0 siblings, 1 reply; 18+ messages in thread
From: Frediano Ziglio @ 2015-03-03 15:36 UTC (permalink / raw)
To: Julien Grall, Ian Campbell, Stefano Stabellini, Tim Deegan
Cc: Zoltan Kiss, xen-devel@lists.xen.org
>
> Hello Frediano,
>
> On 03/03/15 11:19, Frediano Ziglio wrote:
> > The GIC in this platform is mainly compatible with the standard
> > GICv2 beside:
> > - ITARGET is extended to 16 bit to support 16 CPUs;
> > - SGI mask is extended to support 16 CPUs;
> > - maximum supported interrupt is 510;
>
> 510 is not a multiple of 32. Is it normal?
>
> This will result to having nr_lines = 512. What happen is we are trying
> to access IRQ 510 and 511?
>
I don't know. I think it's the same reason why in xen/arch/arm/gic.c the limit for irq is 1021 and not 1024 (see "if ( likely(irq >= 16 && irq < 1021) )" line)
> Also, is it possible to have GICH.VirtualID >= 510?
>
I think so, GICH have the same interface of normal GICv2.
...
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS index 0f04742..b17aab1 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -138,6 +138,11 @@ F: xen/drivers/char/omap-uart.c
> > F: xen/drivers/char/pl011.c
> > F: xen/drivers/passthrough/arm/
> >
> > +HISILICON HIP04 SUPPORT
> > +M: Frediano Ziglio <frediano.ziglio@huawei.com>
>
> It might be good to have 2 maintainers form Huawei on this file. Ian
> any though?
>
Added Zoltan Kiss.
> > +S: Supported
> > +F: xen/arch/arm/git-hip04.c
>
> gic-hip04.c
>
Too many git commands :)
...
> > 20cdbc9..94abdc4 100644
> > --- a/xen/arch/arm/gic-hip04.c
> > +++ b/xen/arch/arm/gic-hip04.c
> > @@ -1,7 +1,8 @@
> > /*
> > - * xen/arch/arm/gic-v2.c
> > + * xen/arch/arm/gic-hip04.c
> > *
> > - * ARM Generic Interrupt Controller support v2
> > + * Generic Interrupt Controller for HiSilicon Hip04 platform
> > + * Based heavily from gic-v2.c
>
> Please add a commit ID. It would help you to keep track of the GIC.
>
> > *
> > * Tim Deegan <tim@xen.org>
> > * Copyright (c) 2011 Citrix Systems.
> > @@ -71,59 +72,69 @@ static struct {
> > void __iomem * map_hbase; /* IO Address of virtual interface
> registers */
> > paddr_t vbase; /* Address of virtual cpu interface
> registers */
> > spinlock_t lock;
> > -} gicv2;
> > +} hip04gic;
> >
> > -static struct gic_info gicv2_info;
> > +static struct gic_info hip04gic_info;
>
> I think the renaming of gicv2 and gicv2_info is pointless here. Instead
> of function name, it doesn't help for debugging.
>
> It would also reduce the diff of this patch.
>
No problem
> [..]
>
> > -DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
> > - .dt_match = gicv2_dt_match,
> > - .init = gicv2_init,
> > +DT_DEVICE_START(hip04gic, "GIC-HIP04", DEVICE_GIC)
> > + .dt_match = hip04gic_dt_match,
> > + .init = hip04gic_init,
> > DT_DEVICE_END
>
> Please keep the same indentation as before.
>
I was wondering why the indentation is different. Ok
Frediano
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 3/4] xen/arm: Make gic-v2 code handle hip04-d01 platform
2015-03-03 15:36 ` Frediano Ziglio
@ 2015-03-03 15:42 ` Julien Grall
2015-03-05 9:31 ` Frediano Ziglio
0 siblings, 1 reply; 18+ messages in thread
From: Julien Grall @ 2015-03-03 15:42 UTC (permalink / raw)
To: Frediano Ziglio, Ian Campbell, Stefano Stabellini, Tim Deegan
Cc: Zoltan Kiss, xen-devel@lists.xen.org
On 03/03/15 15:36, Frediano Ziglio wrote:
>>
>> Hello Frediano,
>>
>> On 03/03/15 11:19, Frediano Ziglio wrote:
>>> The GIC in this platform is mainly compatible with the standard
>>> GICv2 beside:
>>> - ITARGET is extended to 16 bit to support 16 CPUs;
>>> - SGI mask is extended to support 16 CPUs;
>>> - maximum supported interrupt is 510;
>>
>> 510 is not a multiple of 32. Is it normal?
>>
>> This will result to having nr_lines = 512. What happen is we are trying
>> to access IRQ 510 and 511?
>>
>
> I don't know. I think it's the same reason why in xen/arch/arm/gic.c the limit for irq is 1021 and not 1024 (see "if ( likely(irq >= 16 && irq < 1021) )" line)
IRQ 1021-1023 are reserved by the GIC as spurious interrupt.
If I understand correctly what you say, IRQ 510-511 may be considered
for spurious interrupt?
If so, the check (irq >= 16 && irq < 1021) needs to be changed.
>> Also, is it possible to have GICH.VirtualID >= 510?
>>
>
> I think so, GICH have the same interface of normal GICv2.
But some offsets are different... so I'd like a confirmation based on
some spec.
For instance on GICv2 if we use some VirtualID (1021-1023) the behavior
is unpredictable.
So if you have the a similar things on your board we may need to
restrict the number of VirtualID in order to avoid introduce a possible
host denial from a guest.
>> [..]
>>
>>> -DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
>>> - .dt_match = gicv2_dt_match,
>>> - .init = gicv2_init,
>>> +DT_DEVICE_START(hip04gic, "GIC-HIP04", DEVICE_GIC)
>>> + .dt_match = hip04gic_dt_match,
>>> + .init = hip04gic_init,
>>> DT_DEVICE_END
>>
>> Please keep the same indentation as before.
>>
>
> I was wondering why the indentation is different. Ok
I'm not sure why ... but it looks like we use the same indentation
everywhere for DT_DEVICE_START.
Regards,
--
Julien Grall
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 3/4] xen/arm: Make gic-v2 code handle hip04-d01 platform
2015-03-03 15:42 ` Julien Grall
@ 2015-03-05 9:31 ` Frediano Ziglio
2015-03-05 10:36 ` Julien Grall
0 siblings, 1 reply; 18+ messages in thread
From: Frediano Ziglio @ 2015-03-05 9:31 UTC (permalink / raw)
To: Julien Grall
Cc: Zoltan Kiss, Ian Campbell, Tim Deegan, xen-devel@lists.xen.org,
Frediano Ziglio, Stefano Stabellini
2015-03-03 15:42 GMT+00:00 Julien Grall <julien.grall@linaro.org>:
> On 03/03/15 15:36, Frediano Ziglio wrote:
>>>
>>> Hello Frediano,
>>>
>>> On 03/03/15 11:19, Frediano Ziglio wrote:
>>>> The GIC in this platform is mainly compatible with the standard
>>>> GICv2 beside:
>>>> - ITARGET is extended to 16 bit to support 16 CPUs;
>>>> - SGI mask is extended to support 16 CPUs;
>>>> - maximum supported interrupt is 510;
>>>
>>> 510 is not a multiple of 32. Is it normal?
>>>
>>> This will result to having nr_lines = 512. What happen is we are trying
>>> to access IRQ 510 and 511?
>>>
>>
>> I don't know. I think it's the same reason why in xen/arch/arm/gic.c the limit for irq is 1021 and not 1024 (see "if ( likely(irq >= 16 && irq < 1021) )" line)
>
> IRQ 1021-1023 are reserved by the GIC as spurious interrupt.
>
> If I understand correctly what you say, IRQ 510-511 may be considered
> for spurious interrupt?
>
> If so, the check (irq >= 16 && irq < 1021) needs to be changed.
>
>>> Also, is it possible to have GICH.VirtualID >= 510?
>>>
>>
>> I think so, GICH have the same interface of normal GICv2.
>
> But some offsets are different... so I'd like a confirmation based on
> some spec.
>
You can find spec at https://github.com/hisilicon/boards/tree/master/D01/docs.
Yes, VirtualID >= 510 can be used.
> For instance on GICv2 if we use some VirtualID (1021-1023) the behavior
> is unpredictable.
>
Same for our GIC.
> So if you have the a similar things on your board we may need to
> restrict the number of VirtualID in order to avoid introduce a possible
> host denial from a guest.
>
Frediano
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 3/4] xen/arm: Make gic-v2 code handle hip04-d01 platform
2015-03-05 9:31 ` Frediano Ziglio
@ 2015-03-05 10:36 ` Julien Grall
0 siblings, 0 replies; 18+ messages in thread
From: Julien Grall @ 2015-03-05 10:36 UTC (permalink / raw)
To: Frediano Ziglio
Cc: Zoltan Kiss, Ian Campbell, Tim Deegan, xen-devel@lists.xen.org,
Frediano Ziglio, Stefano Stabellini
Hello,
On 05/03/2015 09:31, Frediano Ziglio wrote:
>> But some offsets are different... so I'd like a confirmation based on
>> some spec.
>>
>
> You can find spec at https://github.com/hisilicon/boards/tree/master/D01/docs.
The spec is in Chinese... Any chance to have an English version?
Regards,
--
Julien Grall
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 2/4] xen/arm: Check for interrupt controller directly
2015-03-03 14:45 ` Julien Grall
2015-03-03 15:07 ` Frediano Ziglio
@ 2015-03-05 16:36 ` Ian Campbell
2015-03-09 10:55 ` Julien Grall
1 sibling, 1 reply; 18+ messages in thread
From: Ian Campbell @ 2015-03-05 16:36 UTC (permalink / raw)
To: Julien Grall
Cc: Frediano Ziglio, Tim Deegan, xen-devel, Stefano Stabellini,
zoltan.kiss
On Tue, 2015-03-03 at 14:45 +0000, Julien Grall wrote:
> Hello Frediano,
>
> On 03/03/15 11:19, Frediano Ziglio wrote:
> > This check allow to detect mail interrupt controller even if it does
>
> main
>
> > not match one of the standard ones.
> > This allow boards with non standard controllers to be handled correctly
> > without having to manually edit the global list every time.
> >
> > Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
> > ---
> > xen/arch/arm/domain_build.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 9f1f59f..83951a3 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -1069,7 +1069,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
> >
> > /* Replace these nodes with our own. Note that the original may be
> > * used_by DOMID_XEN so this check comes first. */
> > - if ( dt_match_node(gic_matches, node) )
> > + if ( node == dt_interrupt_controller || dt_match_node(gic_matches, node) )
> > return make_gic_node(d, kinfo->fdt, node);
>
> What about if the device tree exposes multiple GICs? By mistake we will
> expose the secondaries GIC if they are not standard.
Does the existing code here not insert a primary gic node into the dom0
tree for every gic node which find, that doesn't sound like it can be
right!
Is the right pattern:
if ( node == dt_interrupt_controller )
return make_gic_node(d, kinfo->fdt, node);
else if ( device_get_class(node) == DEVICE_GIC )
{
DPRINT(" Secondary GIC, skip it\n");
return 0;/* Skip it */
}
(incorporating the suggestion to match class from further down thread)?
Anyway, I don't think what Frediano proposes in v9 of this series makes
any of this worse, so I don't propose to block the series based on it.
>
> As I suggested on a previous mail, I would prefer to introduce a new
> callback to check if the node is a GIC.
>
> Regards,
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 2/4] xen/arm: Check for interrupt controller directly
2015-03-05 16:36 ` Ian Campbell
@ 2015-03-09 10:55 ` Julien Grall
2015-03-09 16:08 ` Ian Campbell
0 siblings, 1 reply; 18+ messages in thread
From: Julien Grall @ 2015-03-09 10:55 UTC (permalink / raw)
To: Ian Campbell
Cc: Frediano Ziglio, Tim Deegan, xen-devel, Stefano Stabellini,
zoltan.kiss
On 05/03/2015 18:36, Ian Campbell wrote:
> On Tue, 2015-03-03 at 14:45 +0000, Julien Grall wrote:
>> Hello Frediano,
>>
>> On 03/03/15 11:19, Frediano Ziglio wrote:
>>> This check allow to detect mail interrupt controller even if it does
>>
>> main
>>
>>> not match one of the standard ones.
>>> This allow boards with non standard controllers to be handled correctly
>>> without having to manually edit the global list every time.
>>>
>>> Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
>>> ---
>>> xen/arch/arm/domain_build.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>>> index 9f1f59f..83951a3 100644
>>> --- a/xen/arch/arm/domain_build.c
>>> +++ b/xen/arch/arm/domain_build.c
>>> @@ -1069,7 +1069,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
>>>
>>> /* Replace these nodes with our own. Note that the original may be
>>> * used_by DOMID_XEN so this check comes first. */
>>> - if ( dt_match_node(gic_matches, node) )
>>> + if ( node == dt_interrupt_controller || dt_match_node(gic_matches, node) )
>>> return make_gic_node(d, kinfo->fdt, node);
>>
>> What about if the device tree exposes multiple GICs? By mistake we will
>> expose the secondaries GIC if they are not standard.
>
> Does the existing code here not insert a primary gic node into the dom0
> tree for every gic node which find, that doesn't sound like it can be
> right!
The current code doesn't insert any secondary gic (see the check in
make_gic_node) in the DT.
With this version of the patch secondary gics was added to the DOM0
DT
> Is the right pattern:
> if ( node == dt_interrupt_controller )
> return make_gic_node(d, kinfo->fdt, node);
> else if ( device_get_class(node) == DEVICE_GIC )
> {
> DPRINT(" Secondary GIC, skip it\n");
> return 0;/* Skip it */
> }
> (incorporating the suggestion to match class from further down thread)?
>
> Anyway, I don't think what Frediano proposes in v9 of this series makes
> any of this worse, so I don't propose to block the series based on it.
The solution on the v9 was the right one.
I though I sent an email to review it but it looks like not :/
Regards,
--
Julien Grall
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 2/4] xen/arm: Check for interrupt controller directly
2015-03-09 10:55 ` Julien Grall
@ 2015-03-09 16:08 ` Ian Campbell
2015-03-09 16:41 ` Frediano Ziglio
0 siblings, 1 reply; 18+ messages in thread
From: Ian Campbell @ 2015-03-09 16:08 UTC (permalink / raw)
To: Julien Grall
Cc: Frediano Ziglio, Tim Deegan, xen-devel, Stefano Stabellini,
zoltan.kiss
On Mon, 2015-03-09 at 12:55 +0200, Julien Grall wrote:
>
> On 05/03/2015 18:36, Ian Campbell wrote:
> > On Tue, 2015-03-03 at 14:45 +0000, Julien Grall wrote:
> >> Hello Frediano,
> >>
> >> On 03/03/15 11:19, Frediano Ziglio wrote:
> >>> This check allow to detect mail interrupt controller even if it does
> >>
> >> main
> >>
> >>> not match one of the standard ones.
> >>> This allow boards with non standard controllers to be handled correctly
> >>> without having to manually edit the global list every time.
> >>>
> >>> Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
> >>> ---
> >>> xen/arch/arm/domain_build.c | 2 +-
> >>> 1 file changed, 1 insertion(+), 1 deletion(-)
> >>>
> >>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> >>> index 9f1f59f..83951a3 100644
> >>> --- a/xen/arch/arm/domain_build.c
> >>> +++ b/xen/arch/arm/domain_build.c
> >>> @@ -1069,7 +1069,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
> >>>
> >>> /* Replace these nodes with our own. Note that the original may be
> >>> * used_by DOMID_XEN so this check comes first. */
> >>> - if ( dt_match_node(gic_matches, node) )
> >>> + if ( node == dt_interrupt_controller || dt_match_node(gic_matches, node) )
> >>> return make_gic_node(d, kinfo->fdt, node);
> >>
> >> What about if the device tree exposes multiple GICs? By mistake we will
> >> expose the secondaries GIC if they are not standard.
> >
> > Does the existing code here not insert a primary gic node into the dom0
> > tree for every gic node which find, that doesn't sound like it can be
> > right!
>
> The current code doesn't insert any secondary gic (see the check in
> make_gic_node) in the DT.
Ah, I missed that, yes that would avoid the issue for sure.
> With this version of the patch secondary gics was added to the DOM0
> DT
How? Does that same check in make_gic_node not prevent it?
> > Is the right pattern:
> > if ( node == dt_interrupt_controller )
> > return make_gic_node(d, kinfo->fdt, node);
> > else if ( device_get_class(node) == DEVICE_GIC )
> > {
> > DPRINT(" Secondary GIC, skip it\n");
> > return 0;/* Skip it */
> > }
> > (incorporating the suggestion to match class from further down thread)?
> >
> > Anyway, I don't think what Frediano proposes in v9 of this series makes
> > any of this worse, so I don't propose to block the series based on it.
>
> The solution on the v9 was the right one.
Good.
> I though I sent an email to review it but it looks like not :/
I don't recall seeing it.
Ian.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 2/4] xen/arm: Check for interrupt controller directly
2015-03-09 16:08 ` Ian Campbell
@ 2015-03-09 16:41 ` Frediano Ziglio
2015-03-09 17:03 ` Ian Campbell
0 siblings, 1 reply; 18+ messages in thread
From: Frediano Ziglio @ 2015-03-09 16:41 UTC (permalink / raw)
To: Ian Campbell, Julien Grall
Cc: Tim Deegan, xen-devel@lists.xen.org, Stefano Stabellini,
Zoltan Kiss
> From: Ian Campbell [mailto:ian.campbell@citrix.com]
> Sent: Monday, March 09, 2015 4:09 PM
>
> On Mon, 2015-03-09 at 12:55 +0200, Julien Grall wrote:
> >
> > On 05/03/2015 18:36, Ian Campbell wrote:
> > > On Tue, 2015-03-03 at 14:45 +0000, Julien Grall wrote:
> > >> Hello Frediano,
> > >>
> > >> On 03/03/15 11:19, Frediano Ziglio wrote:
> > >>> This check allow to detect mail interrupt controller even if it
> > >>> does
> > >>
> > >> main
> > >>
> > >>> not match one of the standard ones.
> > >>> This allow boards with non standard controllers to be handled
> > >>> correctly without having to manually edit the global list every
> time.
> > >>>
> > >>> Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
> > >>> ---
> > >>> xen/arch/arm/domain_build.c | 2 +-
> > >>> 1 file changed, 1 insertion(+), 1 deletion(-)
> > >>>
> > >>> diff --git a/xen/arch/arm/domain_build.c
> > >>> b/xen/arch/arm/domain_build.c index 9f1f59f..83951a3 100644
> > >>> --- a/xen/arch/arm/domain_build.c
> > >>> +++ b/xen/arch/arm/domain_build.c
> > >>> @@ -1069,7 +1069,7 @@ static int handle_node(struct domain *d,
> > >>> struct kernel_info *kinfo,
> > >>>
> > >>> /* Replace these nodes with our own. Note that the original
> may be
> > >>> * used_by DOMID_XEN so this check comes first. */
> > >>> - if ( dt_match_node(gic_matches, node) )
> > >>> + if ( node == dt_interrupt_controller ||
> > >>> + dt_match_node(gic_matches, node) )
> > >>> return make_gic_node(d, kinfo->fdt, node);
> > >>
> > >> What about if the device tree exposes multiple GICs? By mistake we
> > >> will expose the secondaries GIC if they are not standard.
> > >
> > > Does the existing code here not insert a primary gic node into the
> > > dom0 tree for every gic node which find, that doesn't sound like it
> > > can be right!
> >
> > The current code doesn't insert any secondary gic (see the check in
> > make_gic_node) in the DT.
>
> Ah, I missed that, yes that would avoid the issue for sure.
>
I'm wondering if the final results can always work. I mean, a bare metal kernel will see all interrupt controllers while under Xen kernel receive only the primary one (virtualized). Now the question is "What are topology of secondary controllers?" I mean if a device is supposed so send some interrupt throw a secondary controller and nor kernel nor xen handle this device we lose the ability to use interrupts from this device?
> > With this version of the patch secondary gics was added to the DOM0
> DT
>
> How? Does that same check in make_gic_node not prevent it?
>
> > > Is the right pattern:
> > > if ( node == dt_interrupt_controller )
> > > return make_gic_node(d, kinfo->fdt, node);
> > > else if ( device_get_class(node) == DEVICE_GIC )
> > > {
> > > DPRINT(" Secondary GIC, skip it\n");
> > > return 0;/* Skip it */
> > > }
> > > (incorporating the suggestion to match class from further down
> thread)?
> > >
> > > Anyway, I don't think what Frediano proposes in v9 of this series
> > > makes any of this worse, so I don't propose to block the series
> based on it.
> >
> > The solution on the v9 was the right one.
>
> Good.
>
> > I though I sent an email to review it but it looks like not :/
>
> I don't recall seeing it.
>
I remember something about. What this perhaps (http://lists.xenproject.org/archives/html/xen-devel/2015-03/msg00396.html) ?
Frediano
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v8 2/4] xen/arm: Check for interrupt controller directly
2015-03-09 16:41 ` Frediano Ziglio
@ 2015-03-09 17:03 ` Ian Campbell
0 siblings, 0 replies; 18+ messages in thread
From: Ian Campbell @ 2015-03-09 17:03 UTC (permalink / raw)
To: Frediano Ziglio
Cc: Stefano Stabellini, Julien Grall, Tim Deegan, Zoltan Kiss,
xen-devel@lists.xen.org
On Mon, 2015-03-09 at 16:41 +0000, Frediano Ziglio wrote:
> > From: Ian Campbell [mailto:ian.campbell@citrix.com]
> > Sent: Monday, March 09, 2015 4:09 PM
> >
> > On Mon, 2015-03-09 at 12:55 +0200, Julien Grall wrote:
> > >
> > > On 05/03/2015 18:36, Ian Campbell wrote:
> > > > On Tue, 2015-03-03 at 14:45 +0000, Julien Grall wrote:
> > > >> Hello Frediano,
> > > >>
> > > >> On 03/03/15 11:19, Frediano Ziglio wrote:
> > > >>> This check allow to detect mail interrupt controller even if it
> > > >>> does
> > > >>
> > > >> main
> > > >>
> > > >>> not match one of the standard ones.
> > > >>> This allow boards with non standard controllers to be handled
> > > >>> correctly without having to manually edit the global list every
> > time.
> > > >>>
> > > >>> Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
> > > >>> ---
> > > >>> xen/arch/arm/domain_build.c | 2 +-
> > > >>> 1 file changed, 1 insertion(+), 1 deletion(-)
> > > >>>
> > > >>> diff --git a/xen/arch/arm/domain_build.c
> > > >>> b/xen/arch/arm/domain_build.c index 9f1f59f..83951a3 100644
> > > >>> --- a/xen/arch/arm/domain_build.c
> > > >>> +++ b/xen/arch/arm/domain_build.c
> > > >>> @@ -1069,7 +1069,7 @@ static int handle_node(struct domain *d,
> > > >>> struct kernel_info *kinfo,
> > > >>>
> > > >>> /* Replace these nodes with our own. Note that the original
> > may be
> > > >>> * used_by DOMID_XEN so this check comes first. */
> > > >>> - if ( dt_match_node(gic_matches, node) )
> > > >>> + if ( node == dt_interrupt_controller ||
> > > >>> + dt_match_node(gic_matches, node) )
> > > >>> return make_gic_node(d, kinfo->fdt, node);
> > > >>
> > > >> What about if the device tree exposes multiple GICs? By mistake we
> > > >> will expose the secondaries GIC if they are not standard.
> > > >
> > > > Does the existing code here not insert a primary gic node into the
> > > > dom0 tree for every gic node which find, that doesn't sound like it
> > > > can be right!
> > >
> > > The current code doesn't insert any secondary gic (see the check in
> > > make_gic_node) in the DT.
> >
> > Ah, I missed that, yes that would avoid the issue for sure.
> >
>
> I'm wondering if the final results can always work. I mean, a bare
> metal kernel will see all interrupt controllers while under Xen kernel
> receive only the primary one (virtualized). Now the question is "What
> are topology of secondary controllers?" I mean if a device is supposed
> so send some interrupt throw a secondary controller and nor kernel nor
> xen handle this device we lose the ability to use interrupts from this
> device?
I've never yet seen a GICv2+ system which had multiple interrupt
controllers. Do you know of one?
My gut feeling is that the need to chain GICs was a feature of the GICv1
which isn't virt capable so we don't care much about it.
Ian.
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2015-03-09 17:03 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-03 11:19 [PATCH v8 0/4] xen/arm: Add support for Huawei hip04-d01 platform Frediano Ziglio
2015-03-03 11:19 ` [PATCH v8 1/4] xen/arm: Duplicate gic-v2.c file to support hip04 platform version Frediano Ziglio
2015-03-03 11:19 ` [PATCH v8 2/4] xen/arm: Check for interrupt controller directly Frediano Ziglio
2015-03-03 14:45 ` Julien Grall
2015-03-03 15:07 ` Frediano Ziglio
2015-03-03 15:10 ` Julien Grall
2015-03-05 16:36 ` Ian Campbell
2015-03-09 10:55 ` Julien Grall
2015-03-09 16:08 ` Ian Campbell
2015-03-09 16:41 ` Frediano Ziglio
2015-03-09 17:03 ` Ian Campbell
2015-03-03 11:19 ` [PATCH v8 3/4] xen/arm: Make gic-v2 code handle hip04-d01 platform Frediano Ziglio
2015-03-03 15:07 ` Julien Grall
2015-03-03 15:36 ` Frediano Ziglio
2015-03-03 15:42 ` Julien Grall
2015-03-05 9:31 ` Frediano Ziglio
2015-03-05 10:36 ` Julien Grall
2015-03-03 11:19 ` [PATCH v8 4/4] xen/arm: Force dom0 to use normal GICv2 driver on Hip04 platform Frediano Ziglio
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.