summaryrefslogtreecommitdiffstats
path: root/hw/intc
diff options
context:
space:
mode:
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/arm_gic.c22
-rw-r--r--hw/intc/armv7m_nvic.c5
-rw-r--r--hw/intc/realview_gic.c7
-rw-r--r--hw/intc/xics.c14
4 files changed, 34 insertions, 14 deletions
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index ea0323f969..34dc84ae81 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -543,7 +543,21 @@ static bool gic_eoi_split(GICState *s, int cpu, MemTxAttrs attrs)
static void gic_deactivate_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
{
int cm = 1 << cpu;
- int group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
+ int group;
+
+ if (irq >= s->num_irq) {
+ /*
+ * This handles two cases:
+ * 1. If software writes the ID of a spurious interrupt [ie 1023]
+ * to the GICC_DIR, the GIC ignores that write.
+ * 2. If software writes the number of a non-existent interrupt
+ * this must be a subcase of "value written is not an active interrupt"
+ * and so this is UNPREDICTABLE. We choose to ignore it.
+ */
+ return;
+ }
+
+ group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
if (!gic_eoi_split(s, cpu, attrs)) {
/* This is UNPREDICTABLE; we choose to ignore it */
@@ -737,7 +751,9 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
if (irq >= s->num_irq) {
goto bad_reg;
}
- if (irq >= 29 && irq <= 31) {
+ if (irq < 29 && s->revision == REV_11MPCORE) {
+ res = 0;
+ } else if (irq < GIC_INTERNAL) {
res = cm;
} else {
res = GIC_TARGET(irq);
@@ -1000,7 +1016,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
if (irq >= s->num_irq) {
goto bad_reg;
}
- if (irq < 29) {
+ if (irq < 29 && s->revision == REV_11MPCORE) {
value = 0;
} else if (irq < GIC_INTERNAL) {
value = ALL_CPU_MASK;
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 661be8878a..7a5330f201 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -2296,9 +2296,8 @@ static void armv7m_nvic_instance_init(Object *obj)
NVICState *nvic = NVIC(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- object_initialize(&nvic->systick[M_REG_NS],
- sizeof(nvic->systick[M_REG_NS]), TYPE_SYSTICK);
- qdev_set_parent_bus(DEVICE(&nvic->systick[M_REG_NS]), sysbus_get_default());
+ sysbus_init_child_obj(obj, "systick-reg-ns", &nvic->systick[M_REG_NS],
+ sizeof(nvic->systick[M_REG_NS]), TYPE_SYSTICK);
/* We can't initialize the secure systick here, as we don't know
* yet if we need it.
*/
diff --git a/hw/intc/realview_gic.c b/hw/intc/realview_gic.c
index 50bbab66ee..7f2ff85c83 100644
--- a/hw/intc/realview_gic.c
+++ b/hw/intc/realview_gic.c
@@ -54,16 +54,13 @@ static void realview_gic_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
RealViewGICState *s = REALVIEW_GIC(obj);
- DeviceState *gicdev;
memory_region_init(&s->container, OBJECT(s),
"realview-gic-container", 0x2000);
sysbus_init_mmio(sbd, &s->container);
- object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
- gicdev = DEVICE(&s->gic);
- qdev_set_parent_bus(gicdev, sysbus_get_default());
- qdev_prop_set_uint32(gicdev, "num-cpu", 1);
+ sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic), TYPE_ARM_GIC);
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", 1);
}
static void realview_gic_class_init(ObjectClass *oc, void *data)
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index b9f1a3c972..c90c893228 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -291,7 +291,7 @@ static const VMStateDescription vmstate_icp_server = {
},
};
-static void icp_reset(void *dev)
+static void icp_reset(DeviceState *dev)
{
ICPState *icp = ICP(dev);
@@ -303,6 +303,13 @@ static void icp_reset(void *dev)
qemu_set_irq(icp->output, 0);
}
+static void icp_reset_handler(void *dev)
+{
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
+ dc->reset(dev);
+}
+
static void icp_realize(DeviceState *dev, Error **errp)
{
ICPState *icp = ICP(dev);
@@ -345,7 +352,7 @@ static void icp_realize(DeviceState *dev, Error **errp)
return;
}
- qemu_register_reset(icp_reset, dev);
+ qemu_register_reset(icp_reset_handler, dev);
vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp);
}
@@ -354,7 +361,7 @@ static void icp_unrealize(DeviceState *dev, Error **errp)
ICPState *icp = ICP(dev);
vmstate_unregister(NULL, &vmstate_icp_server, icp);
- qemu_unregister_reset(icp_reset, dev);
+ qemu_unregister_reset(icp_reset_handler, dev);
}
static void icp_class_init(ObjectClass *klass, void *data)
@@ -363,6 +370,7 @@ static void icp_class_init(ObjectClass *klass, void *data)
dc->realize = icp_realize;
dc->unrealize = icp_unrealize;
+ dc->reset = icp_reset;
}
static const TypeInfo icp_info = {