summaryrefslogtreecommitdiffstats
path: root/hw/intc
diff options
context:
space:
mode:
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/Makefile.objs1
-rw-r--r--hw/intc/allwinner-a10-pic.c200
-rw-r--r--hw/intc/apic.c48
-rw-r--r--hw/intc/apic_common.c79
-rw-r--r--hw/intc/arm_gic.c28
-rw-r--r--hw/intc/arm_gic_common.c5
-rw-r--r--hw/intc/arm_gic_kvm.c1
-rw-r--r--hw/intc/etraxfs_pic.c4
-rw-r--r--hw/intc/gic_internal.h7
-rw-r--r--hw/intc/grlib_irqmp.c2
-rw-r--r--hw/intc/i8259_common.c8
-rw-r--r--hw/intc/ioapic.c13
-rw-r--r--hw/intc/ioapic_common.c16
-rw-r--r--hw/intc/omap_intc.c4
-rw-r--r--hw/intc/pl190.c1
-rw-r--r--hw/intc/xics.c24
16 files changed, 339 insertions, 102 deletions
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 47ac44264c..60eb936e0d 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -24,3 +24,4 @@ obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
obj-$(CONFIG_SH4) += sh_intc.o
obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_XICS_KVM) += xics_kvm.o
+obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
new file mode 100644
index 0000000000..407d563514
--- /dev/null
+++ b/hw/intc/allwinner-a10-pic.c
@@ -0,0 +1,200 @@
+/*
+ * Allwinner A10 interrupt controller device emulation
+ *
+ * Copyright (C) 2013 Li Guang
+ * Written by Li Guang <lig.fnst@cn.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/devices.h"
+#include "sysemu/sysemu.h"
+#include "hw/intc/allwinner-a10-pic.h"
+
+static void aw_a10_pic_update(AwA10PICState *s)
+{
+ uint8_t i;
+ int irq = 0, fiq = 0;
+
+ for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
+ irq |= s->irq_pending[i] & ~s->mask[i];
+ fiq |= s->select[i] & s->irq_pending[i] & ~s->mask[i];
+ }
+
+ qemu_set_irq(s->parent_irq, !!irq);
+ qemu_set_irq(s->parent_fiq, !!fiq);
+}
+
+static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
+{
+ AwA10PICState *s = opaque;
+
+ if (level) {
+ set_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
+ }
+ aw_a10_pic_update(s);
+}
+
+static uint64_t aw_a10_pic_read(void *opaque, hwaddr offset, unsigned size)
+{
+ AwA10PICState *s = opaque;
+ uint8_t index = (offset & 0xc) / 4;
+
+ switch (offset) {
+ case AW_A10_PIC_VECTOR:
+ return s->vector;
+ case AW_A10_PIC_BASE_ADDR:
+ return s->base_addr;
+ case AW_A10_PIC_PROTECT:
+ return s->protect;
+ case AW_A10_PIC_NMI:
+ return s->nmi;
+ case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
+ return s->irq_pending[index];
+ case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
+ return s->fiq_pending[index];
+ case AW_A10_PIC_SELECT ... AW_A10_PIC_SELECT + 8:
+ return s->select[index];
+ case AW_A10_PIC_ENABLE ... AW_A10_PIC_ENABLE + 8:
+ return s->enable[index];
+ case AW_A10_PIC_MASK ... AW_A10_PIC_MASK + 8:
+ return s->mask[index];
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%x\n", __func__, (int)offset);
+ break;
+ }
+
+ return 0;
+}
+
+static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ AwA10PICState *s = opaque;
+ uint8_t index = (offset & 0xc) / 4;
+
+ switch (offset) {
+ case AW_A10_PIC_VECTOR:
+ s->vector = value & ~0x3;
+ break;
+ case AW_A10_PIC_BASE_ADDR:
+ s->base_addr = value & ~0x3;
+ case AW_A10_PIC_PROTECT:
+ s->protect = value;
+ break;
+ case AW_A10_PIC_NMI:
+ s->nmi = value;
+ break;
+ case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
+ s->irq_pending[index] &= ~value;
+ break;
+ case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
+ s->fiq_pending[index] &= ~value;
+ break;
+ case AW_A10_PIC_SELECT ... AW_A10_PIC_SELECT + 8:
+ s->select[index] = value;
+ break;
+ case AW_A10_PIC_ENABLE ... AW_A10_PIC_ENABLE + 8:
+ s->enable[index] = value;
+ break;
+ case AW_A10_PIC_MASK ... AW_A10_PIC_MASK + 8:
+ s->mask[index] = value;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%x\n", __func__, (int)offset);
+ break;
+ }
+
+ aw_a10_pic_update(s);
+}
+
+static const MemoryRegionOps aw_a10_pic_ops = {
+ .read = aw_a10_pic_read,
+ .write = aw_a10_pic_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_aw_a10_pic = {
+ .name = "a10.pic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(vector, AwA10PICState),
+ VMSTATE_UINT32(base_addr, AwA10PICState),
+ VMSTATE_UINT32(protect, AwA10PICState),
+ VMSTATE_UINT32(nmi, AwA10PICState),
+ VMSTATE_UINT32_ARRAY(irq_pending, AwA10PICState, AW_A10_PIC_REG_NUM),
+ VMSTATE_UINT32_ARRAY(fiq_pending, AwA10PICState, AW_A10_PIC_REG_NUM),
+ VMSTATE_UINT32_ARRAY(enable, AwA10PICState, AW_A10_PIC_REG_NUM),
+ VMSTATE_UINT32_ARRAY(select, AwA10PICState, AW_A10_PIC_REG_NUM),
+ VMSTATE_UINT32_ARRAY(mask, AwA10PICState, AW_A10_PIC_REG_NUM),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void aw_a10_pic_init(Object *obj)
+{
+ AwA10PICState *s = AW_A10_PIC(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+
+ qdev_init_gpio_in(DEVICE(dev), aw_a10_pic_set_irq, AW_A10_PIC_INT_NR);
+ sysbus_init_irq(dev, &s->parent_irq);
+ sysbus_init_irq(dev, &s->parent_fiq);
+ memory_region_init_io(&s->iomem, OBJECT(s), &aw_a10_pic_ops, s,
+ TYPE_AW_A10_PIC, 0x400);
+ sysbus_init_mmio(dev, &s->iomem);
+}
+
+static void aw_a10_pic_reset(DeviceState *d)
+{
+ AwA10PICState *s = AW_A10_PIC(d);
+ uint8_t i;
+
+ s->base_addr = 0;
+ s->protect = 0;
+ s->nmi = 0;
+ s->vector = 0;
+ for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
+ s->irq_pending[i] = 0;
+ s->fiq_pending[i] = 0;
+ s->select[i] = 0;
+ s->enable[i] = 0;
+ s->mask[i] = 0;
+ }
+}
+
+static void aw_a10_pic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = aw_a10_pic_reset;
+ dc->desc = "allwinner a10 pic";
+ dc->vmsd = &vmstate_aw_a10_pic;
+ }
+
+static const TypeInfo aw_a10_pic_info = {
+ .name = TYPE_AW_A10_PIC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(AwA10PICState),
+ .instance_init = aw_a10_pic_init,
+ .class_init = aw_a10_pic_class_init,
+};
+
+static void aw_a10_register_types(void)
+{
+ type_register_static(&aw_a10_pic_info);
+}
+
+type_init(aw_a10_register_types);
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index a913186ed0..3d3deb6298 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -171,9 +171,9 @@ static void apic_local_deliver(APICCommonState *s, int vector)
}
}
-void apic_deliver_pic_intr(DeviceState *d, int level)
+void apic_deliver_pic_intr(DeviceState *dev, int level)
{
- APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ APICCommonState *s = APIC_COMMON(dev);
if (level) {
apic_local_deliver(s, APIC_LVT_LINT0);
@@ -376,9 +376,9 @@ static void apic_update_irq(APICCommonState *s)
}
}
-void apic_poll_irq(DeviceState *d)
+void apic_poll_irq(DeviceState *dev)
{
- APICCommonState *s = APIC_COMMON(d);
+ APICCommonState *s = APIC_COMMON(dev);
apic_sync_vapic(s, SYNC_FROM_VAPIC);
apic_update_irq(s);
@@ -482,9 +482,9 @@ static void apic_startup(APICCommonState *s, int vector_num)
cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
}
-void apic_sipi(DeviceState *d)
+void apic_sipi(DeviceState *dev)
{
- APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ APICCommonState *s = APIC_COMMON(dev);
cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
@@ -494,11 +494,11 @@ void apic_sipi(DeviceState *d)
s->wait_for_sipi = 0;
}
-static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode,
+static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode,
uint8_t delivery_mode, uint8_t vector_num,
uint8_t trigger_mode)
{
- APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ APICCommonState *s = APIC_COMMON(dev);
uint32_t deliver_bitmask[MAX_APIC_WORDS];
int dest_shorthand = (s->icr[0] >> 18) & 3;
APICCommonState *apic_iter;
@@ -551,9 +551,9 @@ static bool apic_check_pic(APICCommonState *s)
return true;
}
-int apic_get_interrupt(DeviceState *d)
+int apic_get_interrupt(DeviceState *dev)
{
- APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ APICCommonState *s = APIC_COMMON(dev);
int intno;
/* if the APIC is installed or enabled, we let the 8259 handle the
@@ -585,9 +585,9 @@ int apic_get_interrupt(DeviceState *d)
return intno;
}
-int apic_accept_pic_intr(DeviceState *d)
+int apic_accept_pic_intr(DeviceState *dev)
{
- APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ APICCommonState *s = APIC_COMMON(dev);
uint32_t lvt0;
if (!s)
@@ -657,16 +657,16 @@ static void apic_mem_writew(void *opaque, hwaddr addr, uint32_t val)
static uint32_t apic_mem_readl(void *opaque, hwaddr addr)
{
- DeviceState *d;
+ DeviceState *dev;
APICCommonState *s;
uint32_t val;
int index;
- d = cpu_get_current_apic();
- if (!d) {
+ dev = cpu_get_current_apic();
+ if (!dev) {
return 0;
}
- s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ s = APIC_COMMON(dev);
index = (addr >> 4) & 0xff;
switch(index) {
@@ -752,7 +752,7 @@ static void apic_send_msi(hwaddr addr, uint32_t data)
static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val)
{
- DeviceState *d;
+ DeviceState *dev;
APICCommonState *s;
int index = (addr >> 4) & 0xff;
if (addr > 0xfff || !index) {
@@ -765,11 +765,11 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val)
return;
}
- d = cpu_get_current_apic();
- if (!d) {
+ dev = cpu_get_current_apic();
+ if (!dev) {
return;
}
- s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ s = APIC_COMMON(dev);
trace_apic_mem_writel(addr, val);
@@ -810,7 +810,7 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val)
break;
case 0x30:
s->icr[0] = val;
- apic_deliver(d, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
+ apic_deliver(dev, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
(s->icr[0] >> 8) & 7, (s->icr[0] & 0xff),
(s->icr[0] >> 15) & 1);
break;
@@ -871,8 +871,10 @@ static const MemoryRegionOps apic_io_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void apic_init(APICCommonState *s)
+static void apic_realize(DeviceState *dev, Error **errp)
{
+ APICCommonState *s = APIC_COMMON(dev);
+
memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
APIC_SPACE_SIZE);
@@ -886,7 +888,7 @@ static void apic_class_init(ObjectClass *klass, void *data)
{
APICCommonClass *k = APIC_COMMON_CLASS(klass);
- k->init = apic_init;
+ k->realize = apic_realize;
k->set_base = apic_set_base;
k->set_tpr = apic_set_tpr;
k->get_tpr = apic_get_tpr;
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index a0beb10863..c623fcc6d8 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -27,21 +27,21 @@
static int apic_irq_delivered;
bool apic_report_tpr_access;
-void cpu_set_apic_base(DeviceState *d, uint64_t val)
+void cpu_set_apic_base(DeviceState *dev, uint64_t val)
{
trace_cpu_set_apic_base(val);
- if (d) {
- APICCommonState *s = APIC_COMMON(d);
+ if (dev) {
+ APICCommonState *s = APIC_COMMON(dev);
APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
info->set_base(s, val);
}
}
-uint64_t cpu_get_apic_base(DeviceState *d)
+uint64_t cpu_get_apic_base(DeviceState *dev)
{
- if (d) {
- APICCommonState *s = APIC_COMMON(d);
+ if (dev) {
+ APICCommonState *s = APIC_COMMON(dev);
trace_cpu_get_apic_base((uint64_t)s->apicbase);
return s->apicbase;
} else {
@@ -50,39 +50,39 @@ uint64_t cpu_get_apic_base(DeviceState *d)
}
}
-void cpu_set_apic_tpr(DeviceState *d, uint8_t val)
+void cpu_set_apic_tpr(DeviceState *dev, uint8_t val)
{
APICCommonState *s;
APICCommonClass *info;
- if (!d) {
+ if (!dev) {
return;
}
- s = APIC_COMMON(d);
+ s = APIC_COMMON(dev);
info = APIC_COMMON_GET_CLASS(s);
info->set_tpr(s, val);
}
-uint8_t cpu_get_apic_tpr(DeviceState *d)
+uint8_t cpu_get_apic_tpr(DeviceState *dev)
{
APICCommonState *s;
APICCommonClass *info;
- if (!d) {
+ if (!dev) {
return 0;
}
- s = APIC_COMMON(d);
+ s = APIC_COMMON(dev);
info = APIC_COMMON_GET_CLASS(s);
return info->get_tpr(s);
}
-void apic_enable_tpr_access_reporting(DeviceState *d, bool enable)
+void apic_enable_tpr_access_reporting(DeviceState *dev, bool enable)
{
- APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ APICCommonState *s = APIC_COMMON(dev);
APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
apic_report_tpr_access = enable;
@@ -91,19 +91,19 @@ void apic_enable_tpr_access_reporting(DeviceState *d, bool enable)
}
}
-void apic_enable_vapic(DeviceState *d, hwaddr paddr)
+void apic_enable_vapic(DeviceState *dev, hwaddr paddr)
{
- APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ APICCommonState *s = APIC_COMMON(dev);
APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
s->vapic_paddr = paddr;
info->vapic_base_update(s);
}
-void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
+void apic_handle_tpr_access_report(DeviceState *dev, target_ulong ip,
TPRAccess access)
{
- APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ APICCommonState *s = APIC_COMMON(dev);
vapic_report_tpr_access(s->vapic, CPU(s->cpu), ip, access);
}
@@ -129,9 +129,9 @@ int apic_get_irq_delivered(void)
return apic_irq_delivered;
}
-void apic_deliver_nmi(DeviceState *d)
+void apic_deliver_nmi(DeviceState *dev)
{
- APICCommonState *s = APIC_COMMON(d);
+ APICCommonState *s = APIC_COMMON(dev);
APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
info->external_nmi(s);
@@ -170,9 +170,9 @@ bool apic_next_timer(APICCommonState *s, int64_t current_time)
return true;
}
-void apic_init_reset(DeviceState *d)
+void apic_init_reset(DeviceState *dev)
{
- APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ APICCommonState *s = APIC_COMMON(dev);
int i;
if (!s) {
@@ -203,19 +203,19 @@ void apic_init_reset(DeviceState *d)
s->timer_expiry = -1;
}
-void apic_designate_bsp(DeviceState *d)
+void apic_designate_bsp(DeviceState *dev)
{
- if (d == NULL) {
+ if (dev == NULL) {
return;
}
- APICCommonState *s = APIC_COMMON(d);
+ APICCommonState *s = APIC_COMMON(dev);
s->apicbase |= MSR_IA32_APICBASE_BSP;
}
-static void apic_reset_common(DeviceState *d)
+static void apic_reset_common(DeviceState *dev)
{
- APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ APICCommonState *s = APIC_COMMON(dev);
APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
bool bsp;
@@ -226,7 +226,7 @@ static void apic_reset_common(DeviceState *d)
s->vapic_paddr = 0;
info->vapic_base_update(s);
- apic_init_reset(d);
+ apic_init_reset(dev);
if (bsp) {
/*
@@ -284,7 +284,7 @@ static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
return 0;
}
-static int apic_init_common(ICCDevice *dev)
+static void apic_common_realize(DeviceState *dev, Error **errp)
{
APICCommonState *s = APIC_COMMON(dev);
APICCommonClass *info;
@@ -293,14 +293,16 @@ static int apic_init_common(ICCDevice *dev)
static bool mmio_registered;
if (apic_no >= MAX_APICS) {
- return -1;
+ error_setg(errp, "%s initialization failed.",
+ object_get_typename(OBJECT(dev)));
+ return;
}
s->idx = apic_no++;
info = APIC_COMMON_GET_CLASS(s);
- info->init(s);
+ info->realize(dev, errp);
if (!mmio_registered) {
- ICCBus *b = ICC_BUS(qdev_get_parent_bus(DEVICE(dev)));
+ ICCBus *b = ICC_BUS(qdev_get_parent_bus(dev));
memory_region_add_subregion(b->apic_address_space, 0, &s->io_memory);
mmio_registered = true;
}
@@ -315,7 +317,6 @@ static int apic_init_common(ICCDevice *dev)
info->enable_tpr_reporting(s, true);
}
- return 0;
}
static void apic_dispatch_pre_save(void *opaque)
@@ -386,9 +387,13 @@ static void apic_common_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_apic_common;
dc->reset = apic_reset_common;
- dc->no_user = 1;
dc->props = apic_properties_common;
- idc->init = apic_init_common;
+ idc->realize = apic_common_realize;
+ /*
+ * Reason: APIC and CPU need to be wired up by
+ * x86_cpu_apic_create()
+ */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo apic_common_type = {
@@ -400,9 +405,9 @@ static const TypeInfo apic_common_type = {
.abstract = true,
};
-static void register_types(void)
+static void apic_common_register_types(void)
{
type_register_static(&apic_common_type);
}
-type_init(register_types)
+type_init(apic_common_register_types)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index d431b7a881..9409684ce8 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -128,7 +128,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
if (level) {
GIC_SET_LEVEL(irq, cm);
- if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
+ if (GIC_TEST_EDGE_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
DPRINTF("Set %d pending mask %x\n", irq, target);
GIC_SET_PENDING(irq, target);
}
@@ -168,6 +168,15 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu)
return new_irq;
}
+void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val)
+{
+ if (irq < GIC_INTERNAL) {
+ s->priority1[irq][cpu] = val;
+ } else {
+ s->priority2[(irq) - GIC_INTERNAL] = val;
+ }
+}
+
void gic_complete_irq(GICState *s, int cpu, int irq)
{
int update = 0;
@@ -188,7 +197,7 @@ void gic_complete_irq(GICState *s, int cpu, int irq)
return; /* No active IRQ. */
/* Mark level triggered interrupts as pending if they are still
raised. */
- if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
+ if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
&& GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
DPRINTF("Set %d pending mask %x\n", irq, cm);
GIC_SET_PENDING(irq, cm);
@@ -311,7 +320,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset)
for (i = 0; i < 4; i++) {
if (GIC_TEST_MODEL(irq + i))
res |= (1 << (i * 2));
- if (GIC_TEST_TRIGGER(irq + i))
+ if (GIC_TEST_EDGE_TRIGGER(irq + i))
res |= (2 << (i * 2));
}
} else if (offset < 0xfe0) {
@@ -386,7 +395,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
/* If a raised level triggered IRQ enabled then mark
is as pending. */
if (GIC_TEST_LEVEL(irq + i, mask)
- && !GIC_TEST_TRIGGER(irq + i)) {
+ && !GIC_TEST_EDGE_TRIGGER(irq + i)) {
DPRINTF("Set %d pending mask %x\n", irq + i, mask);
GIC_SET_PENDING(irq + i, mask);
}
@@ -443,11 +452,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
irq = (offset - 0x400) + GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
- if (irq < GIC_INTERNAL) {
- s->priority1[irq][cpu] = value;
- } else {
- s->priority2[irq - GIC_INTERNAL] = value;
- }
+ gic_set_priority(s, cpu, irq, value);
} else if (offset < 0xc00) {
/* Interrupt CPU Target. RAZ/WI on uniprocessor GICs, with the
* annoying exception of the 11MPCore's GIC.
@@ -478,9 +483,9 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
GIC_CLEAR_MODEL(irq + i);
}
if (value & (2 << (i * 2))) {
- GIC_SET_TRIGGER(irq + i);
+ GIC_SET_EDGE_TRIGGER(irq + i);
} else {
- GIC_CLEAR_TRIGGER(irq + i);
+ GIC_CLEAR_EDGE_TRIGGER(irq + i);
}
}
} else {
@@ -704,7 +709,6 @@ static void arm_gic_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
ARMGICClass *agc = ARM_GIC_CLASS(klass);
- dc->no_user = 1;
agc->parent_realize = dc->realize;
dc->realize = arm_gic_realize;
}
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index c7658508dd..e4fc65028a 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -51,7 +51,7 @@ static const VMStateDescription vmstate_gic_irq_state = {
VMSTATE_UINT8(active, gic_irq_state),
VMSTATE_UINT8(level, gic_irq_state),
VMSTATE_BOOL(model, gic_irq_state),
- VMSTATE_BOOL(trigger, gic_irq_state),
+ VMSTATE_BOOL(edge_trigger, gic_irq_state),
VMSTATE_END_OF_LIST()
}
};
@@ -126,7 +126,7 @@ static void arm_gic_common_reset(DeviceState *dev)
}
for (i = 0; i < 16; i++) {
GIC_SET_ENABLED(i, ALL_CPU_MASK);
- GIC_SET_TRIGGER(i);
+ GIC_SET_EDGE_TRIGGER(i);
}
if (s->num_cpu == 1) {
/* For uniprocessor GICs all interrupts always target the sole CPU */
@@ -156,7 +156,6 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data)
dc->realize = arm_gic_common_realize;
dc->props = arm_gic_common_properties;
dc->vmsd = &vmstate_gic;
- dc->no_user = 1;
}
static const TypeInfo arm_gic_common_type = {
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index f71397542a..59a3da5a6b 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -150,7 +150,6 @@ static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
kgc->parent_reset = dc->reset;
dc->realize = kvm_arm_gic_realize;
dc->reset = kvm_arm_gic_reset;
- dc->no_user = 1;
}
static const TypeInfo kvm_arm_gic_info = {
diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c
index e02da533cb..636262b49f 100644
--- a/hw/intc/etraxfs_pic.c
+++ b/hw/intc/etraxfs_pic.c
@@ -170,6 +170,10 @@ static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
k->init = etraxfs_pic_init;
dc->props = etraxfs_pic_properties;
+ /*
+ * Note: pointer property "interrupt_vector" may remain null, thus
+ * no need for dc->cannot_instantiate_with_device_add_yet = true;
+ */
}
static const TypeInfo etraxfs_pic_info = {
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 3989fd1bd5..8c02d5888c 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -44,9 +44,9 @@
#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
#define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
#define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
-#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = true
-#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = false
-#define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
+#define GIC_SET_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = true
+#define GIC_CLEAR_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = false
+#define GIC_TEST_EDGE_TRIGGER(irq) (s->irq_state[irq].edge_trigger)
#define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ? \
s->priority1[irq][cpu] : \
s->priority2[(irq) - GIC_INTERNAL])
@@ -61,5 +61,6 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu);
void gic_complete_irq(GICState *s, int cpu, int irq);
void gic_update(GICState *s);
void gic_init_irqs_and_distributor(GICState *s, int num_irq);
+void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val);
#endif /* !QEMU_ARM_GIC_INTERNAL_H */
diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
index 42e00bc4b8..d1813f76b6 100644
--- a/hw/intc/grlib_irqmp.c
+++ b/hw/intc/grlib_irqmp.c
@@ -355,6 +355,8 @@ static void grlib_irqmp_class_init(ObjectClass *klass, void *data)
k->init = grlib_irqmp_init;
dc->reset = grlib_irqmp_reset;
dc->props = grlib_irqmp_properties;
+ /* Reason: pointer properties "set_pil_in", "set_pil_in_opaque" */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo grlib_irqmp_info = {
diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c
index 803d037f68..9d293999be 100644
--- a/hw/intc/i8259_common.c
+++ b/hw/intc/i8259_common.c
@@ -135,9 +135,15 @@ static void pic_common_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &vmstate_pic_common;
- dc->no_user = 1;
dc->props = pic_properties_common;
dc->realize = pic_common_realize;
+ /*
+ * Reason: unlike ordinary ISA devices, the PICs need additional
+ * wiring: its IRQ input lines are set up by board code, and the
+ * wiring of the slave to the master is hard-coded in device model
+ * code.
+ */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo pic_common_type = {
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
index d866e00297..652dd47a1c 100644
--- a/hw/intc/ioapic.c
+++ b/hw/intc/ioapic.c
@@ -36,6 +36,9 @@
static IOAPICCommonState *ioapics[MAX_IOAPICS];
+/* global variable from ioapic_common.c */
+extern int ioapic_no;
+
static void ioapic_service(IOAPICCommonState *s)
{
uint8_t i;
@@ -225,14 +228,16 @@ static const MemoryRegionOps ioapic_io_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void ioapic_init(IOAPICCommonState *s, int instance_no)
+static void ioapic_realize(DeviceState *dev, Error **errp)
{
+ IOAPICCommonState *s = IOAPIC_COMMON(dev);
+
memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s,
"ioapic", 0x1000);
- qdev_init_gpio_in(DEVICE(s), ioapic_set_irq, IOAPIC_NUM_PINS);
+ qdev_init_gpio_in(dev, ioapic_set_irq, IOAPIC_NUM_PINS);
- ioapics[instance_no] = s;
+ ioapics[ioapic_no] = s;
}
static void ioapic_class_init(ObjectClass *klass, void *data)
@@ -240,7 +245,7 @@ static void ioapic_class_init(ObjectClass *klass, void *data)
IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
- k->init = ioapic_init;
+ k->realize = ioapic_realize;
dc->reset = ioapic_reset_common;
}
diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c
index 6b705c1546..4d3d309b62 100644
--- a/hw/intc/ioapic_common.c
+++ b/hw/intc/ioapic_common.c
@@ -23,6 +23,14 @@
#include "hw/i386/ioapic_internal.h"
#include "hw/sysbus.h"
+/* ioapic_no count start from 0 to MAX_IOAPICS,
+ * remove as static variable from ioapic_common_init.
+ * now as a global variable, let child to increase the counter
+ * then we can drop the 'instance_no' argument
+ * and convert to our QOM's realize function
+ */
+int ioapic_no;
+
void ioapic_reset_common(DeviceState *dev)
{
IOAPICCommonState *s = IOAPIC_COMMON(dev);
@@ -61,7 +69,6 @@ static void ioapic_common_realize(DeviceState *dev, Error **errp)
{
IOAPICCommonState *s = IOAPIC_COMMON(dev);
IOAPICCommonClass *info;
- static int ioapic_no;
if (ioapic_no >= MAX_IOAPICS) {
error_setg(errp, "Only %d ioapics allowed", MAX_IOAPICS);
@@ -69,7 +76,7 @@ static void ioapic_common_realize(DeviceState *dev, Error **errp)
}
info = IOAPIC_COMMON_GET_CLASS(s);
- info->init(s, ioapic_no);
+ info->realize(dev, errp);
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io_memory);
ioapic_no++;
@@ -98,7 +105,6 @@ static void ioapic_common_class_init(ObjectClass *klass, void *data)
dc->realize = ioapic_common_realize;
dc->vmsd = &vmstate_ioapic_common;
- dc->no_user = 1;
}
static const TypeInfo ioapic_common_type = {
@@ -110,9 +116,9 @@ static const TypeInfo ioapic_common_type = {
.abstract = true,
};
-static void register_types(void)
+static void ioapic_common_register_types(void)
{
type_register_static(&ioapic_common_type);
}
-type_init(register_types)
+type_init(ioapic_common_register_types)
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
index 7dd63da802..ad3931c112 100644
--- a/hw/intc/omap_intc.c
+++ b/hw/intc/omap_intc.c
@@ -392,6 +392,8 @@ static void omap_intc_class_init(ObjectClass *klass, void *data)
k->init = omap_intc_init;
dc->reset = omap_inth_reset;
dc->props = omap_intc_properties;
+ /* Reason: pointer property "clk" */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo omap_intc_info = {
@@ -637,6 +639,8 @@ static void omap2_intc_class_init(ObjectClass *klass, void *data)
k->init = omap2_intc_init;
dc->reset = omap_inth_reset;
dc->props = omap2_intc_properties;
+ /* Reason: pointer property "iclk", "fclk" */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo omap2_intc_info = {
diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c
index 329680da3a..2bf359a76b 100644
--- a/hw/intc/pl190.c
+++ b/hw/intc/pl190.c
@@ -273,7 +273,6 @@ static void pl190_class_init(ObjectClass *klass, void *data)
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = pl190_init;
- dc->no_user = 1;
dc->reset = pl190_reset;
dc->vmsd = &vmstate_pl190;
}
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index a333305d3d..b437563fb9 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -723,7 +723,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t nr, server, priority;
if ((nargs != 3) || (nret != 1)) {
- rtas_st(rets, 0, -3);
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@@ -733,13 +733,13 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
|| (priority > 0xff)) {
- rtas_st(rets, 0, -3);
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
ics_write_xive(ics, nr, server, priority, priority);
- rtas_st(rets, 0, 0); /* Success */
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@@ -751,18 +751,18 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t nr;
if ((nargs != 1) || (nret != 3)) {
- rtas_st(rets, 0, -3);
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
nr = rtas_ld(args, 0);
if (!ics_valid_irq(ics, nr)) {
- rtas_st(rets, 0, -3);
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
- rtas_st(rets, 0, 0); /* Success */
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
}
@@ -776,21 +776,21 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t nr;
if ((nargs != 1) || (nret != 1)) {
- rtas_st(rets, 0, -3);
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
nr = rtas_ld(args, 0);
if (!ics_valid_irq(ics, nr)) {
- rtas_st(rets, 0, -3);
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
ics->irqs[nr - ics->offset].priority);
- rtas_st(rets, 0, 0); /* Success */
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@@ -802,14 +802,14 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t nr;
if ((nargs != 1) || (nret != 1)) {
- rtas_st(rets, 0, -3);
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
nr = rtas_ld(args, 0);
if (!ics_valid_irq(ics, nr)) {
- rtas_st(rets, 0, -3);
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@@ -817,7 +817,7 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr,
ics->irqs[nr - ics->offset].saved_priority,
ics->irqs[nr - ics->offset].saved_priority);
- rtas_st(rets, 0, 0); /* Success */
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
/*