diff options
Diffstat (limited to 'hw/intc')
-rw-r--r-- | hw/intc/Makefile.objs | 1 | ||||
-rw-r--r-- | hw/intc/allwinner-a10-pic.c | 200 | ||||
-rw-r--r-- | hw/intc/apic.c | 48 | ||||
-rw-r--r-- | hw/intc/apic_common.c | 79 | ||||
-rw-r--r-- | hw/intc/arm_gic.c | 28 | ||||
-rw-r--r-- | hw/intc/arm_gic_common.c | 5 | ||||
-rw-r--r-- | hw/intc/arm_gic_kvm.c | 1 | ||||
-rw-r--r-- | hw/intc/etraxfs_pic.c | 4 | ||||
-rw-r--r-- | hw/intc/gic_internal.h | 7 | ||||
-rw-r--r-- | hw/intc/grlib_irqmp.c | 2 | ||||
-rw-r--r-- | hw/intc/i8259_common.c | 8 | ||||
-rw-r--r-- | hw/intc/ioapic.c | 13 | ||||
-rw-r--r-- | hw/intc/ioapic_common.c | 16 | ||||
-rw-r--r-- | hw/intc/omap_intc.c | 4 | ||||
-rw-r--r-- | hw/intc/pl190.c | 1 | ||||
-rw-r--r-- | hw/intc/xics.c | 24 |
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); } /* |