All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15
@ 2012-01-13 20:52 Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 01/12] vexpress, realview: Add (dummy) L2 cache controller Peter Maydell
                   ` (12 more replies)
  0 siblings, 13 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

This patchset adds support for (a rather limited version of) the
Cortex-A15 CPU and the Versatile Express A15 daughterboard.
The resulting model is capable of booting a Linux kernel which has
been configured for Cortex-A15 with the Versatile Express "extended
memory map" and without support for LPAE.

The series includes three patches at the start which have been
on the list already but which this series depends on:
 * arm: make the number of GIC interrupts configurable
 * vexpress, realview: Add (dummy) L2 cache controller
 * hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop
The first two of these are already queued in my arm-devs.next;
the arm_boot.c patch is in the Exynos4 patchset but is one of the
reviewed and good-to-go ones. [Evgeny: you should keep the arm_boot.c
patch in your patchset until/unless it makes it into master.]
Basically I've included these for convenience of anybody who wants
to test this patchset; I'm assuming this set will need a v2 and
that in the meantime the dependencies will make their way into
master. But I just got this all working this week so I thought
I'd put the whole thing up for review before I went home for the
week :-)

PS for the folk on android-virt: I haven't yet tested these patches
with KVM, only with TCG, but there is no inherent reason for them
not to work...

Evgeny Voevodin (1):
  hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop

Mark Langsdorf (1):
  arm: make the number of GIC interrupts configurable

Peter Maydell (10):
  vexpress, realview: Add (dummy) L2 cache controller
  hw/vexpress.c: Make motherboard peripheral memory map table-driven
  hw/vexpress.c: Move secondary CPU boot code to SRAM
  hw/vexpress.c: Factor out daughterboard-specific initialization
  hw/vexpress.c: Instantiate the motherboard CLCD
  hw/a15mpcore.c: Add Cortex-A15 private peripheral model
  Add dummy implementation of generic timer cp15 registers
  Add Cortex-A15 CPU definition
  arm_boot: Pass base address of GIC CPU interface, not whole GIC
  hw/vexpress.c: Add vexpress-a15 machine

 Makefile.target     |    2 +-
 hw/a15mpcore.c      |   93 ++++++++++++
 hw/a9mpcore.c       |   13 ++-
 hw/arm-misc.h       |    3 +-
 hw/arm11mpcore.c    |   17 ++-
 hw/arm_boot.c       |   18 ++-
 hw/arm_gic.c        |   68 +++++----
 hw/armv7m_nvic.c    |   31 +++-
 hw/realview.c       |   12 +-
 hw/realview_gic.c   |    7 +-
 hw/vexpress.c       |  407 +++++++++++++++++++++++++++++++++++++++++----------
 target-arm/cpu.h    |    2 +
 target-arm/helper.c |   68 ++++++++-
 13 files changed, 594 insertions(+), 147 deletions(-)
 create mode 100644 hw/a15mpcore.c

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

* [Qemu-devel] [PATCH 01/12] vexpress, realview: Add (dummy) L2 cache controller
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 02/12] arm: make the number of GIC interrupts configurable Peter Maydell
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

Instantiate the L2 cache controller on the ARM devboards which have one,
since we have a dummy model of it now. Note that the only non-MP board
with an L2x0 is the PB1176, which we don't model.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/realview.c |    2 ++
 hw/vexpress.c |    1 +
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/hw/realview.c b/hw/realview.c
index d4191e9..e52babc 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -225,6 +225,8 @@ static void realview_init(ram_addr_t ram_size,
         for (n = 0; n < smp_cpus; n++) {
             sysbus_connect_irq(busdev, n, cpu_irq[n]);
         }
+        sysbus_create_varargs("l2x0", realview_binfo.smp_priv_base + 0x2000,
+                              NULL);
     } else {
         uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000;
         /* For now just create the nIRQ GIC, and ignore the others.  */
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 0f39d8d..613be65 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -180,6 +180,7 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     /* 0x100ec000 TrustZone Address Space Controller */
     /* 0x10200000 CoreSight debug APB */
     /* 0x1e00a000 PL310 L2 Cache Controller */
+    sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
 
     /* CS0: NOR0 flash          : 0x40000000 .. 0x44000000 */
     /* CS4: NOR1 flash          : 0x44000000 .. 0x48000000 */
-- 
1.7.1

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

* [Qemu-devel] [PATCH 02/12] arm: make the number of GIC interrupts configurable
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 01/12] vexpress, realview: Add (dummy) L2 cache controller Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-24  8:42   ` [Qemu-devel] [Android-virt] " Rusty Russell
  2012-02-21  2:33   ` [Qemu-devel] [PATCH 2/2] " Rusty Russell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop Peter Maydell
                   ` (10 subsequent siblings)
  12 siblings, 2 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

From: Mark Langsdorf <mark.langsdorf@calxeda.com>

Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
and create a configurable property for each defaulting to 96 and 64
(respectively) so that device modelers can set the value appropriately
for their SoC. Other ARM processors also set their maximum number of
used IRQs appropriately.

Set the maximum theoretical number of GIC interrupts to 1020 and
update the save/restore code to only use the appropriate number for
each SoC.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
[Peter Maydell: fixed minor whitespace snafu]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/a9mpcore.c     |   13 +++++++--
 hw/arm11mpcore.c  |   17 ++++++++----
 hw/arm_gic.c      |   68 +++++++++++++++++++++++++++++-----------------------
 hw/armv7m_nvic.c  |   31 ++++++++++++++++++------
 hw/realview_gic.c |    7 ++++-
 5 files changed, 87 insertions(+), 49 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..521b8cc 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,9 +11,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ * max number of CPUs, how to ID current CPU
  */
-#define GIC_NIRQ 96
 #define NCPU 4
 
 static inline int
@@ -37,6 +36,7 @@ typedef struct a9mp_priv_state {
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } a9mp_priv_state;
 
 static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -153,7 +153,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
     }
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -216,6 +216,13 @@ static SysBusDeviceInfo a9mp_priv_info = {
     .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+        /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
+         * IRQ lines (with another 32 internal). We default to 64+32, which
+         * is the number provided by the Cortex-A9MP test chip in the
+         * Realview PBX-A9 and Versatile Express A9 development boards.
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e..f4d88dc 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,11 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
-   (+ 32 internal).  However my test chip only exposes/reports 32.
-   More importantly Linux falls over if more than 32 are present!  */
-#define GIC_NIRQ 64
-
 #define NCPU 4
 
 static inline int
@@ -37,6 +32,7 @@ typedef struct mpcore_priv_state {
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } mpcore_priv_state;
 
 /* Per-CPU private memory mapped IO.  */
@@ -132,7 +128,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
@@ -221,6 +217,15 @@ static SysBusDeviceInfo mpcore_priv_info = {
     .qdev.size  = sizeof(mpcore_priv_state),
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        /* The ARM11 MPCORE TRM says the on-chip controller may have
+         * anything from 0 to 224 external interrupt IRQ lines (with another
+         * 32 internal). We default to 32+32, which is the number provided by
+         * the ARM11 MPCore test chip in the Realview Versatile Express
+         * coretile. Other boards may differ and should set this property
+         * appropriately. Some Linux kernels may not boot if the hardware
+         * has more IRQ lines than the kernel expects.
+         */
+        DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..cf582a5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,8 @@
    controller, MPCore distributed interrupt controller and ARMv7-M
    Nested Vectored Interrupt Controller.  */
 
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -86,13 +88,13 @@ typedef struct gic_state
     int enabled;
     int cpu_enabled[NCPU];
 
-    gic_irq_state irq_state[GIC_NIRQ];
+    gic_irq_state irq_state[GIC_MAXIRQ];
 #ifndef NVIC
-    int irq_target[GIC_NIRQ];
+    int irq_target[GIC_MAXIRQ];
 #endif
     int priority1[32][NCPU];
-    int priority2[GIC_NIRQ - 32];
-    int last_active[GIC_NIRQ][NCPU];
+    int priority2[GIC_MAXIRQ - 32];
+    int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
     int running_irq[NCPU];
@@ -111,6 +113,7 @@ typedef struct gic_state
     struct gic_state *backref[NCPU];
     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
 #endif
+    uint32_t num_irq;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -133,7 +136,7 @@ static void gic_update(gic_state *s)
         }
         best_prio = 0x100;
         best_irq = 1023;
-        for (irq = 0; irq < GIC_NIRQ; irq++) {
+        for (irq = 0; irq < s->num_irq; irq++) {
             if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +225,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
-    if (irq >= GIC_NIRQ) {
+    if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +282,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (offset == 0)
             return s->enabled;
         if (offset == 4)
-            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
         if (offset >= 0x80) {
@@ -295,7 +298,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x180) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
@@ -310,7 +313,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x280) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -322,7 +325,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x400) {
         /* Interrupt Active.  */
         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -334,14 +337,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = GIC_GET_PRIORITY(irq, cpu);
 #ifndef NVIC
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq >= 29 && irq <= 31) {
             res = cm;
@@ -351,7 +354,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 4; i++) {
@@ -426,7 +429,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x180) {
         /* Interrupt Set Enable.  */
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0xff;
@@ -451,7 +454,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x200) {
         /* Interrupt Clear Enable.  */
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0;
@@ -468,7 +471,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x280) {
         /* Interrupt Set Pending.  */
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           irq = 0;
@@ -481,7 +484,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x300) {
         /* Interrupt Clear Pending.  */
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +500,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32) {
             s->priority1[irq][cpu] = value;
@@ -508,7 +511,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 29)
             value = 0;
@@ -518,7 +521,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32)
             value |= 0xaa;
@@ -699,7 +702,7 @@ static const MemoryRegionOps gic_cpu_ops = {
 static void gic_reset(gic_state *s)
 {
     int i;
-    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
+    memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < NUM_CPU(s); i++) {
         s->priority_mask[i] = 0xf0;
         s->current_pending[i] = 1023;
@@ -735,17 +738,17 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->cpu_enabled[i]);
         for (j = 0; j < 32; j++)
             qemu_put_be32(f, s->priority1[j][i]);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
         qemu_put_be32(f, s->priority_mask[i]);
         qemu_put_be32(f, s->running_irq[i]);
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         qemu_put_be32(f, s->irq_target[i]);
 #endif
@@ -772,17 +775,17 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->cpu_enabled[i] = qemu_get_be32(f);
         for (j = 0; j < 32; j++)
             s->priority1[j][i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
         s->priority_mask[i] = qemu_get_be32(f);
         s->running_irq[i] = qemu_get_be32(f);
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         s->irq_target[i] = qemu_get_be32(f);
 #endif
@@ -798,9 +801,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 #if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
 #else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
 #endif
 {
     int i;
@@ -808,7 +811,12 @@ static void gic_init(gic_state *s)
 #if NCPU > 1
     s->num_cpu = num_cpu;
 #endif
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+    s->num_irq = num_irq + GIC_BASE_IRQ;
+    if (s->num_irq > GIC_MAXIRQ) {
+        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
+                 num_irq, GIC_MAXIRQ);
+    }
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c5..28f36ba 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,9 +15,6 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 
-/* 32 internal lines (16 used for system exceptions) plus 64 external
-   interrupt lines.  */
-#define GIC_NIRQ 96
 #define NCPU 1
 #define NVIC 1
 
@@ -41,6 +38,7 @@ typedef struct {
         int64_t tick;
         QEMUTimer *timer;
     } systick;
+    uint32_t num_irq;
 } nvic_state;
 
 /* qemu timers run at 1GHz.   We want something closer to 1MHz.  */
@@ -125,7 +123,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
 
     switch (offset) {
     case 4: /* Interrupt Control Type.  */
-        return (GIC_NIRQ / 32) - 1;
+        return (s->num_irq / 32) - 1;
     case 0x10: /* SysTick Control and Status.  */
         val = s->systick.control;
         s->systick.control &= ~SYSTICK_COUNTFLAG;
@@ -169,7 +167,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
         if (s->gic.current_pending[0] != 1023)
             val |= (s->gic.current_pending[0] << 12);
         /* ISRPENDING */
-        for (irq = 32; irq < GIC_NIRQ; irq++) {
+        for (irq = 32; irq < s->num_irq; irq++) {
             if (s->gic.irq_state[irq].pending) {
                 val |= (1 << 22);
                 break;
@@ -384,16 +382,33 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
-    gic_init(&s->gic);
+   /* note that for the M profile gic_init() takes the number of external
+    * interrupt lines only.
+    */
+    gic_init(&s->gic, s->num_irq);
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
-    vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
     return 0;
 }
 
+static SysBusDeviceInfo armv7m_nvic_priv_info = {
+    .init = armv7m_nvic_init,
+    .qdev.name  = "armv7m_nvic",
+    .qdev.size  = sizeof(nvic_state),
+    .qdev.vmsd  = &vmstate_nvic,
+    .qdev.props = (Property[]) {
+        /* The ARM v7m may have anything from 0 to 496 external interrupt
+         * IRQ lines. We default to 64. Other boards may differ and should
+         * set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
 static void armv7m_nvic_register_devices(void)
 {
-    sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init);
+    sysbus_register_withprop(&armv7m_nvic_priv_info);
 }
 
 device_init(armv7m_nvic_register_devices)
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..7342ede 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 
-#define GIC_NIRQ 96
 #define NCPU 1
 
 /* Only a single "CPU" interface is present.  */
@@ -37,7 +36,11 @@ static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
-    gic_init(&s->gic);
+    /* The GICs on the RealView boards have a fixed nonconfigurable
+     * number of interrupt lines, so we don't need to expose this as
+     * a qdev property.
+     */
+    gic_init(&s->gic, 96);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 01/12] vexpress, realview: Add (dummy) L2 cache controller Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 02/12] arm: make the number of GIC interrupts configurable Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-16  1:56   ` [Qemu-devel] [Android-virt] " Alexander Graf
  2012-01-17  1:16   ` [Qemu-devel] " andrzej zaborowski
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 04/12] hw/vexpress.c: Make motherboard peripheral memory map table-driven Peter Maydell
                   ` (9 subsequent siblings)
  12 siblings, 2 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

From: Evgeny Voevodin <e.voevodin@samsung.com>

The secondary CPU bootloader in arm_boot.c holds secondary CPUs in a
pen until the primary CPU releases them. Make boards specify the
address to be polled to determine whether to leave the pen (it was
previously hardcoded to 0x10000030, which is a Versatile Express/
Realview specific system register address).

Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm-misc.h |    1 +
 hw/arm_boot.c |   18 ++++++++++--------
 hw/realview.c |    2 ++
 hw/vexpress.c |    2 ++
 4 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index af403a1..6e8ae6b 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -31,6 +31,7 @@ struct arm_boot_info {
     const char *initrd_filename;
     target_phys_addr_t loader_start;
     target_phys_addr_t smp_loader_start;
+    target_phys_addr_t smp_bootreg_addr;
     target_phys_addr_t smp_priv_base;
     int nb_cpus;
     int board_id;
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 215d5de..bf509a8 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -31,17 +31,17 @@ static uint32_t bootloader[] = {
 /* Entry point for secondary CPUs.  Enable interrupt controller and
    Issue WFI until start address is written to system controller.  */
 static uint32_t smpboot[] = {
-  0xe59f0020, /* ldr     r0, privbase */
-  0xe3a01001, /* mov     r1, #1 */
-  0xe5801100, /* str     r1, [r0, #0x100] */
-  0xe3a00201, /* mov     r0, #0x10000000 */
-  0xe3800030, /* orr     r0, #0x30 */
+  0xe59f201c, /* ldr r2, privbase */
+  0xe59f001c, /* ldr r0, startaddr */
+  0xe3a01001, /* mov r1, #1 */
+  0xe5821100, /* str r1, [r2, #256] */
   0xe320f003, /* wfi */
   0xe5901000, /* ldr     r1, [r0] */
   0xe1110001, /* tst     r1, r1 */
   0x0afffffb, /* beq     <wfi> */
   0xe12fff11, /* bx      r1 */
-  0 /* privbase: Private memory region base address.  */
+  0,          /* privbase: Private memory region base address.  */
+  0           /* bootreg: Boot register address is held here */
 };
 
 #define WRITE_WORD(p, value) do { \
@@ -197,6 +197,7 @@ static void do_cpu_reset(void *opaque)
                                     info->loader_start);
                 }
             } else {
+                stl_phys_notdirty(info->smp_bootreg_addr, 0);
                 env->regs[15] = info->smp_loader_start;
             }
         }
@@ -272,8 +273,9 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
         rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
                            info->loader_start);
         if (info->nb_cpus > 1) {
-            smpboot[10] = info->smp_priv_base;
-            for (n = 0; n < sizeof(smpboot) / 4; n++) {
+            smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
+            smpboot[ARRAY_SIZE(smpboot) - 2] = info->smp_priv_base;
+            for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
                 smpboot[n] = tswap32(smpboot[n]);
             }
             rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
diff --git a/hw/realview.c b/hw/realview.c
index e52babc..d2fde44 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -21,6 +21,7 @@
 #include "exec-memory.h"
 
 #define SMP_BOOT_ADDR 0xe0000000
+#define SMP_BOOTREG_ADDR 0x10000030
 
 typedef struct {
     SysBusDevice busdev;
@@ -96,6 +97,7 @@ static void realview_register_devices(void)
 
 static struct arm_boot_info realview_binfo = {
     .smp_loader_start = SMP_BOOT_ADDR,
+    .smp_bootreg_addr = SMP_BOOTREG_ADDR,
 };
 
 /* The following two lists must be consistent.  */
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 613be65..64fab45 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -31,11 +31,13 @@
 #include "exec-memory.h"
 
 #define SMP_BOOT_ADDR 0xe0000000
+#define SMP_BOOTREG_ADDR 0x10000030
 
 #define VEXPRESS_BOARD_ID 0x8e0
 
 static struct arm_boot_info vexpress_binfo = {
     .smp_loader_start = SMP_BOOT_ADDR,
+    .smp_bootreg_addr = SMP_BOOTREG_ADDR,
 };
 
 static void vexpress_a9_init(ram_addr_t ram_size,
-- 
1.7.1

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

* [Qemu-devel] [PATCH 04/12] hw/vexpress.c: Make motherboard peripheral memory map table-driven
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
                   ` (2 preceding siblings ...)
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 05/12] hw/vexpress.c: Move secondary CPU boot code to SRAM Peter Maydell
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

Pull the addresses used for mapping motherboard peripherals into
memory out into a table. This will allow us to simply provide a
second table to implement the "Cortex-A Series" memory map used by
the A15 variant of Versatile Express, as well as the current
"Legacy" map used by A9.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/vexpress.c |  137 +++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 103 insertions(+), 34 deletions(-)

diff --git a/hw/vexpress.c b/hw/vexpress.c
index 64fab45..8c4d3b3 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -31,13 +31,80 @@
 #include "exec-memory.h"
 
 #define SMP_BOOT_ADDR 0xe0000000
-#define SMP_BOOTREG_ADDR 0x10000030
 
 #define VEXPRESS_BOARD_ID 0x8e0
 
 static struct arm_boot_info vexpress_binfo = {
     .smp_loader_start = SMP_BOOT_ADDR,
-    .smp_bootreg_addr = SMP_BOOTREG_ADDR,
+};
+
+/* Address maps for peripherals:
+ * the Versatile Express motherboard has two possible maps,
+ * the "legacy" one (used for A9) and the "Cortex-A Series"
+ * map (used for newer cores).
+ * Individual daughterboards can also have different maps for
+ * their peripherals.
+ */
+
+enum {
+    VE_SYSREGS,
+    VE_SP810,
+    VE_SERIALPCI,
+    VE_PL041,
+    VE_MMCI,
+    VE_KMI0,
+    VE_KMI1,
+    VE_UART0,
+    VE_UART1,
+    VE_UART2,
+    VE_UART3,
+    VE_WDT,
+    VE_TIMER01,
+    VE_TIMER23,
+    VE_SERIALDVI,
+    VE_RTC,
+    VE_COMPACTFLASH,
+    VE_CLCD,
+    VE_NORFLASH0,
+    VE_NORFLASH0ALIAS,
+    VE_NORFLASH1,
+    VE_SRAM,
+    VE_VIDEORAM,
+    VE_ETHERNET,
+    VE_USB,
+    VE_DAPROM,
+};
+
+static target_phys_addr_t motherboard_legacy_map[] = {
+    /* CS7: 0x10000000 .. 0x10020000 */
+    [VE_SYSREGS] = 0x10000000,
+    [VE_SP810] = 0x10001000,
+    [VE_SERIALPCI] = 0x10002000,
+    [VE_PL041] = 0x10004000,
+    [VE_MMCI] = 0x10005000,
+    [VE_KMI0] = 0x10006000,
+    [VE_KMI1] = 0x10007000,
+    [VE_UART0] = 0x10009000,
+    [VE_UART1] = 0x1000a000,
+    [VE_UART2] = 0x1000b000,
+    [VE_UART3] = 0x1000c000,
+    [VE_WDT] = 0x1000f000,
+    [VE_TIMER01] = 0x10011000,
+    [VE_TIMER23] = 0x10012000,
+    [VE_SERIALDVI] = 0x10016000,
+    [VE_RTC] = 0x10017000,
+    [VE_COMPACTFLASH] = 0x1001a000,
+    [VE_CLCD] = 0x1001f000,
+    /* CS0: 0x40000000 .. 0x44000000 */
+    [VE_NORFLASH0] = 0x40000000,
+    /* CS1: 0x44000000 .. 0x48000000 */
+    [VE_NORFLASH1] = 0x44000000,
+    /* CS2: 0x48000000 .. 0x4a000000 */
+    [VE_SRAM] = 0x48000000,
+    /* CS3: 0x4c000000 .. 0x50000000 */
+    [VE_VIDEORAM] = 0x4c000000,
+    [VE_ETHERNET] = 0x4e000000,
+    [VE_USB] = 0x4f000000,
 };
 
 static void vexpress_a9_init(ram_addr_t ram_size,
@@ -61,6 +128,7 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     uint32_t proc_id;
     uint32_t sys_id;
     ram_addr_t low_ram_size, vram_size, sram_size;
+    target_phys_addr_t *map = motherboard_legacy_map;
 
     if (!cpu_model) {
         cpu_model = "cortex-a9";
@@ -116,53 +184,53 @@ static void vexpress_a9_init(ram_addr_t ram_size,
         pic[n] = qdev_get_gpio_in(dev, n);
     }
 
-    /* Motherboard peripherals CS7 : 0x10000000 .. 0x10020000 */
+    /* Motherboard peripherals: the wiring is the same but the
+     * addresses vary between the legacy and A-Series memory maps.
+     */
+
     sys_id = 0x1190f500;
     proc_id = 0x0c000191;
 
-    /* 0x10000000 System registers */
     sysctl = qdev_create(NULL, "realview_sysctl");
     qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
     qdev_init_nofail(sysctl);
     qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
-    sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
+    sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, map[VE_SYSREGS]);
+
+    /* VE_SP810: not modelled */
+    /* VE_SERIALPCI: not modelled */
 
-    /* 0x10001000 SP810 system control */
-    /* 0x10002000 serial bus PCI */
-    /* 0x10004000 PL041 audio */
     pl041 = qdev_create(NULL, "pl041");
     qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
     qdev_init_nofail(pl041);
-    sysbus_mmio_map(sysbus_from_qdev(pl041), 0, 0x10004000);
+    sysbus_mmio_map(sysbus_from_qdev(pl041), 0, map[VE_PL041]);
     sysbus_connect_irq(sysbus_from_qdev(pl041), 0, pic[11]);
 
-    dev = sysbus_create_varargs("pl181", 0x10005000, pic[9], pic[10], NULL);
+    dev = sysbus_create_varargs("pl181", map[VE_MMCI], pic[9], pic[10], NULL);
     /* Wire up MMC card detect and read-only signals */
     qdev_connect_gpio_out(dev, 0,
                           qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT));
     qdev_connect_gpio_out(dev, 1,
                           qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN));
 
-    sysbus_create_simple("pl050_keyboard", 0x10006000, pic[12]);
-    sysbus_create_simple("pl050_mouse", 0x10007000, pic[13]);
-
-    sysbus_create_simple("pl011", 0x10009000, pic[5]);
-    sysbus_create_simple("pl011", 0x1000a000, pic[6]);
-    sysbus_create_simple("pl011", 0x1000b000, pic[7]);
-    sysbus_create_simple("pl011", 0x1000c000, pic[8]);
+    sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]);
+    sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]);
 
-    /* 0x1000f000 SP805 WDT */
+    sysbus_create_simple("pl011", map[VE_UART0], pic[5]);
+    sysbus_create_simple("pl011", map[VE_UART1], pic[6]);
+    sysbus_create_simple("pl011", map[VE_UART2], pic[7]);
+    sysbus_create_simple("pl011", map[VE_UART3], pic[8]);
 
-    sysbus_create_simple("sp804", 0x10011000, pic[2]);
-    sysbus_create_simple("sp804", 0x10012000, pic[3]);
+    sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
+    sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
 
-    /* 0x10016000 Serial Bus DVI */
+    /* VE_SERIALDVI: not modelled */
 
-    sysbus_create_simple("pl031", 0x10017000, pic[4]); /* RTC */
+    sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */
 
-    /* 0x1001a000 Compact Flash */
+    /* VE_COMPACTFLASH: not modelled */
 
-    /* 0x1001f000 PL111 CLCD (motherboard) */
+    /* VE_CLCD: not modelled (we use the daughterboard CLCD only) */
 
     /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
 
@@ -184,28 +252,28 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     /* 0x1e00a000 PL310 L2 Cache Controller */
     sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
 
-    /* CS0: NOR0 flash          : 0x40000000 .. 0x44000000 */
-    /* CS4: NOR1 flash          : 0x44000000 .. 0x48000000 */
-    /* CS2: SRAM                : 0x48000000 .. 0x4a000000 */
+    /* VE_NORFLASH0: not modelled */
+    /* VE_NORFLASH0ALIAS: not modelled */
+    /* VE_NORFLASH1: not modelled */
+
     sram_size = 0x2000000;
     memory_region_init_ram(sram, "vexpress.sram", sram_size);
     vmstate_register_ram_global(sram);
-    memory_region_add_subregion(sysmem, 0x48000000, sram);
-
-    /* CS3: USB, ethernet, VRAM : 0x4c000000 .. 0x50000000 */
+    memory_region_add_subregion(sysmem, map[VE_SRAM], sram);
 
-    /* 0x4c000000 Video RAM */
     vram_size = 0x800000;
     memory_region_init_ram(vram, "vexpress.vram", vram_size);
     vmstate_register_ram_global(vram);
-    memory_region_add_subregion(sysmem, 0x4c000000, vram);
+    memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram);
 
     /* 0x4e000000 LAN9118 Ethernet */
     if (nd_table[0].vlan) {
-        lan9118_init(&nd_table[0], 0x4e000000, pic[15]);
+        lan9118_init(&nd_table[0], map[VE_ETHERNET], pic[15]);
     }
 
-    /* 0x4f000000 ISP1761 USB */
+    /* VE_USB: not modelled */
+
+    /* VE_DAPROM: not modelled */
 
     /* ??? Hack to map an additional page of ram for the secondary CPU
        startup code.  I guess this works on real hardware because the
@@ -222,6 +290,7 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     vexpress_binfo.nb_cpus = smp_cpus;
     vexpress_binfo.board_id = VEXPRESS_BOARD_ID;
     vexpress_binfo.loader_start = 0x60000000;
+    vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
     arm_load_kernel(first_cpu, &vexpress_binfo);
 }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 05/12] hw/vexpress.c: Move secondary CPU boot code to SRAM
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
                   ` (3 preceding siblings ...)
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 04/12] hw/vexpress.c: Make motherboard peripheral memory map table-driven Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 06/12] hw/vexpress.c: Factor out daughterboard-specific initialization Peter Maydell
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

On real Versatile Express hardware, the boot ROM puts the secondary
CPU bootcode/holding pen in SRAM. We can therefore rely on Linux not
trashing this memory until secondary CPUs have booted up, and can
put our QEMU-specific pen code in the same place. This allows us to
drop the odd "hack" RAM page we were using before.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/vexpress.c |   16 ++--------------
 1 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/hw/vexpress.c b/hw/vexpress.c
index 8c4d3b3..99a9690 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -30,13 +30,9 @@
 #include "boards.h"
 #include "exec-memory.h"
 
-#define SMP_BOOT_ADDR 0xe0000000
-
 #define VEXPRESS_BOARD_ID 0x8e0
 
-static struct arm_boot_info vexpress_binfo = {
-    .smp_loader_start = SMP_BOOT_ADDR,
-};
+static struct arm_boot_info vexpress_binfo;
 
 /* Address maps for peripherals:
  * the Versatile Express motherboard has two possible maps,
@@ -118,7 +114,6 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     MemoryRegion *lowram = g_new(MemoryRegion, 1);
     MemoryRegion *vram = g_new(MemoryRegion, 1);
     MemoryRegion *sram = g_new(MemoryRegion, 1);
-    MemoryRegion *hackram = g_new(MemoryRegion, 1);
     DeviceState *dev, *sysctl, *pl041;
     SysBusDevice *busdev;
     qemu_irq *irqp;
@@ -275,14 +270,6 @@ static void vexpress_a9_init(ram_addr_t ram_size,
 
     /* VE_DAPROM: not modelled */
 
-    /* ??? Hack to map an additional page of ram for the secondary CPU
-       startup code.  I guess this works on real hardware because the
-       BootROM happens to be in ROM/flash or in memory that isn't clobbered
-       until after Linux boots the secondary CPUs.  */
-    memory_region_init_ram(hackram, "vexpress.hack", 0x1000);
-    vmstate_register_ram_global(hackram);
-    memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, hackram);
-
     vexpress_binfo.ram_size = ram_size;
     vexpress_binfo.kernel_filename = kernel_filename;
     vexpress_binfo.kernel_cmdline = kernel_cmdline;
@@ -290,6 +277,7 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     vexpress_binfo.nb_cpus = smp_cpus;
     vexpress_binfo.board_id = VEXPRESS_BOARD_ID;
     vexpress_binfo.loader_start = 0x60000000;
+    vexpress_binfo.smp_loader_start = map[VE_SRAM];
     vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
     arm_load_kernel(first_cpu, &vexpress_binfo);
 }
-- 
1.7.1

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

* [Qemu-devel] [PATCH 06/12] hw/vexpress.c: Factor out daughterboard-specific initialization
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
                   ` (4 preceding siblings ...)
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 05/12] hw/vexpress.c: Move secondary CPU boot code to SRAM Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 07/12] hw/vexpress.c: Instantiate the motherboard CLCD Peter Maydell
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

Factor out daughterboard specifics into a data structure and
daughterboard initialization function, in preparation for adding
vexpress-a15 support.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/vexpress.c |  118 ++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 83 insertions(+), 35 deletions(-)

diff --git a/hw/vexpress.c b/hw/vexpress.c
index 99a9690..9033b50 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -103,32 +103,43 @@ static target_phys_addr_t motherboard_legacy_map[] = {
     [VE_USB] = 0x4f000000,
 };
 
-static void vexpress_a9_init(ram_addr_t ram_size,
-                     const char *boot_device,
-                     const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename, const char *cpu_model)
+/* Structure defining the peculiarities of a specific daughterboard */
+
+typedef struct VEDBoardInfo VEDBoardInfo;
+
+typedef void DBoardInitFn(const VEDBoardInfo *daughterboard,
+                          ram_addr_t ram_size,
+                          const char *cpu_model,
+                          qemu_irq *pic, uint32_t *proc_id);
+
+struct VEDBoardInfo {
+    const target_phys_addr_t *motherboard_map;
+    const target_phys_addr_t loader_start;
+    DBoardInitFn *init;
+};
+
+static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
+                                  ram_addr_t ram_size,
+                                  const char *cpu_model,
+                                  qemu_irq *pic, uint32_t *proc_id)
 {
     CPUState *env = NULL;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *lowram = g_new(MemoryRegion, 1);
-    MemoryRegion *vram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    DeviceState *dev, *sysctl, *pl041;
+    DeviceState *dev;
     SysBusDevice *busdev;
     qemu_irq *irqp;
-    qemu_irq pic[64];
     int n;
     qemu_irq cpu_irq[4];
-    uint32_t proc_id;
-    uint32_t sys_id;
-    ram_addr_t low_ram_size, vram_size, sram_size;
-    target_phys_addr_t *map = motherboard_legacy_map;
+    ram_addr_t low_ram_size;
 
     if (!cpu_model) {
         cpu_model = "cortex-a9";
     }
 
+    *proc_id = 0x0c000191;
+
     for (n = 0; n < smp_cpus; n++) {
         env = cpu_init(cpu_model);
         if (!env) {
@@ -141,7 +152,7 @@ static void vexpress_a9_init(ram_addr_t ram_size,
 
     if (ram_size > 0x40000000) {
         /* 1GB is the maximum the address space permits */
-        fprintf(stderr, "vexpress: cannot model more than 1GB RAM\n");
+        fprintf(stderr, "vexpress-a9: cannot model more than 1GB RAM\n");
         exit(1);
     }
 
@@ -179,12 +190,58 @@ static void vexpress_a9_init(ram_addr_t ram_size,
         pic[n] = qdev_get_gpio_in(dev, n);
     }
 
+    /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
+
+    /* 0x10020000 PL111 CLCD (daughterboard) */
+    sysbus_create_simple("pl111", 0x10020000, pic[44]);
+
+    /* 0x10060000 AXI RAM */
+    /* 0x100e0000 PL341 Dynamic Memory Controller */
+    /* 0x100e1000 PL354 Static Memory Controller */
+    /* 0x100e2000 System Configuration Controller */
+
+    sysbus_create_simple("sp804", 0x100e4000, pic[48]);
+    /* 0x100e5000 SP805 Watchdog module */
+    /* 0x100e6000 BP147 TrustZone Protection Controller */
+    /* 0x100e9000 PL301 'Fast' AXI matrix */
+    /* 0x100ea000 PL301 'Slow' AXI matrix */
+    /* 0x100ec000 TrustZone Address Space Controller */
+    /* 0x10200000 CoreSight debug APB */
+    /* 0x1e00a000 PL310 L2 Cache Controller */
+    sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
+}
+
+static const VEDBoardInfo a9_daughterboard = {
+    .motherboard_map = motherboard_legacy_map,
+    .loader_start = 0x60000000,
+    .init = a9_daughterboard_init,
+};
+
+static void vexpress_common_init(const VEDBoardInfo *daughterboard,
+                                 ram_addr_t ram_size,
+                                 const char *boot_device,
+                                 const char *kernel_filename,
+                                 const char *kernel_cmdline,
+                                 const char *initrd_filename,
+                                 const char *cpu_model)
+{
+    DeviceState *dev, *sysctl, *pl041;
+    qemu_irq pic[64];
+    uint32_t proc_id;
+    uint32_t sys_id;
+    ram_addr_t vram_size, sram_size;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *vram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    const target_phys_addr_t *map = daughterboard->motherboard_map;
+
+    daughterboard->init(daughterboard, ram_size, cpu_model, pic, &proc_id);
+
     /* Motherboard peripherals: the wiring is the same but the
      * addresses vary between the legacy and A-Series memory maps.
      */
 
     sys_id = 0x1190f500;
-    proc_id = 0x0c000191;
 
     sysctl = qdev_create(NULL, "realview_sysctl");
     qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
@@ -227,26 +284,6 @@ static void vexpress_a9_init(ram_addr_t ram_size,
 
     /* VE_CLCD: not modelled (we use the daughterboard CLCD only) */
 
-    /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
-
-    /* 0x10020000 PL111 CLCD (daughterboard) */
-    sysbus_create_simple("pl111", 0x10020000, pic[44]);
-
-    /* 0x10060000 AXI RAM */
-    /* 0x100e0000 PL341 Dynamic Memory Controller */
-    /* 0x100e1000 PL354 Static Memory Controller */
-    /* 0x100e2000 System Configuration Controller */
-
-    sysbus_create_simple("sp804", 0x100e4000, pic[48]);
-    /* 0x100e5000 SP805 Watchdog module */
-    /* 0x100e6000 BP147 TrustZone Protection Controller */
-    /* 0x100e9000 PL301 'Fast' AXI matrix */
-    /* 0x100ea000 PL301 'Slow' AXI matrix */
-    /* 0x100ec000 TrustZone Address Space Controller */
-    /* 0x10200000 CoreSight debug APB */
-    /* 0x1e00a000 PL310 L2 Cache Controller */
-    sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
-
     /* VE_NORFLASH0: not modelled */
     /* VE_NORFLASH0ALIAS: not modelled */
     /* VE_NORFLASH1: not modelled */
@@ -276,12 +313,23 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     vexpress_binfo.initrd_filename = initrd_filename;
     vexpress_binfo.nb_cpus = smp_cpus;
     vexpress_binfo.board_id = VEXPRESS_BOARD_ID;
-    vexpress_binfo.loader_start = 0x60000000;
+    vexpress_binfo.loader_start = daughterboard->loader_start;
     vexpress_binfo.smp_loader_start = map[VE_SRAM];
     vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
     arm_load_kernel(first_cpu, &vexpress_binfo);
 }
 
+static void vexpress_a9_init(ram_addr_t ram_size,
+                             const char *boot_device,
+                             const char *kernel_filename,
+                             const char *kernel_cmdline,
+                             const char *initrd_filename,
+                             const char *cpu_model)
+{
+    vexpress_common_init(&a9_daughterboard,
+                         ram_size, boot_device, kernel_filename,
+                         kernel_cmdline, initrd_filename, cpu_model);
+}
 
 static QEMUMachine vexpress_a9_machine = {
     .name = "vexpress-a9",
-- 
1.7.1

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

* [Qemu-devel] [PATCH 07/12] hw/vexpress.c: Instantiate the motherboard CLCD
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
                   ` (5 preceding siblings ...)
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 06/12] hw/vexpress.c: Factor out daughterboard-specific initialization Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 08/12] hw/a15mpcore.c: Add Cortex-A15 private peripheral model Peter Maydell
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

Instantiate the CLCD on the vexpress motherboard as well as one on
the daughterboard -- the A15 daughterboard does not have a CLCD
and so relies on the motherboard one.

At the moment QEMU doesn't provide infrastructure for selecting
which display device gets to actually show graphics -- the first
one registered is it. Fortunately this works for the major use
case (Linux): if the daughterboard has a CLCD it will come first
and be used, otherwise we fall back to the motherboard CLCD.
So we don't (currently) need to implement the control register
which allows software to tell the mux which video output to pass
through to the outside world.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/vexpress.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/vexpress.c b/hw/vexpress.c
index 9033b50..9860085 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -282,7 +282,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
 
     /* VE_COMPACTFLASH: not modelled */
 
-    /* VE_CLCD: not modelled (we use the daughterboard CLCD only) */
+    sysbus_create_simple("pl111", map[VE_CLCD], pic[14]);
 
     /* VE_NORFLASH0: not modelled */
     /* VE_NORFLASH0ALIAS: not modelled */
-- 
1.7.1

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

* [Qemu-devel] [PATCH 08/12] hw/a15mpcore.c: Add Cortex-A15 private peripheral model
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
                   ` (6 preceding siblings ...)
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 07/12] hw/vexpress.c: Instantiate the motherboard CLCD Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 09/12] Add dummy implementation of generic timer cp15 registers Peter Maydell
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

Add a model of the Cortex-A15 memory mapped private peripheral
space. This is fairly simple because the only memory mapped
bit of the A15 is the GIC.

Note that we don't currently model a VGIC and therefore don't
map the VGIC related bits of the GIC.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 Makefile.target |    2 +-
 hw/a15mpcore.c  |   93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+), 1 deletions(-)
 create mode 100644 hw/a15mpcore.c

diff --git a/Makefile.target b/Makefile.target
index 06d79b8..92f133e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -340,7 +340,7 @@ obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
 obj-arm-y += versatile_pci.o
 obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
-obj-arm-y += arm_mptimer.o
+obj-arm-y += arm_mptimer.o a15mpcore.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
 obj-arm-y += arm-semi.o
diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
new file mode 100644
index 0000000..fbbf2dc
--- /dev/null
+++ b/hw/a15mpcore.c
@@ -0,0 +1,93 @@
+/*
+ * Cortex-A15MPCore internal peripheral emulation.
+ *
+ * Copyright (c) 2012 Linaro Limited.
+ * Written by Peter Maydell.
+ *
+ * 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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysbus.h"
+
+/* Configuration for arm_gic.c:
+ * max number of CPUs, how to ID current CPU
+ */
+#define NCPU 4
+
+static inline int gic_get_current_cpu(void)
+{
+  return cpu_single_env->cpu_index;
+}
+
+#include "arm_gic.c"
+
+/* A15MP private memory region.  */
+
+typedef struct A15MPPrivState {
+    gic_state gic;
+    uint32_t num_cpu;
+    uint32_t num_irq;
+    MemoryRegion container;
+} A15MPPrivState;
+
+static int a15mp_priv_init(SysBusDevice *dev)
+{
+    A15MPPrivState *s = FROM_SYSBUSGIC(A15MPPrivState, dev);
+
+    if (s->num_cpu > NCPU) {
+        hw_error("a15mp_priv_init: num-cpu may not be more than %d\n", NCPU);
+    }
+
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
+
+    /* Memory map (addresses are offsets from PERIPHBASE):
+     *  0x0000-0x0fff -- reserved
+     *  0x1000-0x1fff -- GIC Distributor
+     *  0x2000-0x2fff -- GIC CPU interface
+     *  0x4000-0x4fff -- GIC virtual interface control (not modelled)
+     *  0x5000-0x5fff -- GIC virtual interface control (not modelled)
+     *  0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
+     */
+    memory_region_init(&s->container, "a15mp-priv-container", 0x8000);
+    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
+    memory_region_add_subregion(&s->container, 0x2000, &s->gic.cpuiomem[0]);
+
+    sysbus_init_mmio(dev, &s->container);
+    return 0;
+}
+
+static SysBusDeviceInfo a15mp_priv_info = {
+    .init = a15mp_priv_init,
+    .qdev.name  = "a15mpcore_priv",
+    .qdev.size  = sizeof(A15MPPrivState),
+    /* We currently have no savable state outside the common GIC state */
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("num-cpu", A15MPPrivState, num_cpu, 1),
+        /* The Cortex-A15MP may have anything from 0 to 224 external interrupt
+         * IRQ lines (with another 32 internal). We default to 64+32, which
+         * is the number provided by the Cortex-A15MP test chip in the
+         * Versatile Express A15 development board.
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", A15MPPrivState, num_irq, 96),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void a15mp_register_devices(void)
+{
+    sysbus_register_withprop(&a15mp_priv_info);
+}
+
+device_init(a15mp_register_devices)
-- 
1.7.1

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

* [Qemu-devel] [PATCH 09/12] Add dummy implementation of generic timer cp15 registers
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
                   ` (7 preceding siblings ...)
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 08/12] hw/a15mpcore.c: Add Cortex-A15 private peripheral model Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 10/12] Add Cortex-A15 CPU definition Peter Maydell
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

Add a dummy implementation of the cp15 registers for the generic
timer (found in the Cortex-A15), just sufficient for Linux to
decide that it can't use it. This requires at least CNTP_CTL and
CNTFRQ to be implemented as RAZ/WI; we RAZ/WI all of c14.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h    |    1 +
 target-arm/helper.c |   12 ++++++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 26b4981..d5403ea 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -381,6 +381,7 @@ enum arm_features {
     ARM_FEATURE_VAPA, /* cp15 VA to PA lookups */
     ARM_FEATURE_ARM_DIV, /* divide supported in ARM encoding */
     ARM_FEATURE_VFP4, /* VFPv4 (implies that NEON is v2) */
+    ARM_FEATURE_GENERICTIMER,
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fa42c64..de4a50f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1757,7 +1757,11 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
             goto bad_reg;
         }
         break;
-    case 14: /* Reserved.  */
+    case 14: /* Generic timer */
+        if (arm_feature(env, ARM_FEATURE_GENERICTIMER)) {
+            /* Dummy implementation: RAZ/WI for all */
+            break;
+        }
         goto bad_reg;
     case 15: /* Implementation specific.  */
         if (arm_feature(env, ARM_FEATURE_XSCALE)) {
@@ -2123,7 +2127,11 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
         default:
             goto bad_reg;
         }
-    case 14: /* Reserved.  */
+    case 14: /* Generic timer */
+        if (arm_feature(env, ARM_FEATURE_GENERICTIMER)) {
+            /* Dummy implementation: RAZ/WI for all */
+            return 0;
+        }
         goto bad_reg;
     case 15: /* Implementation specific.  */
         if (arm_feature(env, ARM_FEATURE_XSCALE)) {
-- 
1.7.1

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

* [Qemu-devel] [PATCH 10/12] Add Cortex-A15 CPU definition
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
                   ` (8 preceding siblings ...)
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 09/12] Add dummy implementation of generic timer cp15 registers Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-23 18:12   ` [Qemu-devel] [Android-virt] " Peter Maydell
  2012-01-24  7:59   ` [Qemu-devel] " Andreas Färber
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 11/12] arm_boot: Pass base address of GIC CPU interface, not whole GIC Peter Maydell
                   ` (2 subsequent siblings)
  12 siblings, 2 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

Add a definition of a Cortex-A15 CPU. Note that for the moment we do
not implement any of:
 * Large Physical Address Extensions (LPAE)
 * Virtualization Extensions
 * Generic Timer
 * TrustZone (this is also true of our existing Cortex-A9 model, etc)

This CPU model is sufficient to boot a Linux kernel which has been
compiled for an A15 without LPAE enabled.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h    |    1 +
 target-arm/helper.c |   56 ++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index d5403ea..4b8d680 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -433,6 +433,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define ARM_CPUID_CORTEXA8    0x410fc080
 #define ARM_CPUID_CORTEXA9    0x410fc090
 #define ARM_CPUID_CORTEXM3    0x410fc231
+#define ARM_CPUID_CORTEXA15   0x412fc0f1
 #define ARM_CPUID_ANY         0xffffffff
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index de4a50f..a68dc5c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -10,6 +10,16 @@
 #if !defined(CONFIG_USER_ONLY)
 #include "hw/loader.h"
 #endif
+#include "sysemu.h"
+
+static uint32_t cortexa15_cp15_c0_c1[8] = {
+    0x00001131, 0x00011011, 0x02010555, 0x00000000,
+    0x10201105, 0x20000000, 0x01240000, 0x02102211
+};
+
+static uint32_t cortexa15_cp15_c0_c2[8] = {
+    0x02101110, 0x13112111, 0x21232041, 0x11112131, 0x10011142, 0, 0, 0
+};
 
 static uint32_t cortexa9_cp15_c0_c1[8] =
 { 0x1031, 0x11, 0x000, 0, 0x00100103, 0x20000000, 0x01230000, 0x00002111 };
@@ -158,6 +168,27 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_ccsid[1] = 0x200fe015; /* 16k L1 icache. */
         env->cp15.c1_sys = 0x00c50078;
         break;
+    case ARM_CPUID_CORTEXA15:
+        set_feature(env, ARM_FEATURE_V7);
+        set_feature(env, ARM_FEATURE_VFP4);
+        set_feature(env, ARM_FEATURE_VFP_FP16);
+        set_feature(env, ARM_FEATURE_NEON);
+        set_feature(env, ARM_FEATURE_THUMB2EE);
+        set_feature(env, ARM_FEATURE_ARM_DIV);
+        set_feature(env, ARM_FEATURE_V7MP);
+        set_feature(env, ARM_FEATURE_GENERICTIMER);
+        env->vfp.xregs[ARM_VFP_FPSID] = 0x410430f0;
+        env->vfp.xregs[ARM_VFP_MVFR0] = 0x10110222;
+        env->vfp.xregs[ARM_VFP_MVFR1] = 0x11111111;
+        memcpy(env->cp15.c0_c1, cortexa15_cp15_c0_c1, 8 * sizeof(uint32_t));
+        memcpy(env->cp15.c0_c2, cortexa15_cp15_c0_c2, 8 * sizeof(uint32_t));
+        env->cp15.c0_cachetype = 0x8444c004;
+        env->cp15.c0_clid = 0x0a200023;
+        env->cp15.c0_ccsid[0] = 0x701fe00a; /* 32K L1 dcache */
+        env->cp15.c0_ccsid[1] = 0x201fe00a; /* 32K L1 icache */
+        env->cp15.c0_ccsid[2] = 0x711fe07a; /* 4096K L2 unified cache */
+        env->cp15.c1_sys = 0x00c50078;
+        break;
     case ARM_CPUID_CORTEXM3:
         set_feature(env, ARM_FEATURE_V7);
         set_feature(env, ARM_FEATURE_M);
@@ -413,6 +444,7 @@ static const struct arm_cpu_t arm_cpu_names[] = {
     { ARM_CPUID_CORTEXM3, "cortex-m3"},
     { ARM_CPUID_CORTEXA8, "cortex-a8"},
     { ARM_CPUID_CORTEXA9, "cortex-a9"},
+    { ARM_CPUID_CORTEXA15, "cortex-a15"},
     { ARM_CPUID_TI925T, "ti925t" },
     { ARM_CPUID_PXA250, "pxa250" },
     { ARM_CPUID_SA1100,    "sa1100" },
@@ -667,8 +699,6 @@ uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
 
 #else
 
-extern int semihosting_enabled;
-
 /* Map CPU modes onto saved register banks.  */
 static inline int bank_number(CPUState *env, int mode)
 {
@@ -1934,6 +1964,7 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
             case ARM_CPUID_CORTEXA8:
                 return 2;
             case ARM_CPUID_CORTEXA9:
+            case ARM_CPUID_CORTEXA15:
                 return 0;
             default:
                 goto bad_reg;
@@ -2054,11 +2085,26 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
                     goto bad_reg;
                 }
             case 1: /* L2 cache */
-                if (crm != 0) {
+                /* L2 Lockdown and Auxiliary control.  */
+                switch (op2) {
+                case 0:
+                    /* L2 cache lockdown (A8 only) */
+                    return 0;
+                case 2:
+                    /* L2 cache auxiliary control (A8) or control (A15) */
+                    if (ARM_CPUID(env) == ARM_CPUID_CORTEXA15) {
+                        /* Linux wants the number of processors from here.
+                         * Might as well set the interrupt-controller bit too.
+                         */
+                        return ((smp_cpus - 1) << 24) | (1 << 23);
+                    }
+                    return 0;
+                case 3:
+                    /* L2 cache extended control (A15) */
+                    return 0;
+                default:
                     goto bad_reg;
                 }
-                /* L2 Lockdown and Auxiliary control.  */
-                return 0;
             default:
                 goto bad_reg;
             }
-- 
1.7.1

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

* [Qemu-devel] [PATCH 11/12] arm_boot: Pass base address of GIC CPU interface, not whole GIC
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
                   ` (9 preceding siblings ...)
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 10/12] Add Cortex-A15 CPU definition Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 12/12] hw/vexpress.c: Add vexpress-a15 machine Peter Maydell
  2012-01-13 20:57 ` [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
  12 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

The arm_boot secondary boot loader code needs the address of
the GIC CPU interface. Obtaining this from the base address
of the private peripheral region was possible for A9 and 11MPcore,
but the A15 puts the GIC CPU interface in a different place.
So make boards pass in the GIC CPU interface address directly.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm-misc.h |    2 +-
 hw/arm_boot.c |    8 ++++----
 hw/realview.c |   12 +++++++-----
 hw/vexpress.c |    6 ++++--
 4 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 6e8ae6b..a360512 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -32,7 +32,7 @@ struct arm_boot_info {
     target_phys_addr_t loader_start;
     target_phys_addr_t smp_loader_start;
     target_phys_addr_t smp_bootreg_addr;
-    target_phys_addr_t smp_priv_base;
+    target_phys_addr_t gic_cpu_if_addr;
     int nb_cpus;
     int board_id;
     int (*atag_board)(const struct arm_boot_info *info, void *p);
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index bf509a8..89463a3 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -31,16 +31,16 @@ static uint32_t bootloader[] = {
 /* Entry point for secondary CPUs.  Enable interrupt controller and
    Issue WFI until start address is written to system controller.  */
 static uint32_t smpboot[] = {
-  0xe59f201c, /* ldr r2, privbase */
+  0xe59f201c, /* ldr r2, gic_cpu_if */
   0xe59f001c, /* ldr r0, startaddr */
   0xe3a01001, /* mov r1, #1 */
-  0xe5821100, /* str r1, [r2, #256] */
+  0xe5821000, /* str r1, [r2] */
   0xe320f003, /* wfi */
   0xe5901000, /* ldr     r1, [r0] */
   0xe1110001, /* tst     r1, r1 */
   0x0afffffb, /* beq     <wfi> */
   0xe12fff11, /* bx      r1 */
-  0,          /* privbase: Private memory region base address.  */
+  0,          /* gic_cpu_if: base address of GIC CPU interface */
   0           /* bootreg: Boot register address is held here */
 };
 
@@ -274,7 +274,7 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
                            info->loader_start);
         if (info->nb_cpus > 1) {
             smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
-            smpboot[ARRAY_SIZE(smpboot) - 2] = info->smp_priv_base;
+            smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
             for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
                 smpboot[n] = tswap32(smpboot[n]);
             }
diff --git a/hw/realview.c b/hw/realview.c
index d2fde44..9adc46d 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -214,21 +214,23 @@ static void realview_init(ram_addr_t ram_size,
     sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
 
     if (is_mpcore) {
+        target_phys_addr_t periphbase;
         dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
         qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
         qdev_init_nofail(dev);
         busdev = sysbus_from_qdev(dev);
         if (is_pb) {
-            realview_binfo.smp_priv_base = 0x1f000000;
+            periphbase = 0x1f000000;
         } else {
-            realview_binfo.smp_priv_base = 0x10100000;
+            periphbase = 0x10100000;
         }
-        sysbus_mmio_map(busdev, 0, realview_binfo.smp_priv_base);
+        sysbus_mmio_map(busdev, 0, periphbase);
         for (n = 0; n < smp_cpus; n++) {
             sysbus_connect_irq(busdev, n, cpu_irq[n]);
         }
-        sysbus_create_varargs("l2x0", realview_binfo.smp_priv_base + 0x2000,
-                              NULL);
+        sysbus_create_varargs("l2x0", periphbase + 0x2000, NULL);
+        /* Both A9 and 11MPCore put the GIC CPU i/f at base + 0x100 */
+        realview_binfo.gic_cpu_if_addr = periphbase + 0x100;
     } else {
         uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000;
         /* For now just create the nIRQ GIC, and ignore the others.  */
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 9860085..4b9454f 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -115,6 +115,7 @@ typedef void DBoardInitFn(const VEDBoardInfo *daughterboard,
 struct VEDBoardInfo {
     const target_phys_addr_t *motherboard_map;
     const target_phys_addr_t loader_start;
+    const target_phys_addr_t gic_cpu_if_addr;
     DBoardInitFn *init;
 };
 
@@ -175,8 +176,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
     qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
     qdev_init_nofail(dev);
     busdev = sysbus_from_qdev(dev);
-    vexpress_binfo.smp_priv_base = 0x1e000000;
-    sysbus_mmio_map(busdev, 0, vexpress_binfo.smp_priv_base);
+    sysbus_mmio_map(busdev, 0, 0x1e000000);
     for (n = 0; n < smp_cpus; n++) {
         sysbus_connect_irq(busdev, n, cpu_irq[n]);
     }
@@ -214,6 +214,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
 static const VEDBoardInfo a9_daughterboard = {
     .motherboard_map = motherboard_legacy_map,
     .loader_start = 0x60000000,
+    .gic_cpu_if_addr = 0x1e000100,
     .init = a9_daughterboard_init,
 };
 
@@ -316,6 +317,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
     vexpress_binfo.loader_start = daughterboard->loader_start;
     vexpress_binfo.smp_loader_start = map[VE_SRAM];
     vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
+    vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
     arm_load_kernel(first_cpu, &vexpress_binfo);
 }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 12/12] hw/vexpress.c: Add vexpress-a15 machine
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
                   ` (10 preceding siblings ...)
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 11/12] arm_boot: Pass base address of GIC CPU interface, not whole GIC Peter Maydell
@ 2012-01-13 20:52 ` Peter Maydell
  2012-01-13 20:57 ` [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
  12 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

Add the vexpress-a15 machine, and the A-Series memory map it uses.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/vexpress.c |  141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 141 insertions(+), 0 deletions(-)

diff --git a/hw/vexpress.c b/hw/vexpress.c
index 4b9454f..9d16fbf 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -103,6 +103,41 @@ static target_phys_addr_t motherboard_legacy_map[] = {
     [VE_USB] = 0x4f000000,
 };
 
+static target_phys_addr_t motherboard_aseries_map[] = {
+    /* CS0: 0x00000000 .. 0x0c000000 */
+    [VE_NORFLASH0] = 0x00000000,
+    [VE_NORFLASH0ALIAS] = 0x08000000,
+    /* CS4: 0x0c000000 .. 0x10000000 */
+    [VE_NORFLASH1] = 0x0c000000,
+    /* CS5: 0x10000000 .. 0x14000000 */
+    /* CS1: 0x14000000 .. 0x18000000 */
+    [VE_SRAM] = 0x14000000,
+    /* CS2: 0x18000000 .. 0x1c000000 */
+    [VE_VIDEORAM] = 0x18000000,
+    [VE_ETHERNET] = 0x1a000000,
+    [VE_USB] = 0x1b000000,
+    /* CS3: 0x1c000000 .. 0x20000000 */
+    [VE_DAPROM] = 0x1c000000,
+    [VE_SYSREGS] = 0x1c010000,
+    [VE_SP810] = 0x1c020000,
+    [VE_SERIALPCI] = 0x1c030000,
+    [VE_PL041] = 0x1c040000,
+    [VE_MMCI] = 0x1c050000,
+    [VE_KMI0] = 0x1c060000,
+    [VE_KMI1] = 0x1c070000,
+    [VE_UART0] = 0x1c090000,
+    [VE_UART1] = 0x1c0a0000,
+    [VE_UART2] = 0x1c0b0000,
+    [VE_UART3] = 0x1c0c0000,
+    [VE_WDT] = 0x1c0f0000,
+    [VE_TIMER01] = 0x1c110000,
+    [VE_TIMER23] = 0x1c120000,
+    [VE_SERIALDVI] = 0x1c160000,
+    [VE_RTC] = 0x1c170000,
+    [VE_COMPACTFLASH] = 0x1c1a0000,
+    [VE_CLCD] = 0x1c1f0000,
+};
+
 /* Structure defining the peculiarities of a specific daughterboard */
 
 typedef struct VEDBoardInfo VEDBoardInfo;
@@ -218,6 +253,91 @@ static const VEDBoardInfo a9_daughterboard = {
     .init = a9_daughterboard_init,
 };
 
+static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
+                                   ram_addr_t ram_size,
+                                   const char *cpu_model,
+                                   qemu_irq *pic, uint32_t *proc_id)
+{
+    int n;
+    CPUState *env = NULL;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    qemu_irq cpu_irq[4];
+    DeviceState *dev;
+    SysBusDevice *busdev;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a15";
+    }
+
+    *proc_id = 0x14000217;
+
+    for (n = 0; n < smp_cpus; n++) {
+        qemu_irq *irqp;
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    if (ram_size > 0x80000000) {
+        fprintf(stderr, "vexpress-a15: cannot model more than 2GB RAM\n");
+        exit(1);
+    }
+
+    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
+    vmstate_register_ram_global(ram);
+    /* RAM is from 0x80000000 upwards; there is no low-memory alias for it. */
+    memory_region_add_subregion(sysmem, 0x80000000, ram);
+
+    /* 0x2c000000 A15MPCore private memory region (GIC) */
+    dev = qdev_create(NULL, "a15mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0x2c000000);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+    /* Interrupts [42:0] are from the motherboard;
+     * [47:43] are reserved; [63:48] are daughterboard
+     * peripherals. Note that some documentation numbers
+     * external interrupts starting from 32 (because there
+     * are internal interrupts 0..31).
+     */
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    /* A15 daughterboard peripherals: */
+
+    /* 0x20000000: CoreSight interfaces: not modelled */
+    /* 0x2a000000: PL301 AXI interconnect: not modelled */
+    /* 0x2a420000: SCC: not modelled */
+    /* 0x2a430000: system counter: not modelled */
+    /* 0x2b000000: HDLCD controller: not modelled */
+    /* 0x2b060000: SP805 watchdog: not modelled */
+    /* 0x2b0a0000: PL341 dynamic memory controller: not modelled */
+    /* 0x2e000000: system SRAM */
+    memory_region_init_ram(sram, "vexpress.a15sram", 0x10000);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(sysmem, 0x2e000000, sram);
+
+    /* 0x7ffb0000: DMA330 DMA controller: not modelled */
+    /* 0x7ffd0000: PL354 static memory controller: not modelled */
+}
+
+static const VEDBoardInfo a15_daughterboard = {
+    .motherboard_map = motherboard_aseries_map,
+    .loader_start = 0x80000000,
+    .gic_cpu_if_addr = 0x2c002000,
+    .init = a15_daughterboard_init,
+};
+
 static void vexpress_common_init(const VEDBoardInfo *daughterboard,
                                  ram_addr_t ram_size,
                                  const char *boot_device,
@@ -333,6 +453,18 @@ static void vexpress_a9_init(ram_addr_t ram_size,
                          kernel_cmdline, initrd_filename, cpu_model);
 }
 
+static void vexpress_a15_init(ram_addr_t ram_size,
+                              const char *boot_device,
+                              const char *kernel_filename,
+                              const char *kernel_cmdline,
+                              const char *initrd_filename,
+                              const char *cpu_model)
+{
+    vexpress_common_init(&a15_daughterboard,
+                         ram_size, boot_device, kernel_filename,
+                         kernel_cmdline, initrd_filename, cpu_model);
+}
+
 static QEMUMachine vexpress_a9_machine = {
     .name = "vexpress-a9",
     .desc = "ARM Versatile Express for Cortex-A9",
@@ -341,9 +473,18 @@ static QEMUMachine vexpress_a9_machine = {
     .max_cpus = 4,
 };
 
+static QEMUMachine vexpress_a15_machine = {
+    .name = "vexpress-a15",
+    .desc = "ARM Versatile Express for Cortex-A15",
+    .init = vexpress_a15_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+};
+
 static void vexpress_machine_init(void)
 {
     qemu_register_machine(&vexpress_a9_machine);
+    qemu_register_machine(&vexpress_a15_machine);
 }
 
 machine_init(vexpress_machine_init);
-- 
1.7.1

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

* Re: [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15
  2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
                   ` (11 preceding siblings ...)
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 12/12] hw/vexpress.c: Add vexpress-a15 machine Peter Maydell
@ 2012-01-13 20:57 ` Peter Maydell
  2012-01-15 22:56   ` [Qemu-devel] [Android-virt] " Christoffer Dall
  12 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2012-01-13 20:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

On 13 January 2012 20:52, Peter Maydell <peter.maydell@linaro.org> wrote:
> This patchset adds support for (a rather limited version of) the
> Cortex-A15 CPU and the Versatile Express A15 daughterboard.
> The resulting model is capable of booting a Linux kernel which has
> been configured for Cortex-A15 with the Versatile Express "extended
> memory map" and without support for LPAE.

> PS for the folk on android-virt: I haven't yet tested these patches
> with KVM, only with TCG, but there is no inherent reason for them
> not to work...

PPS: these patches are against qemu-master so for kvm you'd need
to (a) rebase them on qemu-linaro (b) put the kvm patches on top
of these (c) wait for me to do a. for you ;-)

-- PMM

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

* Re: [Qemu-devel] [Android-virt] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15
  2012-01-13 20:57 ` [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
@ 2012-01-15 22:56   ` Christoffer Dall
  2012-01-17 19:08     ` Peter Maydell
  0 siblings, 1 reply; 39+ messages in thread
From: Christoffer Dall @ 2012-01-15 22:56 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, android-virt, patches

On Fri, Jan 13, 2012 at 3:57 PM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 13 January 2012 20:52, Peter Maydell <peter.maydell@linaro.org> wrote:
>> This patchset adds support for (a rather limited version of) the
>> Cortex-A15 CPU and the Versatile Express A15 daughterboard.
>> The resulting model is capable of booting a Linux kernel which has
>> been configured for Cortex-A15 with the Versatile Express "extended
>> memory map" and without support for LPAE.
>
>> PS for the folk on android-virt: I haven't yet tested these patches
>> with KVM, only with TCG, but there is no inherent reason for them
>> not to work...
>
> PPS: these patches are against qemu-master so for kvm you'd need
> to (a) rebase them on qemu-linaro (b) put the kvm patches on top
> of these (c) wait for me to do a. for you ;-)
>

ok, I'll test this with the most recent KVM changes soon and also look
forward for your merge... :)

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

* Re: [Qemu-devel] [Android-virt] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop Peter Maydell
@ 2012-01-16  1:56   ` Alexander Graf
  2012-01-16  8:31     ` Peter Maydell
  2012-01-17  1:16   ` [Qemu-devel] " andrzej zaborowski
  1 sibling, 1 reply; 39+ messages in thread
From: Alexander Graf @ 2012-01-16  1:56 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, android-virt, patches


On 13.01.2012, at 21:52, Peter Maydell wrote:

> From: Evgeny Voevodin <e.voevodin@samsung.com>
> 
> The secondary CPU bootloader in arm_boot.c holds secondary CPUs in a
> pen until the primary CPU releases them. Make boards specify the
> address to be polled to determine whether to leave the pen (it was
> previously hardcoded to 0x10000030, which is a Versatile Express/
> Realview specific system register address).

Is smp_boot implementing the same logic as hw/ppce500_spin.c? It looks like the normal u-boot way of waiting for a magic address to be written with boot info. What I don't understand is the WFI. How can you wait for an interrupt if the trigger is a memory write? Or are you actually getting IPIs?


Alex

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

* Re: [Qemu-devel] [Android-virt] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop
  2012-01-16  1:56   ` [Qemu-devel] [Android-virt] " Alexander Graf
@ 2012-01-16  8:31     ` Peter Maydell
  2012-01-16 23:31       ` andrzej zaborowski
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2012-01-16  8:31 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-devel, android-virt, patches

On 16 January 2012 01:56, Alexander Graf <agraf@suse.de> wrote:
>
> On 13.01.2012, at 21:52, Peter Maydell wrote:
>
>> From: Evgeny Voevodin <e.voevodin@samsung.com>
>>
>> The secondary CPU bootloader in arm_boot.c holds secondary CPUs in a
>> pen until the primary CPU releases them. Make boards specify the
>> address to be polled to determine whether to leave the pen (it was
>> previously hardcoded to 0x10000030, which is a Versatile Express/
>> Realview specific system register address).
>
> Is smp_boot implementing the same logic as hw/ppce500_spin.c? It
> looks like the normal u-boot way of waiting for a magic address
> to be written with boot info. What I don't understand is the WFI.
> How can you wait for an interrupt if the trigger is a memory
> write? Or are you actually getting IPIs?

Basically this code is implementing the boot-rom half of
what is technically a platform-specific contract[*] between
the boot rom and the Linux kernel. The kernel end has to
(a) write the secondary CPU's entry point into the register
being polled and (b) send the CPU a softirq (an IPI, in
other words). The WFI basically allows h/w to avoid running
3 cores at 100% when we're booting a uniprocessor OS.
So the arm_boot end has to (a) enable the CPU's interrupt
controller, (b) wait for interrupt, (c) get the entry point
and jump to it.

[*] realview, vexpress, highbank and exynos4 all do something
that's sufficiently similar that we can handle them all by
parameterising the secondary boot code a bit. omap is kinda
different but then we don't support -kernel with omap anyway.

-- PMM

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

* Re: [Qemu-devel] [Android-virt] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop
  2012-01-16  8:31     ` Peter Maydell
@ 2012-01-16 23:31       ` andrzej zaborowski
  2012-01-16 23:41         ` Peter Maydell
  0 siblings, 1 reply; 39+ messages in thread
From: andrzej zaborowski @ 2012-01-16 23:31 UTC (permalink / raw)
  To: Peter Maydell; +Cc: patches, Alexander Graf, android-virt, qemu-devel

On 16 January 2012 09:31, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 16 January 2012 01:56, Alexander Graf <agraf@suse.de> wrote:
>>
>> On 13.01.2012, at 21:52, Peter Maydell wrote:
>>
>>> From: Evgeny Voevodin <e.voevodin@samsung.com>
>>>
>>> The secondary CPU bootloader in arm_boot.c holds secondary CPUs in a
>>> pen until the primary CPU releases them. Make boards specify the
>>> address to be polled to determine whether to leave the pen (it was
>>> previously hardcoded to 0x10000030, which is a Versatile Express/
>>> Realview specific system register address).
>>
>> Is smp_boot implementing the same logic as hw/ppce500_spin.c? It
>> looks like the normal u-boot way of waiting for a magic address
>> to be written with boot info. What I don't understand is the WFI.
>> How can you wait for an interrupt if the trigger is a memory
>> write? Or are you actually getting IPIs?
>
> Basically this code is implementing the boot-rom half of
> what is technically a platform-specific contract[*] between
> the boot rom and the Linux kernel. The kernel end has to
> (a) write the secondary CPU's entry point into the register
> being polled and (b) send the CPU a softirq (an IPI, in
> other words). The WFI basically allows h/w to avoid running
> 3 cores at 100% when we're booting a uniprocessor OS.
> So the arm_boot end has to (a) enable the CPU's interrupt
> controller, (b) wait for interrupt, (c) get the entry point
> and jump to it.
>
> [*] realview, vexpress, highbank and exynos4 all do something
> that's sufficiently similar that we can handle them all by
> parameterising the secondary boot code a bit. omap is kinda
> different but then we don't support -kernel with omap anyway.

In the last sentence you mean the SMP case, right?

Cheers

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

* Re: [Qemu-devel] [Android-virt] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop
  2012-01-16 23:31       ` andrzej zaborowski
@ 2012-01-16 23:41         ` Peter Maydell
  0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-16 23:41 UTC (permalink / raw)
  To: andrzej zaborowski; +Cc: patches, Alexander Graf, android-virt, qemu-devel

On 16 January 2012 23:31, andrzej zaborowski <balrogg@gmail.com> wrote:
> On 16 January 2012 09:31, Peter Maydell <peter.maydell@linaro.org> wrote:
>> [*] realview, vexpress, highbank and exynos4 all do something
>> that's sufficiently similar that we can handle them all by
>> parameterising the secondary boot code a bit. omap is kinda
>> different but then we don't support -kernel with omap anyway.
>
> In the last sentence you mean the SMP case, right?

Hmm, I think I was a bit confused there. So (a) you're right that
the non-SMP case doesn't have a platform dependency so it will
work on anything that wants to call arm_load_kernel (including
omap boards). (b) omap1-3 are all single core anyhow, and I don't
know of anybody who's proposing to write an omap4 model right now
(c) the currently-out-of-tree omap3 models don't call arm_load_kernel
but instead have a model of the omap3 boot rom and just boot from
SD card images like the real hardware. [It's (c) that I was vaguely
thinking of when I wrote that remark.]

-- PMM

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

* Re: [Qemu-devel] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop Peter Maydell
  2012-01-16  1:56   ` [Qemu-devel] [Android-virt] " Alexander Graf
@ 2012-01-17  1:16   ` andrzej zaborowski
  1 sibling, 0 replies; 39+ messages in thread
From: andrzej zaborowski @ 2012-01-17  1:16 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, android-virt, patches

On 13 January 2012 21:52, Peter Maydell <peter.maydell@linaro.org> wrote:
> From: Evgeny Voevodin <e.voevodin@samsung.com>
>
> The secondary CPU bootloader in arm_boot.c holds secondary CPUs in a
> pen until the primary CPU releases them. Make boards specify the
> address to be polled to determine whether to leave the pen (it was
> previously hardcoded to 0x10000030, which is a Versatile Express/
> Realview specific system register address).

I applied this patch out of the series to reduce cross dependency, thanks.

Cheers

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

* Re: [Qemu-devel] [Android-virt] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15
  2012-01-15 22:56   ` [Qemu-devel] [Android-virt] " Christoffer Dall
@ 2012-01-17 19:08     ` Peter Maydell
  2012-01-27 10:28       ` Marc Zyngier
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2012-01-17 19:08 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: qemu-devel, android-virt, patches

On 15 January 2012 22:56, Christoffer Dall <cdall@cs.columbia.edu> wrote:
> On Fri, Jan 13, 2012 at 3:57 PM, Peter Maydell <peter.maydell@linaro.org> wrote:
>> PPS: these patches are against qemu-master so for kvm you'd need
>> to (a) rebase them on qemu-linaro (b) put the kvm patches on top
>> of these (c) wait for me to do a. for you ;-)
>
> ok, I'll test this with the most recent KVM changes soon and also look
> forward for your merge... :)

vexpress-a15 now in qemu-linaro git tree. However it doesn't boot under
KVM:

root@LinaroE102767:~# /usr/local/bin/qemu-system-arm  -enable-kvm
-kernel /a15-no-lpae-uImage  -m 128 -serial stdio -drive
if=sd,file=/maz/vex
press.img -M vexpress-a15 -display none -append "console=ttyAMA0
earlyprintk rootwait mem=128M root=/dev/mmcblk0p2 rw --debug"
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0
Linux version 3.1.0+ (petmay01@LinaroE102767) (gcc version 4.6.1
(Ubuntu/Linaro 4.6.1-9ubuntu3) ) #19 SMP Fri Jan 13 12:23:22 GMT 2012
CPU: ARMv7 Processor [412fc0f1] revision 1 (ARMv7), cr=10c5387f
CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
Machine: ARM-Versatile Express
SoC: ARM VE Platform
bootconsole [earlycon0] enabled
Memory policy: ECC disabled, Data cache writealloc
error: kvm run failed Invalid argument
Aborted

Under TCG the next thing printed is
ct_ca15x4_init_cpu_map: ncores 1
Architected timer frequency not available
sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 178956ms

...possibly the kernel side needs to implement the A15 L2 cache control
register, which is where the guest kernel picks up the number of cores
from; see patch 10 for the TCG version.

-- PMM

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

* Re: [Qemu-devel] [Android-virt] [PATCH 10/12] Add Cortex-A15 CPU definition
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 10/12] Add Cortex-A15 CPU definition Peter Maydell
@ 2012-01-23 18:12   ` Peter Maydell
  2012-01-24  7:59   ` [Qemu-devel] " Andreas Färber
  1 sibling, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-23 18:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: android-virt, patches

Ping. Unless anybody has any review comments on this or patch 9 (generic
timer dummy implementation) I plan to put them into my target-arm.next
queue and send out a pullreq later this week.

-- PMM

On 13 January 2012 20:52, Peter Maydell <peter.maydell@linaro.org> wrote:
> Add a definition of a Cortex-A15 CPU. Note that for the moment we do
> not implement any of:
>  * Large Physical Address Extensions (LPAE)
>  * Virtualization Extensions
>  * Generic Timer
>  * TrustZone (this is also true of our existing Cortex-A9 model, etc)
>
> This CPU model is sufficient to boot a Linux kernel which has been
> compiled for an A15 without LPAE enabled.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target-arm/cpu.h    |    1 +
>  target-arm/helper.c |   56 ++++++++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 52 insertions(+), 5 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index d5403ea..4b8d680 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -433,6 +433,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
>  #define ARM_CPUID_CORTEXA8    0x410fc080
>  #define ARM_CPUID_CORTEXA9    0x410fc090
>  #define ARM_CPUID_CORTEXM3    0x410fc231
> +#define ARM_CPUID_CORTEXA15   0x412fc0f1
>  #define ARM_CPUID_ANY         0xffffffff
>
>  #if defined(CONFIG_USER_ONLY)
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index de4a50f..a68dc5c 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -10,6 +10,16 @@
>  #if !defined(CONFIG_USER_ONLY)
>  #include "hw/loader.h"
>  #endif
> +#include "sysemu.h"
> +
> +static uint32_t cortexa15_cp15_c0_c1[8] = {
> +    0x00001131, 0x00011011, 0x02010555, 0x00000000,
> +    0x10201105, 0x20000000, 0x01240000, 0x02102211
> +};
> +
> +static uint32_t cortexa15_cp15_c0_c2[8] = {
> +    0x02101110, 0x13112111, 0x21232041, 0x11112131, 0x10011142, 0, 0, 0
> +};
>
>  static uint32_t cortexa9_cp15_c0_c1[8] =
>  { 0x1031, 0x11, 0x000, 0, 0x00100103, 0x20000000, 0x01230000, 0x00002111 };
> @@ -158,6 +168,27 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
>         env->cp15.c0_ccsid[1] = 0x200fe015; /* 16k L1 icache. */
>         env->cp15.c1_sys = 0x00c50078;
>         break;
> +    case ARM_CPUID_CORTEXA15:
> +        set_feature(env, ARM_FEATURE_V7);
> +        set_feature(env, ARM_FEATURE_VFP4);
> +        set_feature(env, ARM_FEATURE_VFP_FP16);
> +        set_feature(env, ARM_FEATURE_NEON);
> +        set_feature(env, ARM_FEATURE_THUMB2EE);
> +        set_feature(env, ARM_FEATURE_ARM_DIV);
> +        set_feature(env, ARM_FEATURE_V7MP);
> +        set_feature(env, ARM_FEATURE_GENERICTIMER);
> +        env->vfp.xregs[ARM_VFP_FPSID] = 0x410430f0;
> +        env->vfp.xregs[ARM_VFP_MVFR0] = 0x10110222;
> +        env->vfp.xregs[ARM_VFP_MVFR1] = 0x11111111;
> +        memcpy(env->cp15.c0_c1, cortexa15_cp15_c0_c1, 8 * sizeof(uint32_t));
> +        memcpy(env->cp15.c0_c2, cortexa15_cp15_c0_c2, 8 * sizeof(uint32_t));
> +        env->cp15.c0_cachetype = 0x8444c004;
> +        env->cp15.c0_clid = 0x0a200023;
> +        env->cp15.c0_ccsid[0] = 0x701fe00a; /* 32K L1 dcache */
> +        env->cp15.c0_ccsid[1] = 0x201fe00a; /* 32K L1 icache */
> +        env->cp15.c0_ccsid[2] = 0x711fe07a; /* 4096K L2 unified cache */
> +        env->cp15.c1_sys = 0x00c50078;
> +        break;
>     case ARM_CPUID_CORTEXM3:
>         set_feature(env, ARM_FEATURE_V7);
>         set_feature(env, ARM_FEATURE_M);
> @@ -413,6 +444,7 @@ static const struct arm_cpu_t arm_cpu_names[] = {
>     { ARM_CPUID_CORTEXM3, "cortex-m3"},
>     { ARM_CPUID_CORTEXA8, "cortex-a8"},
>     { ARM_CPUID_CORTEXA9, "cortex-a9"},
> +    { ARM_CPUID_CORTEXA15, "cortex-a15"},
>     { ARM_CPUID_TI925T, "ti925t" },
>     { ARM_CPUID_PXA250, "pxa250" },
>     { ARM_CPUID_SA1100,    "sa1100" },
> @@ -667,8 +699,6 @@ uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
>
>  #else
>
> -extern int semihosting_enabled;
> -
>  /* Map CPU modes onto saved register banks.  */
>  static inline int bank_number(CPUState *env, int mode)
>  {
> @@ -1934,6 +1964,7 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
>             case ARM_CPUID_CORTEXA8:
>                 return 2;
>             case ARM_CPUID_CORTEXA9:
> +            case ARM_CPUID_CORTEXA15:
>                 return 0;
>             default:
>                 goto bad_reg;
> @@ -2054,11 +2085,26 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
>                     goto bad_reg;
>                 }
>             case 1: /* L2 cache */
> -                if (crm != 0) {
> +                /* L2 Lockdown and Auxiliary control.  */
> +                switch (op2) {
> +                case 0:
> +                    /* L2 cache lockdown (A8 only) */
> +                    return 0;
> +                case 2:
> +                    /* L2 cache auxiliary control (A8) or control (A15) */
> +                    if (ARM_CPUID(env) == ARM_CPUID_CORTEXA15) {
> +                        /* Linux wants the number of processors from here.
> +                         * Might as well set the interrupt-controller bit too.
> +                         */
> +                        return ((smp_cpus - 1) << 24) | (1 << 23);
> +                    }
> +                    return 0;
> +                case 3:
> +                    /* L2 cache extended control (A15) */
> +                    return 0;
> +                default:
>                     goto bad_reg;
>                 }
> -                /* L2 Lockdown and Auxiliary control.  */
> -                return 0;
>             default:
>                 goto bad_reg;
>             }
> --
> 1.7.1
>
> _______________________________________________
> Android-virt mailing list
> Android-virt@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/cucslists/listinfo/android-virt

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

* Re: [Qemu-devel] [PATCH 10/12] Add Cortex-A15 CPU definition
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 10/12] Add Cortex-A15 CPU definition Peter Maydell
  2012-01-23 18:12   ` [Qemu-devel] [Android-virt] " Peter Maydell
@ 2012-01-24  7:59   ` Andreas Färber
  2012-01-24  8:33     ` Peter Maydell
  1 sibling, 1 reply; 39+ messages in thread
From: Andreas Färber @ 2012-01-24  7:59 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, android-virt, patches

Am 13.01.2012 21:52, schrieb Peter Maydell:
> Add a definition of a Cortex-A15 CPU. Note that for the moment we do
> not implement any of:
>  * Large Physical Address Extensions (LPAE)
>  * Virtualization Extensions
>  * Generic Timer
>  * TrustZone (this is also true of our existing Cortex-A9 model, etc)
> 
> This CPU model is sufficient to boot a Linux kernel which has been
> compiled for an A15 without LPAE enabled.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target-arm/cpu.h    |    1 +
>  target-arm/helper.c |   56 ++++++++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 52 insertions(+), 5 deletions(-)
> 
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index d5403ea..4b8d680 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -433,6 +433,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
>  #define ARM_CPUID_CORTEXA8    0x410fc080
>  #define ARM_CPUID_CORTEXA9    0x410fc090
>  #define ARM_CPUID_CORTEXM3    0x410fc231
> +#define ARM_CPUID_CORTEXA15   0x412fc0f1

Reminder of our rnpn topic...

We don't seem to have a clear ordering system but I'd suggest to move
A15 one line up, to group the As and Ms in ascending order respectively.

>  #define ARM_CPUID_ANY         0xffffffff
>  
>  #if defined(CONFIG_USER_ONLY)
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index de4a50f..a68dc5c 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -10,6 +10,16 @@
>  #if !defined(CONFIG_USER_ONLY)
>  #include "hw/loader.h"
>  #endif
> +#include "sysemu.h"
> +
> +static uint32_t cortexa15_cp15_c0_c1[8] = {
> +    0x00001131, 0x00011011, 0x02010555, 0x00000000,
> +    0x10201105, 0x20000000, 0x01240000, 0x02102211
> +};
> +
> +static uint32_t cortexa15_cp15_c0_c2[8] = {
> +    0x02101110, 0x13112111, 0x21232041, 0x11112131, 0x10011142, 0, 0, 0
> +};
>  
>  static uint32_t cortexa9_cp15_c0_c1[8] =
>  { 0x1031, 0x11, 0x000, 0, 0x00100103, 0x20000000, 0x01230000, 0x00002111 };
> @@ -158,6 +168,27 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
>          env->cp15.c0_ccsid[1] = 0x200fe015; /* 16k L1 icache. */
>          env->cp15.c1_sys = 0x00c50078;
>          break;
> +    case ARM_CPUID_CORTEXA15:
> +        set_feature(env, ARM_FEATURE_V7);
> +        set_feature(env, ARM_FEATURE_VFP4);
> +        set_feature(env, ARM_FEATURE_VFP_FP16);
> +        set_feature(env, ARM_FEATURE_NEON);
> +        set_feature(env, ARM_FEATURE_THUMB2EE);
> +        set_feature(env, ARM_FEATURE_ARM_DIV);
> +        set_feature(env, ARM_FEATURE_V7MP);
> +        set_feature(env, ARM_FEATURE_GENERICTIMER);

Features look sane.

> @@ -413,6 +444,7 @@ static const struct arm_cpu_t arm_cpu_names[] = {
>      { ARM_CPUID_CORTEXM3, "cortex-m3"},
>      { ARM_CPUID_CORTEXA8, "cortex-a8"},
>      { ARM_CPUID_CORTEXA9, "cortex-a9"},
> +    { ARM_CPUID_CORTEXA15, "cortex-a15"},

Space please.

>      { ARM_CPUID_TI925T, "ti925t" },
>      { ARM_CPUID_PXA250, "pxa250" },
>      { ARM_CPUID_SA1100,    "sa1100" },
> @@ -667,8 +699,6 @@ uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
>  
>  #else
>  
> -extern int semihosting_enabled;
> -
>  /* Map CPU modes onto saved register banks.  */
>  static inline int bank_number(CPUState *env, int mode)
>  {
> @@ -1934,6 +1964,7 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
>              case ARM_CPUID_CORTEXA8:
>                  return 2;
>              case ARM_CPUID_CORTEXA9:
> +            case ARM_CPUID_CORTEXA15:
>                  return 0;
>              default:
>                  goto bad_reg;
> @@ -2054,11 +2085,26 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
>                      goto bad_reg;
>                  }
>              case 1: /* L2 cache */
> -                if (crm != 0) {
> +                /* L2 Lockdown and Auxiliary control.  */
> +                switch (op2) {
> +                case 0:
> +                    /* L2 cache lockdown (A8 only) */
> +                    return 0;
> +                case 2:
> +                    /* L2 cache auxiliary control (A8) or control (A15) */
> +                    if (ARM_CPUID(env) == ARM_CPUID_CORTEXA15) {

Change of mind? You opposed uses of ARM_CPUID() for Cortex-R4F.

Andreas

> +                        /* Linux wants the number of processors from here.
> +                         * Might as well set the interrupt-controller bit too.
> +                         */
> +                        return ((smp_cpus - 1) << 24) | (1 << 23);
> +                    }
> +                    return 0;
> +                case 3:
> +                    /* L2 cache extended control (A15) */
> +                    return 0;
> +                default:
>                      goto bad_reg;
>                  }
> -                /* L2 Lockdown and Auxiliary control.  */
> -                return 0;
>              default:
>                  goto bad_reg;
>              }

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PATCH 10/12] Add Cortex-A15 CPU definition
  2012-01-24  7:59   ` [Qemu-devel] " Andreas Färber
@ 2012-01-24  8:33     ` Peter Maydell
  0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-24  8:33 UTC (permalink / raw)
  To: Andreas Färber; +Cc: qemu-devel, android-virt, patches

On 24 January 2012 07:59, Andreas Färber <afaerber@suse.de> wrote:
> Am 13.01.2012 21:52, schrieb Peter Maydell:
>> @@ -433,6 +433,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
>>  #define ARM_CPUID_CORTEXA8    0x410fc080
>>  #define ARM_CPUID_CORTEXA9    0x410fc090
>>  #define ARM_CPUID_CORTEXM3    0x410fc231
>> +#define ARM_CPUID_CORTEXA15   0x412fc0f1
>
> Reminder of our rnpn topic...

Yeah. I have a cp15-rework series brewing that might assist here.

> We don't seem to have a clear ordering system but I'd suggest to move
> A15 one line up, to group the As and Ms in ascending order respectively.

Good idea.

>> @@ -413,6 +444,7 @@ static const struct arm_cpu_t arm_cpu_names[] = {
>>      { ARM_CPUID_CORTEXM3, "cortex-m3"},
>>      { ARM_CPUID_CORTEXA8, "cortex-a8"},
>>      { ARM_CPUID_CORTEXA9, "cortex-a9"},
>> +    { ARM_CPUID_CORTEXA15, "cortex-a15"},
>
> Space please.

OK. (I just copy-pasted the a9 line, as you've probably guessed.)

>> +                case 2:
>> +                    /* L2 cache auxiliary control (A8) or control (A15) */
>> +                    if (ARM_CPUID(env) == ARM_CPUID_CORTEXA15) {
>
> Change of mind? You opposed uses of ARM_CPUID() for Cortex-R4F.

I kind of view this as a small interim bodge. My aim with my
cp15 rework is that instead of all these switches we will
just set up the cp15 registers for the CPU at cpu_init
time, so A15 will set up one thing, A8 something else and
A9 et al set up nothing at all [and so get the default UNDEF
behaviour].

If you can fish the particular mail of mine you have in mind
out of the archives I can reread it and see if I disagree
with myself :-)

-- PMM

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

* Re: [Qemu-devel] [Android-virt] [PATCH 02/12] arm: make the number of GIC interrupts configurable
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 02/12] arm: make the number of GIC interrupts configurable Peter Maydell
@ 2012-01-24  8:42   ` Rusty Russell
  2012-01-25 15:09     ` Peter Maydell
  2012-02-21  2:33   ` [Qemu-devel] [PATCH 2/2] " Rusty Russell
  1 sibling, 1 reply; 39+ messages in thread
From: Rusty Russell @ 2012-01-24  8:42 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: android-virt, patches

On Fri, 13 Jan 2012 20:52:39 +0000, Peter Maydell <peter.maydell@linaro.org> wrote:
> From: Mark Langsdorf <mark.langsdorf@calxeda.com>
> 
> Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
> and create a configurable property for each defaulting to 96 and 64
> (respectively) so that device modelers can set the value appropriately
> for their SoC. Other ARM processors also set their maximum number of
> used IRQs appropriately.
> 
> Set the maximum theoretical number of GIC interrupts to 1020 and
> update the save/restore code to only use the appropriate number for
> each SoC.

Reading through this, I see a lot of "- 32".  Trivial patch follows,
which applies to your rebasing branch:

Subject: ARM: clean up GIC constants.
From: Rusty Russell <rusty@rustcorp.com.au>

Interrupts numbers 0-31 are private to the processor interface, 32-1019 are
general interrups.  Add GIC_INTERNAL and substitute everywhere.

Also, add a check that the total number of interrupts is divisible by
32 (required for reporting interupt numbers, see gic_dist_readb(), and
is greater than 32.  And remove a single stray tab.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 hw/arm_gic.c |   48 ++++++++++++++++++++++++++----------------------
 1 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index cf582a5..a29eacb 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -13,6 +13,8 @@
 
 /* Maximum number of possible interrupts, determined by the GIC architecture */
 #define GIC_MAXIRQ 1020
+/* First 32 are private to each CPU (SGIs and PPIs). */
+#define GIC_INTERNAL 32
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -74,7 +76,7 @@ typedef struct gic_irq_state
 #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
 #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
 #define GIC_GET_PRIORITY(irq, cpu) \
-  (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
+  (((irq) < GIC_INTERNAL) ? s->priority1[irq][cpu] : s->priority2[(irq) - GIC_INTERNAL])
 #ifdef NVIC
 #define GIC_TARGET(irq) 1
 #else
@@ -92,8 +94,8 @@ typedef struct gic_state
 #ifndef NVIC
     int irq_target[GIC_MAXIRQ];
 #endif
-    int priority1[32][NCPU];
-    int priority2[GIC_MAXIRQ - 32];
+    int priority1[GIC_INTERNAL][NCPU];
+    int priority2[GIC_MAXIRQ - GIC_INTERNAL];
     int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
@@ -131,7 +133,7 @@ static void gic_update(gic_state *s)
         cm = 1 << cpu;
         s->current_pending[cpu] = 1023;
         if (!s->enabled || !s->cpu_enabled[cpu]) {
-	    qemu_irq_lower(s->parent_irq[cpu]);
+            qemu_irq_lower(s->parent_irq[cpu]);
             return;
         }
         best_prio = 0x100;
@@ -174,7 +176,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
 {
     gic_state *s = (gic_state *)opaque;
     /* The first external input line is internal interrupt 32.  */
-    irq += 32;
+    irq += GIC_INTERNAL;
     if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
         return;
 
@@ -316,7 +318,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
-        mask = (irq < 32) ?  cm : ALL_CPU_MASK;
+        mask = (irq < GIC_INTERNAL) ?  cm : ALL_CPU_MASK;
         for (i = 0; i < 8; i++) {
             if (GIC_TEST_PENDING(irq + i, mask)) {
                 res |= (1 << i);
@@ -328,7 +330,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
-        mask = (irq < 32) ?  cm : ALL_CPU_MASK;
+        mask = (irq < GIC_INTERNAL) ?  cm : ALL_CPU_MASK;
         for (i = 0; i < 8; i++) {
             if (GIC_TEST_ACTIVE(irq + i, mask)) {
                 res |= (1 << i);
@@ -435,8 +437,8 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
           value = 0xff;
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
-                int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
+                int mask = (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq);
+                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 
                 if (!GIC_TEST_ENABLED(irq + i, cm)) {
                     DPRINTF("Enabled IRQ %d\n", irq + i);
@@ -460,7 +462,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
           value = 0;
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
+                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 
                 if (GIC_TEST_ENABLED(irq + i, cm)) {
                     DPRINTF("Disabled IRQ %d\n", irq + i);
@@ -502,10 +504,10 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
         irq = (offset - 0x400) + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 32) {
+        if (irq < GIC_INTERNAL) {
             s->priority1[irq][cpu] = value;
         } else {
-            s->priority2[irq - 32] = value;
+            s->priority2[irq - GIC_INTERNAL] = value;
         }
 #ifndef NVIC
     } else if (offset < 0xc00) {
@@ -515,7 +517,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
             goto bad_reg;
         if (irq < 29)
             value = 0;
-        else if (irq < 32)
+        else if (irq < GIC_INTERNAL)
             value = ALL_CPU_MASK;
         s->irq_target[irq] = value & ALL_CPU_MASK;
     } else if (offset < 0xf00) {
@@ -523,7 +525,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 32)
+        if (irq < GIC_INTERNAL)
             value |= 0xaa;
         for (i = 0; i < 4; i++) {
             if (value & (1 << (i * 2))) {
@@ -736,7 +738,7 @@ static void gic_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, s->enabled);
     for (i = 0; i < NUM_CPU(s); i++) {
         qemu_put_be32(f, s->cpu_enabled[i]);
-        for (j = 0; j < 32; j++)
+        for (j = 0; j < GIC_INTERNAL; j++)
             qemu_put_be32(f, s->priority1[j][i]);
         for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
@@ -745,7 +747,7 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < s->num_irq - 32; i++) {
+    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
     for (i = 0; i < s->num_irq; i++) {
@@ -773,7 +775,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
     s->enabled = qemu_get_be32(f);
     for (i = 0; i < NUM_CPU(s); i++) {
         s->cpu_enabled[i] = qemu_get_be32(f);
-        for (j = 0; j < 32; j++)
+        for (j = 0; j < GIC_INTERNAL; j++)
             s->priority1[j][i] = qemu_get_be32(f);
         for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
@@ -782,7 +784,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < s->num_irq - 32; i++) {
+    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
     for (i = 0; i < s->num_irq; i++) {
@@ -812,11 +814,13 @@ static void gic_init(gic_state *s, int num_irq)
     s->num_cpu = num_cpu;
 #endif
     s->num_irq = num_irq + GIC_BASE_IRQ;
-    if (s->num_irq > GIC_MAXIRQ) {
-        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
-                 num_irq, GIC_MAXIRQ);
+    if (s->num_irq > GIC_MAXIRQ
+        || s->num_irq < GIC_INTERNAL
+        || (s->num_irq % 32) != 0) {
+        hw_error("requested %u interrupt lines outside GIC range %d-%d\n",
+                 num_irq, GIC_INTERNAL, GIC_MAXIRQ);
     }
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }

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

* Re: [Qemu-devel] [Android-virt] [PATCH 02/12] arm: make the number of GIC interrupts configurable
  2012-01-24  8:42   ` [Qemu-devel] [Android-virt] " Rusty Russell
@ 2012-01-25 15:09     ` Peter Maydell
  2012-01-27  0:33       ` Rusty Russell
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2012-01-25 15:09 UTC (permalink / raw)
  To: Rusty Russell; +Cc: qemu-devel, android-virt, patches

On 24 January 2012 08:42, Rusty Russell <rusty@rustcorp.com.au> wrote:
> On Fri, 13 Jan 2012 20:52:39 +0000, Peter Maydell <peter.maydell@linaro.org> wrote:
>> From: Mark Langsdorf <mark.langsdorf@calxeda.com>
>>
>> Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
>> and create a configurable property for each defaulting to 96 and 64
>> (respectively) so that device modelers can set the value appropriately
>> for their SoC. Other ARM processors also set their maximum number of
>> used IRQs appropriately.
>>
>> Set the maximum theoretical number of GIC interrupts to 1020 and
>> update the save/restore code to only use the appropriate number for
>> each SoC.
>
> Reading through this, I see a lot of "- 32".  Trivial patch follows,
> which applies to your rebasing branch:

(If you send patches as fresh new emails then they just apply
with git am without needing manual cleanup, appear with sensible
subjects in patchwork/patches.linaro, etc.)

> Subject: ARM: clean up GIC constants.
> From: Rusty Russell <rusty@rustcorp.com.au>
>
> Interrupts numbers 0-31 are private to the processor interface, 32-1019 are
> general interrups.  Add GIC_INTERNAL and substitute everywhere.
>
> Also, add a check that the total number of interrupts is divisible by
> 32 (required for reporting interupt numbers, see gic_dist_readb(), and
> is greater than 32.  And remove a single stray tab.

I agree with Avi that the presence of "Also" in a git
commit message is generally a sign you should have submitted
more than one patch :-)

> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
> ---
>  hw/arm_gic.c |   48 ++++++++++++++++++++++++++----------------------
>  1 files changed, 26 insertions(+), 22 deletions(-)
>
> diff --git a/hw/arm_gic.c b/hw/arm_gic.c
> index cf582a5..a29eacb 100644
> --- a/hw/arm_gic.c
> +++ b/hw/arm_gic.c
> @@ -13,6 +13,8 @@
>
>  /* Maximum number of possible interrupts, determined by the GIC architecture */
>  #define GIC_MAXIRQ 1020
> +/* First 32 are private to each CPU (SGIs and PPIs). */
> +#define GIC_INTERNAL 32
>  //#define DEBUG_GIC
>
>  #ifdef DEBUG_GIC
> @@ -74,7 +76,7 @@ typedef struct gic_irq_state
>  #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
>  #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
>  #define GIC_GET_PRIORITY(irq, cpu) \
> -  (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
> +  (((irq) < GIC_INTERNAL) ? s->priority1[irq][cpu] : s->priority2[(irq) - GIC_INTERNAL])

This line is now >80 characters and needs folding.
(scripts/checkpatch.pl will catch this kind of nit.)

> @@ -812,11 +814,13 @@ static void gic_init(gic_state *s, int num_irq)
>     s->num_cpu = num_cpu;
>  #endif
>     s->num_irq = num_irq + GIC_BASE_IRQ;
> -    if (s->num_irq > GIC_MAXIRQ) {
> -        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
> -                 num_irq, GIC_MAXIRQ);
> +    if (s->num_irq > GIC_MAXIRQ
> +        || s->num_irq < GIC_INTERNAL
> +        || (s->num_irq % 32) != 0) {

So I guess our implementation isn't likely to work properly for a
non-multiple-of-32 number of IRQs, but this isn't an architectural GIC
restriction. (In fact the GIC architecture spec allows the supported
interrupt IDs to not even be in a contiguous range, which we certainly
don't support...)
I also think it's architecturally permitted that not all the internal
(SPI/PPI) interrupts are implemented, ie that s->num_irq < 32 (you
have to read the GIC architecture manually quite closely to deduce
this, though).

Anyway, if we would otherwise die horribly later on we should
catch these cases, but it would be good to have at least a comment
saying that these are implementation limitations rather than
architectural ones.

Beefing up the parameter check should be a separate patch.

Otherwise OK.

-- PMM

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

* Re: [Qemu-devel] [Android-virt] [PATCH 02/12] arm: make the number of GIC interrupts configurable
  2012-01-25 15:09     ` Peter Maydell
@ 2012-01-27  0:33       ` Rusty Russell
  2012-01-27  9:01         ` Peter Maydell
                           ` (2 more replies)
  0 siblings, 3 replies; 39+ messages in thread
From: Rusty Russell @ 2012-01-27  0:33 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, android-virt, patches

On Wed, 25 Jan 2012 15:09:41 +0000, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 24 January 2012 08:42, Rusty Russell <rusty@rustcorp.com.au> wrote:
> > Reading through this, I see a lot of "- 32".  Trivial patch follows,
> > which applies to your rebasing branch:
> 
> (If you send patches as fresh new emails then they just apply
> with git am without needing manual cleanup, appear with sensible
> subjects in patchwork/patches.linaro, etc.)

Indeed, but it's so conversaionally gauche :(  I thought git am did the
Right Thing, but it doesn't, and --scissors doesn't help either (it gets
the wrong Subject line).  Oh well, I'll do it that way in future.

> > Subject: ARM: clean up GIC constants.
> > From: Rusty Russell <rusty@rustcorp.com.au>
> >
> > Interrupts numbers 0-31 are private to the processor interface, 32-1019 are
> > general interrups.  Add GIC_INTERNAL and substitute everywhere.
> >
> > Also, add a check that the total number of interrupts is divisible by
> > 32 (required for reporting interupt numbers, see gic_dist_readb(), and
> > is greater than 32.  And remove a single stray tab.
> 
> I agree with Avi that the presence of "Also" in a git
> commit message is generally a sign you should have submitted
> more than one patch :-)

Indeed, guilty as charged :)

> > Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
> > ---
> >  hw/arm_gic.c |   48 ++++++++++++++++++++++++++----------------------
> >  1 files changed, 26 insertions(+), 22 deletions(-)
> >
> > diff --git a/hw/arm_gic.c b/hw/arm_gic.c
> > index cf582a5..a29eacb 100644
> > --- a/hw/arm_gic.c
> > +++ b/hw/arm_gic.c
> > @@ -13,6 +13,8 @@
> >
> >  /* Maximum number of possible interrupts, determined by the GIC architecture */
> >  #define GIC_MAXIRQ 1020
> > +/* First 32 are private to each CPU (SGIs and PPIs). */
> > +#define GIC_INTERNAL 32
> >  //#define DEBUG_GIC
> >
> >  #ifdef DEBUG_GIC
> > @@ -74,7 +76,7 @@ typedef struct gic_irq_state
> >  #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
> >  #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
> >  #define GIC_GET_PRIORITY(irq, cpu) \
> > -  (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
> > +  (((irq) < GIC_INTERNAL) ? s->priority1[irq][cpu] : s->priority2[(irq) - GIC_INTERNAL])
> 
> This line is now >80 characters and needs folding.
> (scripts/checkpatch.pl will catch this kind of nit.)

Will do.

> > @@ -812,11 +814,13 @@ static void gic_init(gic_state *s, int num_irq)
> >     s->num_cpu = num_cpu;
> >  #endif
> >     s->num_irq = num_irq + GIC_BASE_IRQ;
> > -    if (s->num_irq > GIC_MAXIRQ) {
> > -        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
> > -                 num_irq, GIC_MAXIRQ);
> > +    if (s->num_irq > GIC_MAXIRQ
> > +        || s->num_irq < GIC_INTERNAL
> > +        || (s->num_irq % 32) != 0) {
> 
> So I guess our implementation isn't likely to work properly for a
> non-multiple-of-32 number of IRQs, but this isn't an architectural GIC
> restriction. (In fact the GIC architecture spec allows the supported
> interrupt IDs to not even be in a contiguous range, which we certainly
> don't support...)

Yes, I intuited it from here:

static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
{
...
        if (offset == 4)
            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);

If want want to support non-32-divisible # irqs, we need at least:

        ((s->num_irq + 31) / 32 - 1)

Seemed easier to have an initialization-time assert than check
everywhere else for overflows.

> I also think it's architecturally permitted that not all the internal
> (SPI/PPI) interrupts are implemented, ie that s->num_irq < 32 (you
> have to read the GIC architecture manually quite closely to deduce
> this, though).

This made me read that part of the manual... interesting.

> Anyway, if we would otherwise die horribly later on we should
> catch these cases, but it would be good to have at least a comment
> saying that these are implementation limitations rather than
> architectural ones.

Good point.  If we add an "supported" bit to each irq, we could do weird
things, but presumably ->num_irq would still correspond to
ITLinesNumber.

I don't want to put too much of an essay in there.  How's this:

        /* ITLinesNumber is represented as (N - 32) / 1.  See
          gic_dist_readb. */
        if (s->num_irq < 32 || (s->num_irq % 32)) {
                hw_error("%u interrupt lines unsupported: not divisible by 32\n",
                         num_irq);
                

> Beefing up the parameter check should be a separate patch.

Thanks, coming soon.

I should be getting access to git.linaro.org RSN, so I can post there
for easier merging.

Thanks,
Rusty.

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

* Re: [Qemu-devel] [Android-virt] [PATCH 02/12] arm: make the number of GIC interrupts configurable
  2012-01-27  0:33       ` Rusty Russell
@ 2012-01-27  9:01         ` Peter Maydell
  2012-02-19 23:06         ` [Qemu-devel] [PATCH 1/2] arm: clean up GIC constants Rusty Russell
  2012-02-19 23:07         ` [Qemu-devel] [PATCH] arm: make sure that number of irqs can be represented in GICD_TYPER Rusty Russell
  2 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-01-27  9:01 UTC (permalink / raw)
  To: Rusty Russell; +Cc: qemu-devel, android-virt, patches

On 27 January 2012 00:33, Rusty Russell <rusty@rustcorp.com.au> wrote:
> Peter Maydell wrote:
>> Anyway, if we would otherwise die horribly later on we should
>> catch these cases, but it would be good to have at least a comment
>> saying that these are implementation limitations rather than
>> architectural ones.
>
> Good point.  If we add an "supported" bit to each irq, we could do weird
> things, but presumably ->num_irq would still correspond to
> ITLinesNumber.
>
> I don't want to put too much of an essay in there.  How's this:
>
>        /* ITLinesNumber is represented as (N - 32) / 1.  See
>          gic_dist_readb. */
>        if (s->num_irq < 32 || (s->num_irq % 32)) {
>                hw_error("%u interrupt lines unsupported: not divisible by 32\n",
>                         num_irq);

I think that's a notch too terse for my taste. How about:

        /* ITLinesNumber is represented as (N - 32) / 1 (see
         * gic_dist_readb) so this is an implementation imposed
         * restriction, not an architectural one:
         */

thanks
-- PMM

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

* Re: [Qemu-devel] [Android-virt] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15
  2012-01-17 19:08     ` Peter Maydell
@ 2012-01-27 10:28       ` Marc Zyngier
  0 siblings, 0 replies; 39+ messages in thread
From: Marc Zyngier @ 2012-01-27 10:28 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Christoffer Dall, qemu-devel, android-virt, patches

On 17/01/12 19:08, Peter Maydell wrote:
> On 15 January 2012 22:56, Christoffer Dall <cdall@cs.columbia.edu> wrote:
>> On Fri, Jan 13, 2012 at 3:57 PM, Peter Maydell <peter.maydell@linaro.org> wrote:
>>> PPS: these patches are against qemu-master so for kvm you'd need
>>> to (a) rebase them on qemu-linaro (b) put the kvm patches on top
>>> of these (c) wait for me to do a. for you ;-)
>>
>> ok, I'll test this with the most recent KVM changes soon and also look
>> forward for your merge... :)
> 
> vexpress-a15 now in qemu-linaro git tree. However it doesn't boot under
> KVM:
> 
> root@LinaroE102767:~# /usr/local/bin/qemu-system-arm  -enable-kvm
> -kernel /a15-no-lpae-uImage  -m 128 -serial stdio -drive
> if=sd,file=/maz/vex
> press.img -M vexpress-a15 -display none -append "console=ttyAMA0
> earlyprintk rootwait mem=128M root=/dev/mmcblk0p2 rw --debug"
> Uncompressing Linux... done, booting the kernel.
> Booting Linux on physical CPU 0
> Linux version 3.1.0+ (petmay01@LinaroE102767) (gcc version 4.6.1
> (Ubuntu/Linaro 4.6.1-9ubuntu3) ) #19 SMP Fri Jan 13 12:23:22 GMT 2012
> CPU: ARMv7 Processor [412fc0f1] revision 1 (ARMv7), cr=10c5387f
> CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
> Machine: ARM-Versatile Express
> SoC: ARM VE Platform
> bootconsole [earlycon0] enabled
> Memory policy: ECC disabled, Data cache writealloc
> error: kvm run failed Invalid argument
> Aborted
> 
> Under TCG the next thing printed is
> ct_ca15x4_init_cpu_map: ncores 1
> Architected timer frequency not available
> sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 178956ms
> 
> ...possibly the kernel side needs to implement the A15 L2 cache control
> register, which is where the guest kernel picks up the number of cores
> from; see patch 10 for the TCG version.

I've pushed a new branch (kvm-v3.3-rc1) to my arm-platforms repo. It
contains a fix (or shall we call it a horrible hack?) for the above.

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [Qemu-devel] [PATCH 1/2] arm: clean up GIC constants.
  2012-01-27  0:33       ` Rusty Russell
  2012-01-27  9:01         ` Peter Maydell
@ 2012-02-19 23:06         ` Rusty Russell
  2012-02-20 17:27           ` Peter Maydell
  2012-02-19 23:07         ` [Qemu-devel] [PATCH] arm: make sure that number of irqs can be represented in GICD_TYPER Rusty Russell
  2 siblings, 1 reply; 39+ messages in thread
From: Rusty Russell @ 2012-02-19 23:06 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, android-virt, patches

Interrupts numbers 0-31 are private to the processor interface, 32-1019 are
general interrups.  Add GIC_INTERNAL and substitute everywhere.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index cf582a5..fa6a60a 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -13,6 +13,8 @@
 
 /* Maximum number of possible interrupts, determined by the GIC architecture */
 #define GIC_MAXIRQ 1020
+/* First 32 are private to each CPU (SGIs and PPIs). */
+#define GIC_INTERNAL 32
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -74,7 +76,7 @@ typedef struct gic_irq_state
 #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
 #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
 #define GIC_GET_PRIORITY(irq, cpu) \
-  (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
+  (((irq) < GIC_INTERNAL) ? s->priority1[irq][cpu] : s->priority2[(irq) - GIC_INTERNAL])
 #ifdef NVIC
 #define GIC_TARGET(irq) 1
 #else
@@ -92,8 +94,8 @@ typedef struct gic_state
 #ifndef NVIC
     int irq_target[GIC_MAXIRQ];
 #endif
-    int priority1[32][NCPU];
-    int priority2[GIC_MAXIRQ - 32];
+    int priority1[GIC_INTERNAL][NCPU];
+    int priority2[GIC_MAXIRQ - GIC_INTERNAL];
     int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
@@ -174,7 +176,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
 {
     gic_state *s = (gic_state *)opaque;
     /* The first external input line is internal interrupt 32.  */
-    irq += 32;
+    irq += GIC_INTERNAL;
     if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
         return;
 
@@ -316,7 +318,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
-        mask = (irq < 32) ?  cm : ALL_CPU_MASK;
+        mask = (irq < GIC_INTERNAL) ?  cm : ALL_CPU_MASK;
         for (i = 0; i < 8; i++) {
             if (GIC_TEST_PENDING(irq + i, mask)) {
                 res |= (1 << i);
@@ -328,7 +330,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
-        mask = (irq < 32) ?  cm : ALL_CPU_MASK;
+        mask = (irq < GIC_INTERNAL) ?  cm : ALL_CPU_MASK;
         for (i = 0; i < 8; i++) {
             if (GIC_TEST_ACTIVE(irq + i, mask)) {
                 res |= (1 << i);
@@ -435,8 +437,8 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
           value = 0xff;
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
-                int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
+                int mask = (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq);
+                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 
                 if (!GIC_TEST_ENABLED(irq + i, cm)) {
                     DPRINTF("Enabled IRQ %d\n", irq + i);
@@ -460,7 +462,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
           value = 0;
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
+                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 
                 if (GIC_TEST_ENABLED(irq + i, cm)) {
                     DPRINTF("Disabled IRQ %d\n", irq + i);
@@ -502,10 +504,10 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
         irq = (offset - 0x400) + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 32) {
+        if (irq < GIC_INTERNAL) {
             s->priority1[irq][cpu] = value;
         } else {
-            s->priority2[irq - 32] = value;
+            s->priority2[irq - GIC_INTERNAL] = value;
         }
 #ifndef NVIC
     } else if (offset < 0xc00) {
@@ -515,7 +517,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
             goto bad_reg;
         if (irq < 29)
             value = 0;
-        else if (irq < 32)
+        else if (irq < GIC_INTERNAL)
             value = ALL_CPU_MASK;
         s->irq_target[irq] = value & ALL_CPU_MASK;
     } else if (offset < 0xf00) {
@@ -523,7 +525,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 32)
+        if (irq < GIC_INTERNAL)
             value |= 0xaa;
         for (i = 0; i < 4; i++) {
             if (value & (1 << (i * 2))) {
@@ -736,7 +738,7 @@ static void gic_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, s->enabled);
     for (i = 0; i < NUM_CPU(s); i++) {
         qemu_put_be32(f, s->cpu_enabled[i]);
-        for (j = 0; j < 32; j++)
+        for (j = 0; j < GIC_INTERNAL; j++)
             qemu_put_be32(f, s->priority1[j][i]);
         for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
@@ -745,7 +747,7 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < s->num_irq - 32; i++) {
+    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
     for (i = 0; i < s->num_irq; i++) {
@@ -773,7 +775,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
     s->enabled = qemu_get_be32(f);
     for (i = 0; i < NUM_CPU(s); i++) {
         s->cpu_enabled[i] = qemu_get_be32(f);
-        for (j = 0; j < 32; j++)
+        for (j = 0; j < GIC_INTERNAL; j++)
             s->priority1[j][i] = qemu_get_be32(f);
         for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
@@ -782,7 +784,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < s->num_irq - 32; i++) {
+    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
     for (i = 0; i < s->num_irq; i++) {
@@ -816,7 +818,7 @@ static void gic_init(gic_state *s, int num_irq)
         hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
                  num_irq, GIC_MAXIRQ);
     }
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }

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

* [Qemu-devel] [PATCH] arm: make sure that number of irqs can be represented in GICD_TYPER.
  2012-01-27  0:33       ` Rusty Russell
  2012-01-27  9:01         ` Peter Maydell
  2012-02-19 23:06         ` [Qemu-devel] [PATCH 1/2] arm: clean up GIC constants Rusty Russell
@ 2012-02-19 23:07         ` Rusty Russell
  2012-02-19 23:40           ` [Qemu-devel] [Android-virt] " Christoffer Dall
  2 siblings, 1 reply; 39+ messages in thread
From: Rusty Russell @ 2012-02-19 23:07 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, android-virt, patches

We currently assume that the number of interrupts (ITLinesNumber in
the architecture reference manual) is divisible by 32, since we
present it to the guest when it reads GICD_TYPER (in gic_dist_readb())
as (N - 32) / 1.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index fa6a60a..6446800 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -818,6 +818,15 @@ static void gic_init(gic_state *s, int num_irq)
         hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
                  num_irq, GIC_MAXIRQ);
     }
+    /* ITLinesNumber is represented as (N - 32) / 1 (see
+     * gic_dist_readb) so this is an implementation imposed
+     * restriction, not an architectural one:
+     */
+    if (s->num_irq < 32 || (s->num_irq % 32)) {
+        hw_error("%d interrupt lines unsupported: not divisible by 32\n",
+                 num_irq);
+    }
+
     qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);

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

* Re: [Qemu-devel] [Android-virt] [PATCH] arm: make sure that number of irqs can be represented in GICD_TYPER.
  2012-02-19 23:07         ` [Qemu-devel] [PATCH] arm: make sure that number of irqs can be represented in GICD_TYPER Rusty Russell
@ 2012-02-19 23:40           ` Christoffer Dall
  2012-02-20  3:52             ` Rusty Russell
  2012-02-20  3:53             ` [Qemu-devel] [PATCH 3/2] " Rusty Russell
  0 siblings, 2 replies; 39+ messages in thread
From: Christoffer Dall @ 2012-02-19 23:40 UTC (permalink / raw)
  To: Rusty Russell; +Cc: Peter Maydell, qemu-devel, android-virt, patches

On Sun, Feb 19, 2012 at 6:07 PM, Rusty Russell <rusty@rustcorp.com.au> wrote:
> We currently assume that the number of interrupts (ITLinesNumber in
> the architecture reference manual) is divisible by 32, since we
> present it to the guest when it reads GICD_TYPER (in gic_dist_readb())
> as (N - 32) / 1.
>
> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
>
> diff --git a/hw/arm_gic.c b/hw/arm_gic.c
> index fa6a60a..6446800 100644
> --- a/hw/arm_gic.c
> +++ b/hw/arm_gic.c
> @@ -818,6 +818,15 @@ static void gic_init(gic_state *s, int num_irq)
>         hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
>                  num_irq, GIC_MAXIRQ);
>     }
> +    /* ITLinesNumber is represented as (N - 32) / 1 (see
> +     * gic_dist_readb) so this is an implementation imposed
> +     * restriction, not an architectural one:
> +     */

What is this division by 1? Isn't (N - 32) / 1 == (N - 32) and how
does that explain the division. Was it (N / 32) - 1? Or is this a
cast? Or am I missing something completely?

> +    if (s->num_irq < 32 || (s->num_irq % 32)) {
> +        hw_error("%d interrupt lines unsupported: not divisible by 32\n",
> +                 num_irq);
> +    }
> +
>     qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
>     for (i = 0; i < NUM_CPU(s); i++) {
>         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
> _______________________________________________
> Android-virt mailing list
> Android-virt@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/cucslists/listinfo/android-virt

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

* Re: [Qemu-devel] [Android-virt] [PATCH] arm: make sure that number of irqs can be represented in GICD_TYPER.
  2012-02-19 23:40           ` [Qemu-devel] [Android-virt] " Christoffer Dall
@ 2012-02-20  3:52             ` Rusty Russell
  2012-02-20  3:53             ` [Qemu-devel] [PATCH 3/2] " Rusty Russell
  1 sibling, 0 replies; 39+ messages in thread
From: Rusty Russell @ 2012-02-20  3:52 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: Peter Maydell, qemu-devel, android-virt, patches

On Sun, 19 Feb 2012 18:40:08 -0500, Christoffer Dall <c.dall@virtualopensystems.com> wrote:
> On Sun, Feb 19, 2012 at 6:07 PM, Rusty Russell <rusty@rustcorp.com.au> wrote:
> > We currently assume that the number of interrupts (ITLinesNumber in
> > the architecture reference manual) is divisible by 32, since we
> > present it to the guest when it reads GICD_TYPER (in gic_dist_readb())
> > as (N - 32) / 1.
> >
> > Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
> >
> > diff --git a/hw/arm_gic.c b/hw/arm_gic.c
> > index fa6a60a..6446800 100644
> > --- a/hw/arm_gic.c
> > +++ b/hw/arm_gic.c
> > @@ -818,6 +818,15 @@ static void gic_init(gic_state *s, int num_irq)
> >         hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
> >                  num_irq, GIC_MAXIRQ);
> >     }
> > +    /* ITLinesNumber is represented as (N - 32) / 1 (see
> > +     * gic_dist_readb) so this is an implementation imposed
> > +     * restriction, not an architectural one:
> > +     */
> 
> What is this division by 1? Isn't (N - 32) / 1 == (N - 32) and how
> does that explain the division. Was it (N / 32) - 1? Or is this a
> cast? Or am I missing something completely?

That's hilarious; we were concentrating so hard on the wording of the
comment, we didn't notice that I completely screwed the content :)

It is, of course, (N / 32) - 1:

static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
{
...
        if (offset == 4)
            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);

I'll fix it, thanks!
Rusty.

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

* [Qemu-devel] [PATCH 3/2] arm: make sure that number of irqs can be represented in GICD_TYPER.
  2012-02-19 23:40           ` [Qemu-devel] [Android-virt] " Christoffer Dall
  2012-02-20  3:52             ` Rusty Russell
@ 2012-02-20  3:53             ` Rusty Russell
  1 sibling, 0 replies; 39+ messages in thread
From: Rusty Russell @ 2012-02-20  3:53 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: Peter Maydell, qemu-devel, android-virt, patches

We currently assume that the number of interrupts (ITLinesNumber in
the architecture reference manual) is divisible by 32, since we
present it to the guest when it reads GICD_TYPER (in gic_dist_readb())
as (N / 32) - 1.

Thanks to Christoffer Dall for undoing comment thinko.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index fa6a60a..6446800 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -818,6 +818,15 @@ static void gic_init(gic_state *s, int num_irq)
         hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
                  num_irq, GIC_MAXIRQ);
     }
+    /* ITLinesNumber is represented as (N / 32) - 1 (see
+     * gic_dist_readb) so this is an implementation imposed
+     * restriction, not an architectural one:
+     */
+    if (s->num_irq < 32 || (s->num_irq % 32)) {
+        hw_error("%d interrupt lines unsupported: not divisible by 32\n",
+                 num_irq);
+    }
+
     qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);

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

* Re: [Qemu-devel] [PATCH 1/2] arm: clean up GIC constants.
  2012-02-19 23:06         ` [Qemu-devel] [PATCH 1/2] arm: clean up GIC constants Rusty Russell
@ 2012-02-20 17:27           ` Peter Maydell
  2012-02-21  2:33             ` Rusty Russell
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2012-02-20 17:27 UTC (permalink / raw)
  To: Rusty Russell; +Cc: qemu-devel, android-virt, patches

On 19 February 2012 23:06, Rusty Russell <rusty@rustcorp.com.au> wrote:
> Interrupts numbers 0-31 are private to the processor interface, 32-1019 are
> general interrups.  Add GIC_INTERNAL and substitute everywhere.

"interrupts".

> @@ -74,7 +76,7 @@ typedef struct gic_irq_state
>  #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
>  #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
>  #define GIC_GET_PRIORITY(irq, cpu) \
> -  (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
> +  (((irq) < GIC_INTERNAL) ? s->priority1[irq][cpu] : s->priority2[(irq) - GIC_INTERNAL])

This line is now >80 chars and needs folding (ISTR saying this
for the first version of this patch).

Also, which patches are actually in this series? This is a 1/2,
and I also see a patch with no series indication and a 3/2 which
seems to be a respun version of that, but no 2/2...

-- PMM

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

* [Qemu-devel] [PATCH 1/2] arm: clean up GIC constants.
  2012-02-20 17:27           ` Peter Maydell
@ 2012-02-21  2:33             ` Rusty Russell
  2012-02-21 12:42               ` Peter Maydell
  0 siblings, 1 reply; 39+ messages in thread
From: Rusty Russell @ 2012-02-21  2:33 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, android-virt, patches

Interrupts numbers 0-31 are private to the processor interface, 32-1019 are
general interrups.  Add GIC_INTERNAL and substitute everywhere.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 hw/arm_gic.c |   41 ++++++++++++++++++++++-------------------
 1 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index cf582a5..4b1b486 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -13,6 +13,8 @@
 
 /* Maximum number of possible interrupts, determined by the GIC architecture */
 #define GIC_MAXIRQ 1020
+/* First 32 are private to each CPU (SGIs and PPIs). */
+#define GIC_INTERNAL 32
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -73,8 +75,9 @@ typedef struct gic_irq_state
 #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
 #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
 #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
-#define GIC_GET_PRIORITY(irq, cpu) \
-  (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
+#define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ?		\
+				    s->priority1[irq][cpu] :		\
+				    s->priority2[(irq) - GIC_INTERNAL])
 #ifdef NVIC
 #define GIC_TARGET(irq) 1
 #else
@@ -92,8 +95,8 @@ typedef struct gic_state
 #ifndef NVIC
     int irq_target[GIC_MAXIRQ];
 #endif
-    int priority1[32][NCPU];
-    int priority2[GIC_MAXIRQ - 32];
+    int priority1[GIC_INTERNAL][NCPU];
+    int priority2[GIC_MAXIRQ - GIC_INTERNAL];
     int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
@@ -174,7 +177,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
 {
     gic_state *s = (gic_state *)opaque;
     /* The first external input line is internal interrupt 32.  */
-    irq += 32;
+    irq += GIC_INTERNAL;
     if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
         return;
 
@@ -316,7 +319,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
-        mask = (irq < 32) ?  cm : ALL_CPU_MASK;
+        mask = (irq < GIC_INTERNAL) ?  cm : ALL_CPU_MASK;
         for (i = 0; i < 8; i++) {
             if (GIC_TEST_PENDING(irq + i, mask)) {
                 res |= (1 << i);
@@ -328,7 +331,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
-        mask = (irq < 32) ?  cm : ALL_CPU_MASK;
+        mask = (irq < GIC_INTERNAL) ?  cm : ALL_CPU_MASK;
         for (i = 0; i < 8; i++) {
             if (GIC_TEST_ACTIVE(irq + i, mask)) {
                 res |= (1 << i);
@@ -435,8 +438,8 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
           value = 0xff;
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
-                int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
+                int mask = (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq);
+                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 
                 if (!GIC_TEST_ENABLED(irq + i, cm)) {
                     DPRINTF("Enabled IRQ %d\n", irq + i);
@@ -460,7 +463,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
           value = 0;
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
+                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 
                 if (GIC_TEST_ENABLED(irq + i, cm)) {
                     DPRINTF("Disabled IRQ %d\n", irq + i);
@@ -502,10 +505,10 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
         irq = (offset - 0x400) + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 32) {
+        if (irq < GIC_INTERNAL) {
             s->priority1[irq][cpu] = value;
         } else {
-            s->priority2[irq - 32] = value;
+            s->priority2[irq - GIC_INTERNAL] = value;
         }
 #ifndef NVIC
     } else if (offset < 0xc00) {
@@ -515,7 +518,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
             goto bad_reg;
         if (irq < 29)
             value = 0;
-        else if (irq < 32)
+        else if (irq < GIC_INTERNAL)
             value = ALL_CPU_MASK;
         s->irq_target[irq] = value & ALL_CPU_MASK;
     } else if (offset < 0xf00) {
@@ -523,7 +526,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 32)
+        if (irq < GIC_INTERNAL)
             value |= 0xaa;
         for (i = 0; i < 4; i++) {
             if (value & (1 << (i * 2))) {
@@ -736,7 +739,7 @@ static void gic_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, s->enabled);
     for (i = 0; i < NUM_CPU(s); i++) {
         qemu_put_be32(f, s->cpu_enabled[i]);
-        for (j = 0; j < 32; j++)
+        for (j = 0; j < GIC_INTERNAL; j++)
             qemu_put_be32(f, s->priority1[j][i]);
         for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
@@ -745,7 +748,7 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < s->num_irq - 32; i++) {
+    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
     for (i = 0; i < s->num_irq; i++) {
@@ -773,7 +776,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
     s->enabled = qemu_get_be32(f);
     for (i = 0; i < NUM_CPU(s); i++) {
         s->cpu_enabled[i] = qemu_get_be32(f);
-        for (j = 0; j < 32; j++)
+        for (j = 0; j < GIC_INTERNAL; j++)
             s->priority1[j][i] = qemu_get_be32(f);
         for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
@@ -782,7 +785,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < s->num_irq - 32; i++) {
+    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
     for (i = 0; i < s->num_irq; i++) {
@@ -816,7 +819,7 @@ static void gic_init(gic_state *s, int num_irq)
         hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
                  num_irq, GIC_MAXIRQ);
     }
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }

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

* [Qemu-devel] [PATCH 2/2] arm: make sure that number of irqs can be represented in GICD_TYPER.
  2012-01-13 20:52 ` [Qemu-devel] [PATCH 02/12] arm: make the number of GIC interrupts configurable Peter Maydell
  2012-01-24  8:42   ` [Qemu-devel] [Android-virt] " Rusty Russell
@ 2012-02-21  2:33   ` Rusty Russell
  2012-02-21 12:42     ` Peter Maydell
  1 sibling, 1 reply; 39+ messages in thread
From: Rusty Russell @ 2012-02-21  2:33 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: android-virt, patches

We currently assume that the number of interrupts (ITLinesNumber in
the architecture reference manual) is divisible by 32, since we
present it to the guest when it reads GICD_TYPER (in gic_dist_readb())
as (N / 32) - 1.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 hw/arm_gic.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 4b1b486..a19212e 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -819,6 +819,15 @@ static void gic_init(gic_state *s, int num_irq)
         hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
                  num_irq, GIC_MAXIRQ);
     }
+    /* ITLinesNumber is represented as (N / 32) - 1 (see
+     * gic_dist_readb) so this is an implementation imposed
+     * restriction, not an architectural one:
+     */
+    if (s->num_irq < 32 || (s->num_irq % 32)) {
+        hw_error("%d interrupt lines unsupported: not divisible by 32\n",
+                 num_irq);
+    }
+
     qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);

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

* Re: [Qemu-devel] [PATCH 1/2] arm: clean up GIC constants.
  2012-02-21  2:33             ` Rusty Russell
@ 2012-02-21 12:42               ` Peter Maydell
  0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-02-21 12:42 UTC (permalink / raw)
  To: Rusty Russell; +Cc: qemu-devel, android-virt, patches

On 21 February 2012 02:33, Rusty Russell <rusty@rustcorp.com.au> wrote:
> Interrupts numbers 0-31 are private to the processor interface, 32-1019 are
> general interrups.  Add GIC_INTERNAL and substitute everywhere.
> @@ -73,8 +75,9 @@ typedef struct gic_irq_state
>  #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
>  #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
>  #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
> -#define GIC_GET_PRIORITY(irq, cpu) \
> -  (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
> +#define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ?           \
> +                                   s->priority1[irq][cpu] :            \
> +                                   s->priority2[(irq) - GIC_INTERNAL])

Hardcoded tabs are against coding style. In the interests of not taking
another round for what's really not a very significant patch, I've
fixed this (and the typo in the commit message) and put the fixed
result into arm-devs.next.

(http://git.linaro.org/gitweb?p=people/pmaydell/qemu-arm.git;a=shortlog;h=refs/heads/arm-devs.next)

-- PMM

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

* Re: [Qemu-devel] [PATCH 2/2] arm: make sure that number of irqs can be represented in GICD_TYPER.
  2012-02-21  2:33   ` [Qemu-devel] [PATCH 2/2] " Rusty Russell
@ 2012-02-21 12:42     ` Peter Maydell
  0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2012-02-21 12:42 UTC (permalink / raw)
  To: Rusty Russell; +Cc: qemu-devel, android-virt, patches

On 21 February 2012 02:33, Rusty Russell <rusty@rustcorp.com.au> wrote:
> We currently assume that the number of interrupts (ITLinesNumber in
> the architecture reference manual) is divisible by 32, since we
> present it to the guest when it reads GICD_TYPER (in gic_dist_readb())
> as (N / 32) - 1.
>
> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
and put into arm-devs.next.

-- PMM

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

end of thread, other threads:[~2012-02-21 12:43 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-13 20:52 [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 01/12] vexpress, realview: Add (dummy) L2 cache controller Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 02/12] arm: make the number of GIC interrupts configurable Peter Maydell
2012-01-24  8:42   ` [Qemu-devel] [Android-virt] " Rusty Russell
2012-01-25 15:09     ` Peter Maydell
2012-01-27  0:33       ` Rusty Russell
2012-01-27  9:01         ` Peter Maydell
2012-02-19 23:06         ` [Qemu-devel] [PATCH 1/2] arm: clean up GIC constants Rusty Russell
2012-02-20 17:27           ` Peter Maydell
2012-02-21  2:33             ` Rusty Russell
2012-02-21 12:42               ` Peter Maydell
2012-02-19 23:07         ` [Qemu-devel] [PATCH] arm: make sure that number of irqs can be represented in GICD_TYPER Rusty Russell
2012-02-19 23:40           ` [Qemu-devel] [Android-virt] " Christoffer Dall
2012-02-20  3:52             ` Rusty Russell
2012-02-20  3:53             ` [Qemu-devel] [PATCH 3/2] " Rusty Russell
2012-02-21  2:33   ` [Qemu-devel] [PATCH 2/2] " Rusty Russell
2012-02-21 12:42     ` Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 03/12] hw/arm_boot.c: Make SMP boards specify address to poll in bootup loop Peter Maydell
2012-01-16  1:56   ` [Qemu-devel] [Android-virt] " Alexander Graf
2012-01-16  8:31     ` Peter Maydell
2012-01-16 23:31       ` andrzej zaborowski
2012-01-16 23:41         ` Peter Maydell
2012-01-17  1:16   ` [Qemu-devel] " andrzej zaborowski
2012-01-13 20:52 ` [Qemu-devel] [PATCH 04/12] hw/vexpress.c: Make motherboard peripheral memory map table-driven Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 05/12] hw/vexpress.c: Move secondary CPU boot code to SRAM Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 06/12] hw/vexpress.c: Factor out daughterboard-specific initialization Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 07/12] hw/vexpress.c: Instantiate the motherboard CLCD Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 08/12] hw/a15mpcore.c: Add Cortex-A15 private peripheral model Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 09/12] Add dummy implementation of generic timer cp15 registers Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 10/12] Add Cortex-A15 CPU definition Peter Maydell
2012-01-23 18:12   ` [Qemu-devel] [Android-virt] " Peter Maydell
2012-01-24  7:59   ` [Qemu-devel] " Andreas Färber
2012-01-24  8:33     ` Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 11/12] arm_boot: Pass base address of GIC CPU interface, not whole GIC Peter Maydell
2012-01-13 20:52 ` [Qemu-devel] [PATCH 12/12] hw/vexpress.c: Add vexpress-a15 machine Peter Maydell
2012-01-13 20:57 ` [Qemu-devel] [PATCH 00/12] Add support for Cortex-A15 and vexpress-a15 Peter Maydell
2012-01-15 22:56   ` [Qemu-devel] [Android-virt] " Christoffer Dall
2012-01-17 19:08     ` Peter Maydell
2012-01-27 10:28       ` Marc Zyngier

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.