[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts
From: |
Mark Langsdorf |
Subject: |
[Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts configurable |
Date: |
Tue, 27 Dec 2011 14:13:47 -0600 |
Increase the maximum number of GIC interrupts for a9mp to 192, and
create a configurable property defaulting to 96 so that device
modelers can set the value appropriately for their SoC.
Signed-off-by: Mark Langsdorf <address@hidden>
---
Changes from v2
Skipped
Changes from v1
Increase the number of a9mp interrupts to 192
Add a property defaulting to 96
Add a num_irq member in the gic state structure
Use the num_irq value as appropriate
Add num_irq argument to gic_init()
Add num_irq to various CPU calls to gic_init
hw/a9mpcore.c | 9 +++++++--
hw/arm11mpcore.c | 2 +-
hw/arm_gic.c | 40 +++++++++++++++++++++-------------------
hw/armv7m_nvic.c | 2 +-
hw/realview_gic.c | 2 +-
5 files changed, 31 insertions(+), 24 deletions(-)
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..89504c4 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -13,7 +13,7 @@
/* Configuration for arm_gic.c:
* number of external IRQ lines, max number of CPUs, how to ID current CPU
*/
-#define GIC_NIRQ 96
+#define GIC_NIRQ 192
#define NCPU 4
static inline int
@@ -37,6 +37,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,
@@ -152,8 +153,11 @@ static int a9mp_priv_init(SysBusDevice *dev)
if (s->num_cpu > NCPU) {
hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
}
+ if (s->num_irq > GIC_NIRQ) {
+ hw_error("a9mp_priv_init: num-irq may not be more than %d\n",
GIC_NIRQ);
+ }
- 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 +220,7 @@ static SysBusDeviceInfo a9mp_priv_info = {
.qdev.reset = a9mp_priv_reset,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+ 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..039b401 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -132,7 +132,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, GIC_NIRQ);
s->mptimer = qdev_create(NULL, "arm_mptimer");
qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
qdev_init_nofail(s->mptimer);
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..cc21262 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -111,6 +111,7 @@ typedef struct gic_state
struct gic_state *backref[NCPU];
MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
#endif
+ int num_irq;
} gic_state;
/* TODO: Many places that call this routine could be optimized. */
@@ -133,7 +134,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 +223,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 +280,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 +296,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 +311,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 +323,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 +335,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 +352,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 +427,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 +452,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 +469,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 +482,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 +498,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 +509,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 +519,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;
@@ -798,9 +799,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 +809,8 @@ 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;
+ 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..b97c904 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -384,7 +384,7 @@ static int armv7m_nvic_init(SysBusDevice *dev)
{
nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
- gic_init(&s->gic);
+ gic_init(&s->gic, GIC_NIRQ);
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);
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..a967f36 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -37,7 +37,7 @@ static int realview_gic_init(SysBusDevice *dev)
{
RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
- gic_init(&s->gic);
+ gic_init(&s->gic, GIC_NIRQ);
realview_gic_map_setup(s);
sysbus_init_mmio(dev, &s->container);
return 0;
--
1.7.5.4
- Re: [Qemu-devel] [PATCH v3 7/9] add L2x0/PL310 cache controller device, (continued)
- [Qemu-devel] [PATCH v3 2/9] arm: Set frequencies for arm_timer, Mark Langsdorf, 2011/12/27
- [Qemu-devel] [PATCH v3 4/9] arm: add dummy gic security registers, Mark Langsdorf, 2011/12/27
- [Qemu-devel] [PATCH v3 1/9] arm: add missing scu registers, Mark Langsdorf, 2011/12/27
- [Qemu-devel] [PATCH v3 5/9] ahci: convert ahci_reset to use AHCIState, Mark Langsdorf, 2011/12/27
- [Qemu-devel] [PATCH v3 6/9] ahci: add support for non-PCI based controllers, Mark Langsdorf, 2011/12/27
- [Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts configurable,
Mark Langsdorf <=
- [Qemu-devel] [PATCH v3 8/9] Add xgmac ethernet model, Mark Langsdorf, 2011/12/27