aboutsummaryrefslogtreecommitdiff
path: root/hw/mpcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/mpcore.c')
-rw-r--r--hw/mpcore.c64
1 files changed, 50 insertions, 14 deletions
diff --git a/hw/mpcore.c b/hw/mpcore.c
index 46c2b9d994..eccb2e188d 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -44,6 +44,7 @@ typedef struct mpcore_priv_state {
uint32_t scu_control;
int iomemtype;
mpcore_timer_state timer[8];
+ uint32_t num_cpu;
} mpcore_priv_state;
/* Per-CPU Timers. */
@@ -166,7 +167,8 @@ static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
case 0x00: /* Control. */
return s->scu_control;
case 0x04: /* Configuration. */
- return 0xf3;
+ id = ((1 << s->num_cpu) - 1) << 4;
+ return id | (s->num_cpu - 1);
case 0x08: /* CPU status. */
return 0;
case 0x0c: /* Invalidate all. */
@@ -180,6 +182,9 @@ static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
id = gic_get_current_cpu();
} else {
id = (offset - 0x200) >> 8;
+ if (id >= s->num_cpu) {
+ return 0;
+ }
}
return gic_cpu_read(&s->gic, id, offset & 0xff);
} else if (offset < 0xb00) {
@@ -188,6 +193,9 @@ static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
id = gic_get_current_cpu();
} else {
id = (offset - 0x700) >> 8;
+ if (id >= s->num_cpu) {
+ return 0;
+ }
}
id <<= 1;
if (offset & 0x20)
@@ -224,7 +232,9 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
} else {
id = (offset - 0x200) >> 8;
}
- gic_cpu_write(&s->gic, id, offset & 0xff, value);
+ if (id < s->num_cpu) {
+ gic_cpu_write(&s->gic, id, offset & 0xff, value);
+ }
} else if (offset < 0xb00) {
/* Timers. */
if (offset < 0x700) {
@@ -232,10 +242,12 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
} else {
id = (offset - 0x700) >> 8;
}
- id <<= 1;
- if (offset & 0x20)
- id++;
- mpcore_timer_write(&s->timer[id], offset & 0xf, value);
+ if (id < s->num_cpu) {
+ id <<= 1;
+ if (offset & 0x20)
+ id++;
+ mpcore_timer_write(&s->timer[id], offset & 0xf, value);
+ }
return;
}
return;
@@ -267,11 +279,11 @@ static int mpcore_priv_init(SysBusDevice *dev)
mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
int i;
- gic_init(&s->gic);
+ gic_init(&s->gic, s->num_cpu);
s->iomemtype = cpu_register_io_memory(mpcore_priv_readfn,
mpcore_priv_writefn, s);
sysbus_init_mmio_cb(dev, 0x2000, mpcore_priv_map);
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < s->num_cpu * 2; i++) {
mpcore_timer_init(s, &s->timer[i], i);
}
return 0;
@@ -284,6 +296,7 @@ typedef struct {
SysBusDevice busdev;
qemu_irq cpuic[32];
qemu_irq rvic[4][64];
+ uint32_t num_cpu;
} mpcore_rirq_state;
/* Map baseboard IRQs onto CPU IRQ lines. */
@@ -315,11 +328,16 @@ static int realview_mpcore_init(SysBusDevice *dev)
mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev);
DeviceState *gic;
DeviceState *priv;
+ SysBusDevice *bus_priv;
int n;
int i;
- priv = sysbus_create_simple("arm11mpcore_priv", MPCORE_PRIV_BASE, NULL);
- sysbus_pass_irq(dev, sysbus_from_qdev(priv));
+ priv = qdev_create(NULL, "arm11mpcore_priv");
+ qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
+ qdev_init_nofail(priv);
+ bus_priv = sysbus_from_qdev(priv);
+ sysbus_mmio_map(bus_priv, 0, MPCORE_PRIV_BASE);
+ sysbus_pass_irq(dev, bus_priv);
for (i = 0; i < 32; i++) {
s->cpuic[i] = qdev_get_gpio_in(priv, i);
}
@@ -335,12 +353,30 @@ static int realview_mpcore_init(SysBusDevice *dev)
return 0;
}
+static SysBusDeviceInfo mpcore_rirq_info = {
+ .init = realview_mpcore_init,
+ .qdev.name = "realview_mpcore",
+ .qdev.size = sizeof(mpcore_rirq_state),
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
+ DEFINE_PROP_END_OF_LIST(),
+ }
+};
+
+static SysBusDeviceInfo mpcore_priv_info = {
+ .init = mpcore_priv_init,
+ .qdev.name = "arm11mpcore_priv",
+ .qdev.size = sizeof(mpcore_priv_state),
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+ DEFINE_PROP_END_OF_LIST(),
+ }
+};
+
static void mpcore_register_devices(void)
{
- sysbus_register_dev("realview_mpcore", sizeof(mpcore_rirq_state),
- realview_mpcore_init);
- sysbus_register_dev("arm11mpcore_priv", sizeof(mpcore_priv_state),
- mpcore_priv_init);
+ sysbus_register_withprop(&mpcore_rirq_info);
+ sysbus_register_withprop(&mpcore_priv_info);
}
device_init(mpcore_register_devices)