diff options
author | Anthony Liguori <aliguori@amazon.com> | 2013-11-05 10:33:32 -0800 |
---|---|---|
committer | Anthony Liguori <aliguori@amazon.com> | 2013-11-05 10:33:32 -0800 |
commit | a30b377e0a921bf93349dc4adb94580a3bec7ea4 (patch) | |
tree | ac3d4a52357d07b7c3d6928fc6001845fcb06c45 /hw | |
parent | c905c5012ac0c6fde3b8094d2206a3139deddba2 (diff) | |
parent | 80bbaee66ac38bcb5fe5a6f285e20457afcc8bec (diff) |
Merge remote-tracking branch 'afaerber/tags/qom-devices-for-anthony' into staging
QOM device refactorings
* QTest coverage for all machines
* QOM realize for Milkymist UART
* QOM realize for ARM MPCore
* device_add bug fixes and cleanups
* QOM for PCMCIA/MicroDrive (last legacy IDE device)
# gpg: Signature made Tue 05 Nov 2013 09:07:03 AM PST using RSA key ID 3E7E013F
# gpg: Can't check signature: public key not found
# By Andreas Färber (49) and others
# Via Andreas Färber
* afaerber/tags/qom-devices-for-anthony: (54 commits)
pcmcia/pxa2xx: QOM'ify PXA2xxPCMCIAState
ide: Drop ide_init2_with_non_qdev_drives()
microdrive: Coding Style cleanups
pcmcia: QOM'ify PCMCIACardState and MicroDriveState
pxa: Fix typo "dettach"
qom: Fix pointer to int property helpers' documentation
qdev-monitor: Inline qdev_init() for device_add
qdev-monitor: Avoid qdev as variable name
qdev: Drop misleading qdev_free() function
qdev-monitor: Unref device when device_add fails
qdev-monitor: Fix crash when device_add is called with abstract driver
qdev-monitor: Clean up qdev_device_add() variable naming
arm11mpcore: Split off RealView MPCore
arm11mpcore: Prepare for QOM embedding
arm11mpcore: Convert mpcore_rirq_state to QOM realize
realview_gic: Prepare for QOM embedding
realview_gic: Convert to QOM realize
arm11mpcore: Convert ARM11MPCorePriveState to QOM realize
arm11mpcore: Split off SCU device
arm11mpcore: Create container MemoryRegion in instance_init
...
Diffstat (limited to 'hw')
49 files changed, 878 insertions, 678 deletions
diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 0243d6aa0e..d91b9cc6c6 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -18,6 +18,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += net/ devices-dirs-$(CONFIG_SOFTMMU) += nvram/ devices-dirs-$(CONFIG_SOFTMMU) += pci/ devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/ +devices-dirs-$(CONFIG_SOFTMMU) += pcmcia/ devices-dirs-$(CONFIG_SOFTMMU) += scsi/ devices-dirs-$(CONFIG_SOFTMMU) += sd/ devices-dirs-$(CONFIG_SOFTMMU) += ssi/ diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 3bcd890567..93849c8d36 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -328,7 +328,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots) if (pc->no_hotplug) { slot_free = false; } else { - qdev_free(qdev); + object_unparent(OBJECT(qdev)); } } } diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index 89a9015de7..397e8dfb37 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -11,6 +11,8 @@ #include "hw/arm/arm.h" #include "hw/loader.h" #include "elf.h" +#include "sysemu/qtest.h" +#include "qemu/error-report.h" /* Bitbanded IO. Each word corresponds to a single bit. */ @@ -232,21 +234,22 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, big_endian = 0; #endif - if (!kernel_filename) { + if (!kernel_filename && !qtest_enabled()) { fprintf(stderr, "Guest image must be specified (using -kernel)\n"); exit(1); } - image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr, - NULL, big_endian, ELF_MACHINE, 1); - if (image_size < 0) { - image_size = load_image_targphys(kernel_filename, 0, flash_size); - lowaddr = 0; - } - if (image_size < 0) { - fprintf(stderr, "qemu: could not load kernel '%s'\n", - kernel_filename); - exit(1); + if (kernel_filename) { + image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr, + NULL, big_endian, ELF_MACHINE, 1); + if (image_size < 0) { + image_size = load_image_targphys(kernel_filename, 0, flash_size); + lowaddr = 0; + } + if (image_size < 0) { + error_report("Could not load kernel '%s'", kernel_filename); + exit(1); + } } /* Hack to map an additional page of ram at the top of the address diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c index 2929f9f8ab..26cedecee3 100644 --- a/hw/arm/exynos4_boards.c +++ b/hw/arm/exynos4_boards.c @@ -22,6 +22,7 @@ */ #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "hw/sysbus.h" #include "net/net.h" #include "hw/arm/arm.h" @@ -96,7 +97,7 @@ static void lan9215_init(uint32_t base, qemu_irq irq) static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args, Exynos4BoardType board_type) { - if (smp_cpus != EXYNOS4210_NCPUS) { + if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) { fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus" " value.\n", exynos4_machines[board_type].name, diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c index e97fbbd231..aeea17295b 100644 --- a/hw/arm/gumstix.c +++ b/hw/arm/gumstix.c @@ -42,6 +42,7 @@ #include "hw/boards.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" static const int sector_len = 128 * 1024; @@ -58,7 +59,7 @@ static void connex_init(QEMUMachineInitArgs *args) cpu = pxa255_init(address_space_mem, connex_ram); dinfo = drive_get(IF_PFLASH, 0, 0); - if (!dinfo) { + if (!dinfo && !qtest_enabled()) { fprintf(stderr, "A flash image must be given with the " "'pflash' parameter\n"); exit(1); @@ -70,7 +71,8 @@ static void connex_init(QEMUMachineInitArgs *args) be = 0; #endif if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom, - dinfo->bdrv, sector_len, connex_rom / sector_len, + dinfo ? dinfo->bdrv : NULL, + sector_len, connex_rom / sector_len, 2, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); @@ -95,7 +97,7 @@ static void verdex_init(QEMUMachineInitArgs *args) cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0"); dinfo = drive_get(IF_PFLASH, 0, 0); - if (!dinfo) { + if (!dinfo && !qtest_enabled()) { fprintf(stderr, "A flash image must be given with the " "'pflash' parameter\n"); exit(1); @@ -107,7 +109,8 @@ static void verdex_init(QEMUMachineInitArgs *args) be = 0; #endif if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom, - dinfo->bdrv, sector_len, verdex_rom / sector_len, + dinfo ? dinfo->bdrv : NULL, + sector_len, verdex_rom / sector_len, 2, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c index b244f7e112..9402c841e9 100644 --- a/hw/arm/mainstone.c +++ b/hw/arm/mainstone.c @@ -21,6 +21,7 @@ #include "sysemu/blockdev.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" /* Device addresses */ #define MST_FPGA_PHYS 0x08000000 @@ -127,6 +128,9 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, for (i = 0; i < 2; i ++) { dinfo = drive_get(IF_PFLASH, 0, i); if (!dinfo) { + if (qtest_enabled()) { + break; + } fprintf(stderr, "Two flash images must be given with the " "'pflash' parameter\n"); exit(1); @@ -147,7 +151,6 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, qdev_get_gpio_in(mpu->gpio, 0)); /* setup keypad */ - printf("map addr %p\n", &map); pxa27x_register_keypad(mpu->kp, map, 0xe0); /* MMC/SD host */ diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c index 03b381688b..3ba263ab4d 100644 --- a/hw/arm/omap_sx1.c +++ b/hw/arm/omap_sx1.c @@ -32,6 +32,7 @@ #include "hw/arm/arm.h" #include "hw/block/flash.h" #include "sysemu/blockdev.h" +#include "sysemu/qtest.h" #include "exec/address-spaces.h" /*****************************************************************************/ @@ -188,7 +189,7 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version) OMAP_CS1_BASE, &cs[1]); } - if (!args->kernel_filename && !fl_idx) { + if (!args->kernel_filename && !fl_idx && !qtest_enabled()) { fprintf(stderr, "Kernel or Flash image must be specified\n"); exit(1); } diff --git a/hw/arm/palm.c b/hw/arm/palm.c index 0b72bbe5fb..fac4f69807 100644 --- a/hw/arm/palm.c +++ b/hw/arm/palm.c @@ -19,6 +19,7 @@ #include "hw/hw.h" #include "audio/audio.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "ui/console.h" #include "hw/arm/omap.h" #include "hw/boards.h" @@ -255,7 +256,7 @@ static void palmte_init(QEMUMachineInitArgs *args) } } - if (!rom_loaded && !kernel_filename) { + if (!rom_loaded && !kernel_filename && !qtest_enabled()) { fprintf(stderr, "Kernel or ROM image must be specified\n"); exit(1); } diff --git a/hw/arm/z2.c b/hw/arm/z2.c index a00fcc042d..d52c5019b3 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -24,6 +24,7 @@ #include "ui/console.h" #include "audio/audio.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" #ifdef DEBUG_Z2 #define DPRINTF(fmt, ...) \ @@ -323,7 +324,7 @@ static void z2_init(QEMUMachineInitArgs *args) be = 0; #endif dinfo = drive_get(IF_PFLASH, 0, 0); - if (!dinfo) { + if (!dinfo && !qtest_enabled()) { fprintf(stderr, "Flash image must be given with the " "'pflash' parameter\n"); exit(1); @@ -331,7 +332,7 @@ static void z2_init(QEMUMachineInitArgs *args) if (!pflash_cfi01_register(Z2_FLASH_BASE, NULL, "z2.flash0", Z2_FLASH_SIZE, - dinfo->bdrv, sector_len, + dinfo ? dinfo->bdrv : NULL, sector_len, Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); diff --git a/hw/block/tc58128.c b/hw/block/tc58128.c index a3929d444f..728f1c3b68 100644 --- a/hw/block/tc58128.c +++ b/hw/block/tc58128.c @@ -1,6 +1,8 @@ #include "hw/hw.h" #include "hw/sh4/sh.h" #include "hw/loader.h" +#include "sysemu/qtest.h" +#include "qemu/error-report.h" #define CE1 0x0100 #define CE2 0x0200 @@ -36,10 +38,10 @@ static void init_dev(tc58128_dev * dev, const char *filename) /* Load flash image skipping the first block */ ret = load_image(filename, dev->flash_contents + 528 * 32); if (ret < 0) { - fprintf(stderr, "ret=%d\n", ret); - fprintf(stderr, "qemu: could not load flash image %s\n", - filename); - exit(1); + if (!qtest_enabled()) { + error_report("Could not load flash image %s", filename); + exit(1); + } } else { /* Build first block with number of blocks */ blocks = (ret + 528 * 32 - 1) / (528 * 32); diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c index 2e4b5c58b0..2c52a0fa8e 100644 --- a/hw/char/milkymist-uart.c +++ b/hw/char/milkymist-uart.c @@ -195,22 +195,26 @@ static void milkymist_uart_reset(DeviceState *d) s->regs[R_STAT] = STAT_THRE; } -static int milkymist_uart_init(SysBusDevice *dev) +static void milkymist_uart_realize(DeviceState *dev, Error **errp) { MilkymistUartState *s = MILKYMIST_UART(dev); - sysbus_init_irq(dev, &s->irq); - - memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s, - "milkymist-uart", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); - s->chr = qemu_char_get_next_serial(); if (s->chr) { qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); } +} - return 0; +static void milkymist_uart_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + MilkymistUartState *s = MILKYMIST_UART(obj); + + sysbus_init_irq(sbd, &s->irq); + + memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s, + "milkymist-uart", R_MAX * 4); + sysbus_init_mmio(sbd, &s->regs_region); } static const VMStateDescription vmstate_milkymist_uart = { @@ -227,9 +231,8 @@ static const VMStateDescription vmstate_milkymist_uart = { static void milkymist_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = milkymist_uart_init; + dc->realize = milkymist_uart_realize; dc->reset = milkymist_uart_reset; dc->vmsd = &vmstate_milkymist_uart; } @@ -238,6 +241,7 @@ static const TypeInfo milkymist_uart_info = { .name = TYPE_MILKYMIST_UART, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(MilkymistUartState), + .instance_init = milkymist_uart_init, .class_init = milkymist_uart_class_init, }; diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 533f6dd122..e374a9399f 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -164,7 +164,7 @@ int qdev_init(DeviceState *dev) if (local_err != NULL) { qerror_report_err(local_err); error_free(local_err); - qdev_free(dev); + object_unparent(OBJECT(dev)); return -1; } return 0; @@ -258,7 +258,7 @@ void qbus_reset_all_fn(void *opaque) int qdev_simple_unplug_cb(DeviceState *dev) { /* just zap it */ - qdev_free(dev); + object_unparent(OBJECT(dev)); return 0; } @@ -280,12 +280,6 @@ void qdev_init_nofail(DeviceState *dev) } } -/* Unlink device from bus and free the structure. */ -void qdev_free(DeviceState *dev) -{ - object_unparent(OBJECT(dev)); -} - void qdev_machine_creation_done(void) { /* @@ -458,7 +452,7 @@ static void bus_unparent(Object *obj) while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) { DeviceState *dev = kid->child; - qdev_free(dev); + object_unparent(OBJECT(dev)); } if (bus->parent) { QLIST_REMOVE(bus, sibling); diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs index df287c1d8c..6381238cc5 100644 --- a/hw/cpu/Makefile.objs +++ b/hw/cpu/Makefile.objs @@ -1,4 +1,5 @@ obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o +obj-$(CONFIG_REALVIEW) += realview_mpcore.o obj-$(CONFIG_A9MPCORE) += a9mpcore.o obj-$(CONFIG_A15MPCORE) += a15mpcore.o obj-$(CONFIG_ICC_BUS) += icc_bus.o diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index 9abba67632..acc419e11a 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -18,55 +18,60 @@ * with this program; if not, see <http://www.gnu.org/licenses/>. */ -#include "hw/sysbus.h" +#include "hw/cpu/a15mpcore.h" #include "sysemu/kvm.h" -/* A15MP private memory region. */ - -#define TYPE_A15MPCORE_PRIV "a15mpcore_priv" -#define A15MPCORE_PRIV(obj) \ - OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV) - -typedef struct A15MPPrivState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - uint32_t num_cpu; - uint32_t num_irq; - MemoryRegion container; - DeviceState *gic; -} A15MPPrivState; - static void a15mp_priv_set_irq(void *opaque, int irq, int level) { A15MPPrivState *s = (A15MPPrivState *)opaque; - qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); + + qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level); } -static int a15mp_priv_init(SysBusDevice *dev) +static void a15mp_priv_initfn(Object *obj) { - A15MPPrivState *s = A15MPCORE_PRIV(dev); - SysBusDevice *busdev; + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + A15MPPrivState *s = A15MPCORE_PRIV(obj); + DeviceState *gicdev; const char *gictype = "arm_gic"; - int i; if (kvm_irqchip_in_kernel()) { gictype = "kvm-arm-gic"; } - s->gic = qdev_create(NULL, gictype); - qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); - qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq); - qdev_prop_set_uint32(s->gic, "revision", 2); - qdev_init_nofail(s->gic); - busdev = SYS_BUS_DEVICE(s->gic); + memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000); + sysbus_init_mmio(sbd, &s->container); + + object_initialize(&s->gic, sizeof(s->gic), gictype); + gicdev = DEVICE(&s->gic); + qdev_set_parent_bus(gicdev, sysbus_get_default()); + qdev_prop_set_uint32(gicdev, "revision", 2); +} + +static void a15mp_priv_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + A15MPPrivState *s = A15MPCORE_PRIV(dev); + DeviceState *gicdev; + SysBusDevice *busdev; + int i; + Error *err = NULL; + + gicdev = DEVICE(&s->gic); + qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu); + qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq); + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + busdev = SYS_BUS_DEVICE(&s->gic); /* Pass through outbound IRQ lines from the GIC */ - sysbus_pass_irq(dev, busdev); + sysbus_pass_irq(sbd, busdev); /* Pass through inbound GPIO lines to the GIC */ - qdev_init_gpio_in(DEVICE(dev), a15mp_priv_set_irq, s->num_irq - 32); + qdev_init_gpio_in(dev, a15mp_priv_set_irq, s->num_irq - 32); /* Wire the outputs from each CPU's generic timer to the * appropriate GIC PPI inputs @@ -78,10 +83,10 @@ static int a15mp_priv_init(SysBusDevice *dev) * since a real A15 always has TrustZone but QEMU doesn't. */ qdev_connect_gpio_out(cpudev, 0, - qdev_get_gpio_in(s->gic, ppibase + 30)); + qdev_get_gpio_in(gicdev, ppibase + 30)); /* virtual timer */ qdev_connect_gpio_out(cpudev, 1, - qdev_get_gpio_in(s->gic, ppibase + 27)); + qdev_get_gpio_in(gicdev, ppibase + 27)); } /* Memory map (addresses are offsets from PERIPHBASE): @@ -92,15 +97,10 @@ static int a15mp_priv_init(SysBusDevice *dev) * 0x5000-0x5fff -- GIC virtual interface control (not modelled) * 0x6000-0x7fff -- GIC virtual CPU interface (not modelled) */ - memory_region_init(&s->container, OBJECT(s), - "a15mp-priv-container", 0x8000); memory_region_add_subregion(&s->container, 0x1000, sysbus_mmio_get_region(busdev, 0)); memory_region_add_subregion(&s->container, 0x2000, sysbus_mmio_get_region(busdev, 1)); - - sysbus_init_mmio(dev, &s->container); - return 0; } static Property a15mp_priv_properties[] = { @@ -118,8 +118,8 @@ static Property a15mp_priv_properties[] = { static void a15mp_priv_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = a15mp_priv_init; + + dc->realize = a15mp_priv_realize; dc->props = a15mp_priv_properties; /* We currently have no savable state */ } @@ -128,6 +128,7 @@ static const TypeInfo a15mp_priv_info = { .name = TYPE_A15MPCORE_PRIV, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(A15MPPrivState), + .instance_init = a15mp_priv_initfn, .class_init = a15mp_priv_class_init, }; diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index 3e675e3941..918a7d1291 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -8,64 +8,86 @@ * This code is licensed under the GPL. */ -#include "hw/sysbus.h" - -#define TYPE_A9MPCORE_PRIV "a9mpcore_priv" -#define A9MPCORE_PRIV(obj) \ - OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV) - -typedef struct A9MPPrivState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - uint32_t num_cpu; - MemoryRegion container; - DeviceState *mptimer; - DeviceState *wdt; - DeviceState *gic; - DeviceState *scu; - uint32_t num_irq; -} A9MPPrivState; +#include "hw/cpu/a9mpcore.h" static void a9mp_priv_set_irq(void *opaque, int irq, int level) { A9MPPrivState *s = (A9MPPrivState *)opaque; - qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); + + qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level); +} + +static void a9mp_priv_initfn(Object *obj) +{ + A9MPPrivState *s = A9MPCORE_PRIV(obj); + + memory_region_init(&s->container, obj, "a9mp-priv-container", 0x2000); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->container); + + object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC); + qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); + + object_initialize(&s->scu, sizeof(s->scu), TYPE_A9_SCU); + qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default()); + + object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER); + qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default()); + + object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ARM_MPTIMER); + qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default()); } -static int a9mp_priv_init(SysBusDevice *dev) +static void a9mp_priv_realize(DeviceState *dev, Error **errp) { + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); A9MPPrivState *s = A9MPCORE_PRIV(dev); + DeviceState *gicdev, *scudev, *mptimerdev, *wdtdev; SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev; + Error *err = NULL; int i; - s->gic = qdev_create(NULL, "arm_gic"); - qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); - qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq); - qdev_init_nofail(s->gic); - gicbusdev = SYS_BUS_DEVICE(s->gic); + gicdev = DEVICE(&s->gic); + qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu); + qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq); + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + gicbusdev = SYS_BUS_DEVICE(&s->gic); /* Pass through outbound IRQ lines from the GIC */ - sysbus_pass_irq(dev, gicbusdev); + sysbus_pass_irq(sbd, gicbusdev); /* Pass through inbound GPIO lines to the GIC */ - qdev_init_gpio_in(DEVICE(dev), a9mp_priv_set_irq, s->num_irq - 32); - - s->scu = qdev_create(NULL, "a9-scu"); - qdev_prop_set_uint32(s->scu, "num-cpu", s->num_cpu); - qdev_init_nofail(s->scu); - scubusdev = SYS_BUS_DEVICE(s->scu); - - s->mptimer = qdev_create(NULL, "arm_mptimer"); - qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu); - qdev_init_nofail(s->mptimer); - timerbusdev = SYS_BUS_DEVICE(s->mptimer); - - s->wdt = qdev_create(NULL, "arm_mptimer"); - qdev_prop_set_uint32(s->wdt, "num-cpu", s->num_cpu); - qdev_init_nofail(s->wdt); - wdtbusdev = SYS_BUS_DEVICE(s->wdt); + qdev_init_gpio_in(dev, a9mp_priv_set_irq, s->num_irq - 32); + + scudev = DEVICE(&s->scu); + qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->scu), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + scubusdev = SYS_BUS_DEVICE(&s->scu); + + mptimerdev = DEVICE(&s->mptimer); + qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + timerbusdev = SYS_BUS_DEVICE(&s->mptimer); + + wdtdev = DEVICE(&s->wdt); + qdev_prop_set_uint32(wdtdev, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + wdtbusdev = SYS_BUS_DEVICE(&s->wdt); /* Memory map (addresses are offsets from PERIPHBASE): * 0x0000-0x00ff -- Snoop Control Unit @@ -78,7 +100,6 @@ static int a9mp_priv_init(SysBusDevice *dev) * * We should implement the global timer but don't currently do so. */ - memory_region_init(&s->container, OBJECT(s), "a9mp-priv-container", 0x2000); memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(scubusdev, 0)); /* GIC CPU interface */ @@ -94,19 +115,16 @@ static int a9mp_priv_init(SysBusDevice *dev) memory_region_add_subregion(&s->container, 0x1000, sysbus_mmio_get_region(gicbusdev, 0)); - sysbus_init_mmio(dev, &s->container); - /* Wire up the interrupt from each watchdog and timer. * For each core the timer is PPI 29 and the watchdog PPI 30. */ for (i = 0; i < s->num_cpu; i++) { int ppibase = (s->num_irq - 32) + i * 32; sysbus_connect_irq(timerbusdev, i, - qdev_get_gpio_in(s->gic, ppibase + 29)); + qdev_get_gpio_in(gicdev, ppibase + 29)); sysbus_connect_irq(wdtbusdev, i, - qdev_get_gpio_in(s->gic, ppibase + 30)); + qdev_get_gpio_in(gicdev, ppibase + 30)); } - return 0; } static Property a9mp_priv_properties[] = { @@ -124,9 +142,8 @@ static Property a9mp_priv_properties[] = { static void a9mp_priv_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = a9mp_priv_init; + dc->realize = a9mp_priv_realize; dc->props = a9mp_priv_properties; } @@ -134,6 +151,7 @@ static const TypeInfo a9mp_priv_info = { .name = TYPE_A9MPCORE_PRIV, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(A9MPPrivState), + .instance_init = a9mp_priv_initfn, .class_init = a9mp_priv_class_init, }; diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index a786c628dd..717d3e4f88 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -7,96 +7,28 @@ * This code is licensed under the GPL. */ -#include "hw/sysbus.h" -#include "qemu/timer.h" +#include "hw/cpu/arm11mpcore.h" +#include "hw/intc/realview_gic.h" -/* MPCore private memory region. */ - -#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv" -#define ARM11MPCORE_PRIV(obj) \ - OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV) - -typedef struct ARM11MPCorePriveState { - SysBusDevice parent_obj; - - uint32_t scu_control; - int iomemtype; - uint32_t old_timer_status[8]; - uint32_t num_cpu; - MemoryRegion iomem; - MemoryRegion container; - DeviceState *mptimer; - DeviceState *wdtimer; - DeviceState *gic; - uint32_t num_irq; -} ARM11MPCorePriveState; - -/* Per-CPU private memory mapped IO. */ - -static uint64_t mpcore_scu_read(void *opaque, hwaddr offset, - unsigned size) -{ - ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque; - int id; - /* SCU */ - switch (offset) { - case 0x00: /* Control. */ - return s->scu_control; - case 0x04: /* Configuration. */ - id = ((1 << s->num_cpu) - 1) << 4; - return id | (s->num_cpu - 1); - case 0x08: /* CPU status. */ - return 0; - case 0x0c: /* Invalidate all. */ - return 0; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "mpcore_priv_read: Bad offset %x\n", (int)offset); - return 0; - } -} - -static void mpcore_scu_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque; - /* SCU */ - switch (offset) { - case 0: /* Control register. */ - s->scu_control = value & 1; - break; - case 0x0c: /* Invalidate all. */ - /* This is a no-op as cache is not emulated. */ - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "mpcore_priv_read: Bad offset %x\n", (int)offset); - } -} - -static const MemoryRegionOps mpcore_scu_ops = { - .read = mpcore_scu_read, - .write = mpcore_scu_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; static void mpcore_priv_set_irq(void *opaque, int irq, int level) { ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque; - qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); + + qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level); } static void mpcore_priv_map_setup(ARM11MPCorePriveState *s) { int i; - SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic); - SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer); - SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer); - memory_region_init(&s->container, OBJECT(s), - "mpcode-priv-container", 0x2000); - memory_region_init_io(&s->iomem, OBJECT(s), - &mpcore_scu_ops, s, "mpcore-scu", 0x100); - memory_region_add_subregion(&s->container, 0, &s->iomem); + SysBusDevice *scubusdev = SYS_BUS_DEVICE(&s->scu); + DeviceState *gicdev = DEVICE(&s->gic); + SysBusDevice *gicbusdev = SYS_BUS_DEVICE(&s->gic); + SysBusDevice *timerbusdev = SYS_BUS_DEVICE(&s->mptimer); + SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(&s->wdtimer); + + memory_region_add_subregion(&s->container, 0, + sysbus_mmio_get_region(scubusdev, 0)); /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs * at 0x200, 0x300... */ @@ -124,134 +56,84 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s) for (i = 0; i < s->num_cpu; i++) { int ppibase = (s->num_irq - 32) + i * 32; sysbus_connect_irq(timerbusdev, i, - qdev_get_gpio_in(s->gic, ppibase + 29)); + qdev_get_gpio_in(gicdev, ppibase + 29)); sysbus_connect_irq(wdtbusdev, i, - qdev_get_gpio_in(s->gic, ppibase + 30)); + qdev_get_gpio_in(gicdev, ppibase + 30)); } } -static int mpcore_priv_init(SysBusDevice *sbd) +static void mpcore_priv_realize(DeviceState *dev, Error **errp) { - DeviceState *dev = DEVICE(sbd); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(dev); + DeviceState *scudev = DEVICE(&s->scu); + DeviceState *gicdev = DEVICE(&s->gic); + DeviceState *mptimerdev = DEVICE(&s->mptimer); + DeviceState *wdtimerdev = DEVICE(&s->wdtimer); + Error *err = NULL; + + qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->scu), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } - s->gic = qdev_create(NULL, "arm_gic"); - qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); - qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq); - /* Request the legacy 11MPCore GIC behaviour: */ - qdev_prop_set_uint32(s->gic, "revision", 0); - qdev_init_nofail(s->gic); + qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu); + qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq); + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } /* Pass through outbound IRQ lines from the GIC */ - sysbus_pass_irq(sbd, SYS_BUS_DEVICE(s->gic)); + sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->gic)); /* Pass through inbound GPIO lines to the GIC */ qdev_init_gpio_in(dev, mpcore_priv_set_irq, s->num_irq - 32); - s->mptimer = qdev_create(NULL, "arm_mptimer"); - qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu); - qdev_init_nofail(s->mptimer); + qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } - s->wdtimer = qdev_create(NULL, "arm_mptimer"); - qdev_prop_set_uint32(s->wdtimer, "num-cpu", s->num_cpu); - qdev_init_nofail(s->wdtimer); + qdev_prop_set_uint32(wdtimerdev, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->wdtimer), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } mpcore_priv_map_setup(s); - sysbus_init_mmio(sbd, &s->container); - return 0; } -#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore" -#define REALVIEW_MPCORE_RIRQ(obj) \ - OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ) - -/* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ - controllers. The output of these, plus some of the raw input lines - are fed into a single SMP-aware interrupt controller on the CPU. */ -typedef struct { - SysBusDevice parent_obj; - - SysBusDevice *priv; - qemu_irq cpuic[32]; - qemu_irq rvic[4][64]; - uint32_t num_cpu; -} mpcore_rirq_state; - -/* Map baseboard IRQs onto CPU IRQ lines. */ -static const int mpcore_irq_map[32] = { - -1, -1, -1, -1, 1, 2, -1, -1, - -1, -1, 6, -1, 4, 5, -1, -1, - -1, 14, 15, 0, 7, 8, -1, -1, - -1, -1, -1, -1, 9, 3, -1, -1, -}; - -static void mpcore_rirq_set_irq(void *opaque, int irq, int level) +static void mpcore_priv_initfn(Object *obj) { - mpcore_rirq_state *s = (mpcore_rirq_state *)opaque; - int i; - - for (i = 0; i < 4; i++) { - qemu_set_irq(s->rvic[i][irq], level); - } - if (irq < 32) { - irq = mpcore_irq_map[irq]; - if (irq >= 0) { - qemu_set_irq(s->cpuic[irq], level); - } - } -} + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(obj); -static int realview_mpcore_init(SysBusDevice *sbd) -{ - DeviceState *dev = DEVICE(sbd); - mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev); - DeviceState *gic; - DeviceState *priv; - int n; - int i; + memory_region_init(&s->container, OBJECT(s), + "mpcore-priv-container", 0x2000); + sysbus_init_mmio(sbd, &s->container); - priv = qdev_create(NULL, TYPE_ARM11MPCORE_PRIV); - qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu); - qdev_init_nofail(priv); - s->priv = SYS_BUS_DEVICE(priv); - sysbus_pass_irq(sbd, s->priv); - for (i = 0; i < 32; i++) { - s->cpuic[i] = qdev_get_gpio_in(priv, i); - } - /* ??? IRQ routing is hardcoded to "normal" mode. */ - for (n = 0; n < 4; n++) { - gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000, - s->cpuic[10 + n]); - for (i = 0; i < 64; i++) { - s->rvic[n][i] = qdev_get_gpio_in(gic, i); - } - } - qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64); - sysbus_init_mmio(sbd, sysbus_mmio_get_region(s->priv, 0)); - return 0; -} + object_initialize(&s->scu, sizeof(s->scu), TYPE_ARM11_SCU); + qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default()); -static Property mpcore_rirq_properties[] = { - DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1), - DEFINE_PROP_END_OF_LIST(), -}; + object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC); + qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); + /* Request the legacy 11MPCore GIC behaviour: */ + qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 0); -static void mpcore_rirq_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER); + qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default()); - k->init = realview_mpcore_init; - dc->props = mpcore_rirq_properties; + object_initialize(&s->wdtimer, sizeof(s->wdtimer), TYPE_ARM_MPTIMER); + qdev_set_parent_bus(DEVICE(&s->wdtimer), sysbus_get_default()); } -static const TypeInfo mpcore_rirq_info = { - .name = TYPE_REALVIEW_MPCORE_RIRQ, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(mpcore_rirq_state), - .class_init = mpcore_rirq_class_init, -}; - static Property mpcore_priv_properties[] = { DEFINE_PROP_UINT32("num-cpu", ARM11MPCorePriveState, num_cpu, 1), /* The ARM11 MPCORE TRM says the on-chip controller may have @@ -269,9 +151,8 @@ static Property mpcore_priv_properties[] = { static void mpcore_priv_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = mpcore_priv_init; + dc->realize = mpcore_priv_realize; dc->props = mpcore_priv_properties; } @@ -279,12 +160,12 @@ static const TypeInfo mpcore_priv_info = { .name = TYPE_ARM11MPCORE_PRIV, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ARM11MPCorePriveState), + .instance_init = mpcore_priv_initfn, .class_init = mpcore_priv_class_init, }; static void arm11mpcore_register_types(void) { - type_register_static(&mpcore_rirq_info); type_register_static(&mpcore_priv_info); } diff --git a/hw/cpu/realview_mpcore.c b/hw/cpu/realview_mpcore.c new file mode 100644 index 0000000000..c39a2da42d --- /dev/null +++ b/hw/cpu/realview_mpcore.c @@ -0,0 +1,139 @@ +/* + * RealView ARM11MPCore internal peripheral emulation + * + * Copyright (c) 2006-2007 CodeSourcery. + * Copyright (c) 2013 SUSE LINUX Products GmbH + * Written by Paul Brook and Andreas Färber + * + * This code is licensed under the GPL. + */ + +#include "hw/cpu/arm11mpcore.h" +#include "hw/intc/realview_gic.h" + +#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore" +#define REALVIEW_MPCORE_RIRQ(obj) \ + OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ) + +/* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ + controllers. The output of these, plus some of the raw input lines + are fed into a single SMP-aware interrupt controller on the CPU. */ +typedef struct { + SysBusDevice parent_obj; + + qemu_irq cpuic[32]; + qemu_irq rvic[4][64]; + uint32_t num_cpu; + + ARM11MPCorePriveState priv; + RealViewGICState gic[4]; +} mpcore_rirq_state; + +/* Map baseboard IRQs onto CPU IRQ lines. */ +static const int mpcore_irq_map[32] = { + -1, -1, -1, -1, 1, 2, -1, -1, + -1, -1, 6, -1, 4, 5, -1, -1, + -1, 14, 15, 0, 7, 8, -1, -1, + -1, -1, -1, -1, 9, 3, -1, -1, +}; + +static void mpcore_rirq_set_irq(void *opaque, int irq, int level) +{ + mpcore_rirq_state *s = (mpcore_rirq_state *)opaque; + int i; + + for (i = 0; i < 4; i++) { + qemu_set_irq(s->rvic[i][irq], level); + } + if (irq < 32) { + irq = mpcore_irq_map[irq]; + if (irq >= 0) { + qemu_set_irq(s->cpuic[irq], level); + } + } +} + +static void realview_mpcore_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev); + DeviceState *priv = DEVICE(&s->priv); + DeviceState *gic; + SysBusDevice *gicbusdev; + Error *err = NULL; + int n; + int i; + + qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->priv), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv)); + for (i = 0; i < 32; i++) { + s->cpuic[i] = qdev_get_gpio_in(priv, i); + } + /* ??? IRQ routing is hardcoded to "normal" mode. */ + for (n = 0; n < 4; n++) { + object_property_set_bool(OBJECT(&s->gic[n]), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + gic = DEVICE(&s->gic[n]); + gicbusdev = SYS_BUS_DEVICE(&s->gic[n]); + sysbus_mmio_map(gicbusdev, 0, 0x10040000 + n * 0x10000); + sysbus_connect_irq(gicbusdev, 0, s->cpuic[10 + n]); + for (i = 0; i < 64; i++) { + s->rvic[n][i] = qdev_get_gpio_in(gic, i); + } + } + qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64); +} + +static void mpcore_rirq_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(obj); + SysBusDevice *privbusdev; + int i; + + object_initialize(&s->priv, sizeof(s->priv), TYPE_ARM11MPCORE_PRIV); + qdev_set_parent_bus(DEVICE(&s->priv), sysbus_get_default()); + privbusdev = SYS_BUS_DEVICE(&s->priv); + sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0)); + + for (i = 0; i < 4; i++) { + object_initialize(&s->gic[i], sizeof(s->gic[i]), TYPE_REALVIEW_GIC); + qdev_set_parent_bus(DEVICE(&s->gic[i]), sysbus_get_default()); + } +} + +static Property mpcore_rirq_properties[] = { + DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void mpcore_rirq_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = realview_mpcore_realize; + dc->props = mpcore_rirq_properties; +} + +static const TypeInfo mpcore_rirq_info = { + .name = TYPE_REALVIEW_MPCORE_RIRQ, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(mpcore_rirq_state), + .instance_init = mpcore_rirq_init, + .class_init = mpcore_rirq_class_init, +}; + +static void realview_mpcore_register_types(void) +{ + type_register_static(&mpcore_rirq_info); +} + +type_init(realview_mpcore_register_types) diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c index 03058d3bc5..55240886f5 100644 --- a/hw/cris/axis_dev88.c +++ b/hw/cris/axis_dev88.c @@ -32,6 +32,7 @@ #include "boot.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" #define D(x) #define DNAND(x) @@ -340,14 +341,14 @@ void axisdev88_init(QEMUMachineInitArgs *args) irq[0x14 + i]); } - if (!kernel_filename) { + if (kernel_filename) { + li.image_filename = kernel_filename; + li.cmdline = kernel_cmdline; + cris_load_image(cpu, &li); + } else if (!qtest_enabled()) { fprintf(stderr, "Kernel image must be specified\n"); exit(1); } - - li.image_filename = kernel_filename; - li.cmdline = kernel_cmdline; - cris_load_image(cpu, &li); } static QEMUMachine axisdev88_machine = { diff --git a/hw/ide/core.c b/hw/ide/core.c index 399b1bae68..e1f4c33fb8 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2215,55 +2215,6 @@ void ide_init2(IDEBus *bus, qemu_irq irq) bus->dma = &ide_dma_nop; } -/* TODO convert users to qdev and remove */ -void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, - DriveInfo *hd1, qemu_irq irq) -{ - int i, trans; - DriveInfo *dinfo; - uint32_t cyls, heads, secs; - - for(i = 0; i < 2; i++) { - dinfo = i == 0 ? hd0 : hd1; - ide_init1(bus, i); - if (dinfo) { - cyls = dinfo->cyls; - heads = dinfo->heads; - secs = dinfo->secs; - trans = dinfo->trans; - if (!cyls && !heads && !secs) { - hd_geometry_guess(dinfo->bdrv, &cyls, &heads, &secs, &trans); - } else if (trans == BIOS_ATA_TRANSLATION_AUTO) { - trans = hd_bios_chs_auto_trans(cyls, heads, secs); - } - if (cyls < 1 || cyls > 65535) { - error_report("cyls must be between 1 and 65535"); - exit(1); - } - if (heads < 1 || heads > 16) { - error_report("heads must be between 1 and 16"); - exit(1); - } - if (secs < 1 || secs > 255) { - error_report("secs must be between 1 and 255"); - exit(1); - } - if (ide_init_drive(&bus->ifs[i], dinfo->bdrv, - dinfo->media_cd ? IDE_CD : IDE_HD, - NULL, dinfo->serial, NULL, 0, - cyls, heads, secs, trans) < 0) { - error_report("Can't set up IDE drive %s", dinfo->id); - exit(1); - } - bdrv_attach_dev_nofail(dinfo->bdrv, &bus->ifs[i]); - } else { - ide_reset(&bus->ifs[i]); - } - } - bus->irq = irq; - bus->dma = &ide_dma_nop; -} - static const MemoryRegionPortio ide_portio_list[] = { { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write }, { 0, 2, 2, .read = ide_data_readw, .write = ide_data_writew }, diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 5d1cf87742..0567a522f5 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -553,8 +553,6 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, uint32_t cylinders, uint32_t heads, uint32_t secs, int chs_trans); void ide_init2(IDEBus *bus, qemu_irq irq); -void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, - DriveInfo *hd1, qemu_irq irq); void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); void ide_exec_cmd(IDEBus *bus, uint32_t val); diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 92c1df0460..21d6495817 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -30,15 +30,22 @@ #include <hw/ide/internal.h> +#define TYPE_MICRODRIVE "microdrive" +#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE) + /***********************************************************/ /* CF-ATA Microdrive */ #define METADATA_SIZE 0x20 /* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface. */ -typedef struct { + +typedef struct MicroDriveState { + /*< private >*/ + PCMCIACardState parent_obj; + /*< public >*/ + IDEBus bus; - PCMCIACardState card; uint32_t attr_base; uint32_t io_base; @@ -81,10 +88,13 @@ enum md_ctrl { static inline void md_interrupt_update(MicroDriveState *s) { - if (!s->card.slot) + PCMCIACardState *card = PCMCIA_CARD(s); + + if (card->slot == NULL) { return; + } - qemu_set_irq(s->card.slot->irq, + qemu_set_irq(card->slot->irq, !(s->stat & STAT_INT) && /* Inverted */ !(s->ctrl & (CTRL_IEN | CTRL_SRST)) && !(s->opt & OPT_SRESET)); @@ -93,16 +103,20 @@ static inline void md_interrupt_update(MicroDriveState *s) static void md_set_irq(void *opaque, int irq, int level) { MicroDriveState *s = opaque; - if (level) + + if (level) { s->stat |= STAT_INT; - else + } else { s->stat &= ~STAT_INT; + } md_interrupt_update(s); } -static void md_reset(MicroDriveState *s) +static void md_reset(DeviceState *dev) { + MicroDriveState *s = MICRODRIVE(dev); + s->opt = OPT_MODE_MMAP; s->stat = 0; s->pins = 0; @@ -111,14 +125,17 @@ static void md_reset(MicroDriveState *s) ide_bus_reset(&s->bus); } -static uint8_t md_attr_read(void *opaque, uint32_t at) +static uint8_t md_attr_read(PCMCIACardState *card, uint32_t at) { - MicroDriveState *s = opaque; + MicroDriveState *s = MICRODRIVE(card); + PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card); + if (at < s->attr_base) { - if (at < s->card.cis_len) - return s->card.cis[at]; - else + if (at < pcc->cis_len) { + return pcc->cis[at]; + } else { return 0x00; + } } at -= s->attr_base; @@ -127,10 +144,11 @@ static uint8_t md_attr_read(void *opaque, uint32_t at) case 0x00: /* Configuration Option Register */ return s->opt; case 0x02: /* Card Configuration Status Register */ - if (s->ctrl & CTRL_IEN) + if (s->ctrl & CTRL_IEN) { return s->stat & ~STAT_INT; - else + } else { return s->stat; + } case 0x04: /* Pin Replacement Register */ return (s->pins & PINS_CRDY) | 0x0c; case 0x06: /* Socket and Copy Register */ @@ -144,21 +162,24 @@ static uint8_t md_attr_read(void *opaque, uint32_t at) return 0; } -static void md_attr_write(void *opaque, uint32_t at, uint8_t value) +static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value) { - MicroDriveState *s = opaque; + MicroDriveState *s = MICRODRIVE(card); + at -= s->attr_base; switch (at) { case 0x00: /* Configuration Option Register */ s->opt = value & 0xcf; - if (value & OPT_SRESET) - md_reset(s); + if (value & OPT_SRESET) { + device_reset(DEVICE(s)); + } md_interrupt_update(s); break; case 0x02: /* Card Configuration Status Register */ - if ((s->stat ^ value) & STAT_PWRDWN) + if ((s->stat ^ value) & STAT_PWRDWN) { s->pins |= PINS_CRDY; + } s->stat &= 0x82; s->stat |= value & 0x74; md_interrupt_update(s); @@ -175,32 +196,35 @@ static void md_attr_write(void *opaque, uint32_t at, uint8_t value) } } -static uint16_t md_common_read(void *opaque, uint32_t at) +static uint16_t md_common_read(PCMCIACardState *card, uint32_t at) { - MicroDriveState *s = opaque; + MicroDriveState *s = MICRODRIVE(card); IDEState *ifs; uint16_t ret; at -= s->io_base; switch (s->opt & OPT_MODE) { case OPT_MODE_MMAP: - if ((at & ~0x3ff) == 0x400) + if ((at & ~0x3ff) == 0x400) { at = 0; + } break; case OPT_MODE_IOMAP16: at &= 0xf; break; case OPT_MODE_IOMAP1: - if ((at & ~0xf) == 0x3f0) + if ((at & ~0xf) == 0x3f0) { at -= 0x3e8; - else if ((at & ~0xf) == 0x1f0) + } else if ((at & ~0xf) == 0x1f0) { at -= 0x1f0; + } break; case OPT_MODE_IOMAP2: - if ((at & ~0xf) == 0x370) + if ((at & ~0xf) == 0x370) { at -= 0x368; - else if ((at & ~0xf) == 0x170) + } else if ((at & ~0xf) == 0x170) { at -= 0x170; + } } switch (at) { @@ -209,9 +233,9 @@ static uint16_t md_common_read(void *opaque, uint32_t at) return ide_data_readw(&s->bus, 0); /* TODO: 8-bit accesses */ - if (s->cycle) + if (s->cycle) { ret = s->io >> 8; - else { + } else { s->io = ide_data_readw(&s->bus, 0); ret = s->io & 0xff; } @@ -223,10 +247,11 @@ static uint16_t md_common_read(void *opaque, uint32_t at) return ide_ioport_read(&s->bus, 0x1); case 0xe: /* Alternate Status */ ifs = idebus_active_if(&s->bus); - if (ifs->bs) + if (ifs->bs) { return ifs->status; - else + } else { return 0; + } case 0xf: /* Device Address */ ifs = idebus_active_if(&s->bus); return 0xc2 | ((~ifs->select << 2) & 0x3c); @@ -237,30 +262,33 @@ static uint16_t md_common_read(void *opaque, uint32_t at) return 0; } -static void md_common_write(void *opaque, uint32_t at, uint16_t value) +static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value) { - MicroDriveState *s = opaque; + MicroDriveState *s = MICRODRIVE(card); at -= s->io_base; switch (s->opt & OPT_MODE) { case OPT_MODE_MMAP: - if ((at & ~0x3ff) == 0x400) + if ((at & ~0x3ff) == 0x400) { at = 0; + } break; case OPT_MODE_IOMAP16: at &= 0xf; break; case OPT_MODE_IOMAP1: - if ((at & ~0xf) == 0x3f0) + if ((at & ~0xf) == 0x3f0) { at -= 0x3e8; - else if ((at & ~0xf) == 0x1f0) + } else if ((at & ~0xf) == 0x1f0) { at -= 0x1f0; + } break; case OPT_MODE_IOMAP2: - if ((at & ~0xf) == 0x370) + if ((at & ~0xf) == 0x370) { at -= 0x368; - else if ((at & ~0xf) == 0x170) + } else if ((at & ~0xf) == 0x170) { at -= 0x170; + } } switch (at) { @@ -270,10 +298,11 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value) break; /* TODO: 8-bit accesses */ - if (s->cycle) + if (s->cycle) { ide_data_writew(&s->bus, 0, s->io | (value << 8)); - else + } else { s->io = value & 0xff; + } s->cycle = !s->cycle; break; case 0x9: @@ -285,8 +314,9 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value) break; case 0xe: /* Device Control */ s->ctrl = value; - if (value & CTRL_SRST) - md_reset(s); + if (value & CTRL_SRST) { + device_reset(DEVICE(s)); + } md_interrupt_update(s); break; default: @@ -501,49 +531,109 @@ static const uint8_t dscm1xxxx_cis[0x14a] = { [0x146] = CISTPL_END, /* Tuple End */ }; -static int dscm1xxxx_attach(void *opaque) +#define TYPE_DSCM1XXXX "dscm1xxxx" + +static int dscm1xxxx_attach(PCMCIACardState *card) { - MicroDriveState *md = opaque; - md->card.attr_read = md_attr_read; - md->card.attr_write = md_attr_write; - md->card.common_read = md_common_read; - md->card.common_write = md_common_write; - md->card.io_read = md_common_read; - md->card.io_write = md_common_write; - - md->attr_base = md->card.cis[0x74] | (md->card.cis[0x76] << 8); + MicroDriveState *md = MICRODRIVE(card); + PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card); + + md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8); md->io_base = 0x0; - md_reset(md); + device_reset(DEVICE(md)); md_interrupt_update(md); - md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive"; + card->slot->card_string = "DSCM-1xxxx Hitachi Microdrive"; return 0; } -static int dscm1xxxx_detach(void *opaque) +static int dscm1xxxx_detach(PCMCIACardState *card) { - MicroDriveState *md = opaque; - md_reset(md); + MicroDriveState *md = MICRODRIVE(card); + + device_reset(DEVICE(md)); return 0; } -PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv) +PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo) { - MicroDriveState *md = (MicroDriveState *) g_malloc0(sizeof(MicroDriveState)); - md->card.state = md; - md->card.attach = dscm1xxxx_attach; - md->card.detach = dscm1xxxx_detach; - md->card.cis = dscm1xxxx_cis; - md->card.cis_len = sizeof(dscm1xxxx_cis); - - ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL, - qemu_allocate_irqs(md_set_irq, md, 1)[0]); + MicroDriveState *md; + + md = MICRODRIVE(object_new(TYPE_DSCM1XXXX)); + qdev_init_nofail(DEVICE(md)); + + if (dinfo != NULL) { + ide_create_drive(&md->bus, 0, dinfo); + } md->bus.ifs[0].drive_kind = IDE_CFATA; md->bus.ifs[0].mdata_size = METADATA_SIZE; md->bus.ifs[0].mdata_storage = (uint8_t *) g_malloc0(METADATA_SIZE); - vmstate_register(NULL, -1, &vmstate_microdrive, md); + return PCMCIA_CARD(md); +} + +static void dscm1xxxx_class_init(ObjectClass *oc, void *data) +{ + PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc); + + pcc->cis = dscm1xxxx_cis; + pcc->cis_len = sizeof(dscm1xxxx_cis); + + pcc->attach = dscm1xxxx_attach; + pcc->detach = dscm1xxxx_detach; +} + +static const TypeInfo dscm1xxxx_type_info = { + .name = TYPE_DSCM1XXXX, + .parent = TYPE_MICRODRIVE, + .class_init = dscm1xxxx_class_init, +}; + +static void microdrive_realize(DeviceState *dev, Error **errp) +{ + MicroDriveState *md = MICRODRIVE(dev); + + ide_init2(&md->bus, qemu_allocate_irqs(md_set_irq, md, 1)[0]); +} + +static void microdrive_init(Object *obj) +{ + MicroDriveState *md = MICRODRIVE(obj); + + ide_bus_new(&md->bus, sizeof(md->bus), DEVICE(obj), 0, 1); +} - return &md->card; +static void microdrive_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc); + + pcc->attr_read = md_attr_read; + pcc->attr_write = md_attr_write; + pcc->common_read = md_common_read; + pcc->common_write = md_common_write; + pcc->io_read = md_common_read; + pcc->io_write = md_common_write; + + dc->realize = microdrive_realize; + dc->reset = md_reset; + dc->vmsd = &vmstate_microdrive; } + +static const TypeInfo microdrive_type_info = { + .name = TYPE_MICRODRIVE, + .parent = TYPE_PCMCIA_CARD, + .instance_size = sizeof(MicroDriveState), + .instance_init = microdrive_init, + .abstract = true, + .class_init = microdrive_class_init, +}; + +static void microdrive_register_types(void) +{ + type_register_static(µdrive_type_info); + type_register_static(&dscm1xxxx_type_info); +} + +type_init(microdrive_register_types) diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index 709b5c2984..c7658508dd 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -64,17 +64,17 @@ static const VMStateDescription vmstate_gic = { .post_load = gic_post_load, .fields = (VMStateField[]) { VMSTATE_BOOL(enabled, GICState), - VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, NCPU), + VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, GIC_NCPU), VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1, vmstate_gic_irq_state, gic_irq_state), VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ), - VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU), + VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU), VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL), - VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU), - VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU), - VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU), - VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU), - VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU), + VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU), + VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU), + VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU), + VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU), + VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU), VMSTATE_END_OF_LIST() } }; @@ -84,9 +84,9 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp) GICState *s = ARM_GIC_COMMON(dev); int num_irq = s->num_irq; - if (s->num_cpu > NCPU) { + if (s->num_cpu > GIC_NCPU) { error_setg(errp, "requested %u CPUs exceeds GIC maximum %d", - s->num_cpu, NCPU); + s->num_cpu, GIC_NCPU); return; } s->num_irq += GIC_BASE_IRQ; diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h index 14264373fe..3989fd1bd5 100644 --- a/hw/intc/gic_internal.h +++ b/hw/intc/gic_internal.h @@ -21,16 +21,9 @@ #ifndef QEMU_ARM_GIC_INTERNAL_H #define QEMU_ARM_GIC_INTERNAL_H -#include "hw/sysbus.h" +#include "hw/intc/arm_gic.h" -/* Maximum number of possible interrupts, determined by the GIC architecture */ -#define GIC_MAXIRQ 1020 -/* First 32 are private to each CPU (SGIs and PPIs). */ -#define GIC_INTERNAL 32 -/* Maximum number of possible CPU interfaces, determined by GIC architecture */ -#define NCPU 8 - -#define ALL_CPU_MASK ((unsigned)(((1 << NCPU) - 1))) +#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1))) /* The NVIC has 16 internal vectors. However these are not exposed through the normal GIC interface. */ @@ -59,48 +52,6 @@ s->priority2[(irq) - GIC_INTERNAL]) #define GIC_TARGET(irq) s->irq_target[irq] -typedef struct gic_irq_state { - /* The enable bits are only banked for per-cpu interrupts. */ - uint8_t enabled; - uint8_t pending; - uint8_t active; - uint8_t level; - bool model; /* 0 = N:N, 1 = 1:N */ - bool trigger; /* nonzero = edge triggered. */ -} gic_irq_state; - -typedef struct GICState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - qemu_irq parent_irq[NCPU]; - bool enabled; - bool cpu_enabled[NCPU]; - - gic_irq_state irq_state[GIC_MAXIRQ]; - uint8_t irq_target[GIC_MAXIRQ]; - uint8_t priority1[GIC_INTERNAL][NCPU]; - uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL]; - uint16_t last_active[GIC_MAXIRQ][NCPU]; - - uint16_t priority_mask[NCPU]; - uint16_t running_irq[NCPU]; - uint16_t running_priority[NCPU]; - uint16_t current_pending[NCPU]; - - uint32_t num_cpu; - - MemoryRegion iomem; /* Distributor */ - /* This is just so we can have an opaque pointer which identifies - * both this GIC and which CPU interface we should be accessing. - */ - struct GICState *backref[NCPU]; - MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */ - uint32_t num_irq; - uint32_t revision; -} GICState; - /* The special cases for the revision property: */ #define REV_11MPCORE 0 #define REV_NVIC 0xffffffff @@ -111,31 +62,4 @@ 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); -#define TYPE_ARM_GIC_COMMON "arm_gic_common" -#define ARM_GIC_COMMON(obj) \ - OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON) -#define ARM_GIC_COMMON_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON) -#define ARM_GIC_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON) - -typedef struct ARMGICCommonClass { - SysBusDeviceClass parent_class; - void (*pre_save)(GICState *s); - void (*post_load)(GICState *s); -} ARMGICCommonClass; - -#define TYPE_ARM_GIC "arm_gic" -#define ARM_GIC(obj) \ - OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC) -#define ARM_GIC_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC) -#define ARM_GIC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC) - -typedef struct ARMGICClass { - ARMGICCommonClass parent_class; - DeviceRealize parent_realize; -} ARMGICClass; - #endif /* !QEMU_ARM_GIC_INTERNAL_H */ diff --git a/hw/intc/realview_gic.c b/hw/intc/realview_gic.c index ce8044780a..6c812961cc 100644 --- a/hw/intc/realview_gic.c +++ b/hw/intc/realview_gic.c @@ -7,41 +7,34 @@ * This code is licensed under the GPL. */ -#include "hw/sysbus.h" - -#define TYPE_REALVIEW_GIC "realview_gic" -#define REALVIEW_GIC(obj) \ - OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC) - -typedef struct { - SysBusDevice parent_obj; - - DeviceState *gic; - MemoryRegion container; -} RealViewGICState; +#include "hw/intc/realview_gic.h" static void realview_gic_set_irq(void *opaque, int irq, int level) { RealViewGICState *s = (RealViewGICState *)opaque; - qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); + + qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level); } -static int realview_gic_init(SysBusDevice *sbd) +static void realview_gic_realize(DeviceState *dev, Error **errp) { - DeviceState *dev = DEVICE(sbd); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); RealViewGICState *s = REALVIEW_GIC(dev); SysBusDevice *busdev; + Error *err = NULL; /* The GICs on the RealView boards have a fixed nonconfigurable * number of interrupt lines, so we don't need to expose this as * a qdev property. */ int numirq = 96; - s->gic = qdev_create(NULL, "arm_gic"); - qdev_prop_set_uint32(s->gic, "num-cpu", 1); - qdev_prop_set_uint32(s->gic, "num-irq", numirq); - qdev_init_nofail(s->gic); - busdev = SYS_BUS_DEVICE(s->gic); + qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", numirq); + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + busdev = SYS_BUS_DEVICE(&s->gic); /* Pass through outbound IRQ lines from the GIC */ sysbus_pass_irq(sbd, busdev); @@ -49,27 +42,40 @@ static int realview_gic_init(SysBusDevice *sbd) /* Pass through inbound GPIO lines to the GIC */ qdev_init_gpio_in(dev, realview_gic_set_irq, numirq - 32); - memory_region_init(&s->container, OBJECT(s), - "realview-gic-container", 0x2000); memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(busdev, 1)); memory_region_add_subregion(&s->container, 0x1000, sysbus_mmio_get_region(busdev, 0)); +} + +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); - return 0; + + 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); } -static void realview_gic_class_init(ObjectClass *klass, void *data) +static void realview_gic_class_init(ObjectClass *oc, void *data) { - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(oc); - sdc->init = realview_gic_init; + dc->realize = realview_gic_realize; } static const TypeInfo realview_gic_info = { .name = TYPE_REALVIEW_GIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(RealViewGICState), + .instance_init = realview_gic_init, .class_init = realview_gic_class_init, }; diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c index f1744ec07e..15053c4c37 100644 --- a/hw/lm32/milkymist.c +++ b/hw/lm32/milkymist.c @@ -21,6 +21,7 @@ #include "hw/hw.h" #include "hw/block/flash.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "hw/devices.h" #include "hw/boards.h" #include "hw/loader.h" @@ -143,7 +144,7 @@ milkymist_init(QEMUMachineInitArgs *args) reset_info->bootstrap_pc = BIOS_OFFSET; /* if no kernel is given no valid bios rom is a fatal error */ - if (!kernel_filename && !dinfo && !bios_filename) { + if (!kernel_filename && !dinfo && !bios_filename && !qtest_enabled()) { fprintf(stderr, "qemu: could not load Milkymist One bios '%s'\n", bios_name); exit(1); diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c index a8eee44e62..24f2068559 100644 --- a/hw/m68k/an5206.c +++ b/hw/m68k/an5206.c @@ -12,6 +12,7 @@ #include "hw/loader.h" #include "elf.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" #define KERNEL_LOAD_ADDR 0x10000 #define AN5206_MBAR_ADDR 0x10000000 @@ -62,6 +63,9 @@ static void an5206_init(QEMUMachineInitArgs *args) /* Load kernel. */ if (!kernel_filename) { + if (qtest_enabled()) { + return; + } fprintf(stderr, "Kernel image must be specified\n"); exit(1); } diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index fb96fe8548..6e30c0b393 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -10,6 +10,7 @@ #include "qemu/timer.h" #include "hw/ptimer.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "net/net.h" #include "hw/boards.h" #include "hw/loader.h" @@ -267,6 +268,9 @@ static void mcf5208evb_init(QEMUMachineInitArgs *args) /* Load kernel. */ if (!kernel_filename) { + if (qtest_enabled()) { + return; + } fprintf(stderr, "Kernel image must be specified\n"); exit(1); } diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c index 242bab9779..239aa6ac8c 100644 --- a/hw/mips/mips_mipssim.c +++ b/hw/mips/mips_mipssim.c @@ -38,6 +38,7 @@ #include "hw/sysbus.h" #include "exec/address-spaces.h" #include "qemu/error-report.h" +#include "sysemu/qtest.h" static struct _loaderparams { int ram_size; @@ -190,7 +191,8 @@ mips_mipssim_init(QEMUMachineInitArgs *args) } else { bios_size = -1; } - if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { + if ((bios_size < 0 || bios_size > BIOS_SIZE) && + !kernel_filename && !qtest_enabled()) { /* Bail out if we have neither a kernel image nor boot vector code. */ error_report("Could not load MIPS bios '%s', and no " "-kernel argument was specified", filename); diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index cca5c058cc..f6743659f7 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -11,6 +11,8 @@ obj-$(CONFIG_VMPORT) += vmport.o # ARM devices common-obj-$(CONFIG_PL310) += arm_l2x0.o common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o +common-obj-$(CONFIG_A9SCU) += a9scu.o +common-obj-$(CONFIG_ARM11SCU) += arm11scu.o # PKUnity SoC devices common-obj-$(CONFIG_PUV3) += puv3_pm.o @@ -23,7 +25,6 @@ obj-$(CONFIG_LINUX) += vfio.o endif obj-$(CONFIG_REALVIEW) += arm_sysctl.o -obj-$(CONFIG_A9SCU) += a9scu.o obj-$(CONFIG_NSERIES) += cbus.o obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o @@ -37,7 +38,6 @@ obj-$(CONFIG_OMAP) += omap_gpmc.o obj-$(CONFIG_OMAP) += omap_l4.o obj-$(CONFIG_OMAP) += omap_sdrc.o obj-$(CONFIG_OMAP) += omap_tap.o -obj-$(CONFIG_PXA2XX) += pxa2xx_pcmcia.o obj-$(CONFIG_SLAVIO) += slavio_misc.o obj-$(CONFIG_ZYNQ) += zynq_slcr.o diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c index 601b5733f2..4434945908 100644 --- a/hw/misc/a9scu.c +++ b/hw/misc/a9scu.c @@ -8,20 +8,7 @@ * This code is licensed under the GPL. */ -#include "hw/sysbus.h" - -/* A9MP private memory region. */ - -typedef struct A9SCUState { - SysBusDevice busdev; - MemoryRegion iomem; - uint32_t control; - uint32_t status; - uint32_t num_cpu; -} A9SCUState; - -#define TYPE_A9_SCU "a9-scu" -#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU) +#include "hw/misc/a9scu.h" static uint64_t a9_scu_read(void *opaque, hwaddr offset, unsigned size) @@ -114,12 +101,12 @@ static void a9_scu_reset(DeviceState *dev) s->control = 0; } -static void a9_scu_realize(DeviceState *dev, Error ** errp) +static void a9_scu_init(Object *obj) { - A9SCUState *s = A9_SCU(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + A9SCUState *s = A9_SCU(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - memory_region_init_io(&s->iomem, OBJECT(dev), &a9_scu_ops, s, + memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s, "a9-scu", 0x100); sysbus_init_mmio(sbd, &s->iomem); } @@ -144,7 +131,6 @@ static void a9_scu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - dc->realize = a9_scu_realize; dc->props = a9_scu_properties; dc->vmsd = &vmstate_a9_scu; dc->reset = a9_scu_reset; @@ -154,6 +140,7 @@ static const TypeInfo a9_scu_info = { .name = TYPE_A9_SCU, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(A9SCUState), + .instance_init = a9_scu_init, .class_init = a9_scu_class_init, }; diff --git a/hw/misc/arm11scu.c b/hw/misc/arm11scu.c new file mode 100644 index 0000000000..a791675443 --- /dev/null +++ b/hw/misc/arm11scu.c @@ -0,0 +1,100 @@ +/* + * ARM11MPCore Snoop Control Unit (SCU) emulation + * + * Copyright (c) 2006-2007 CodeSourcery. + * Copyright (c) 2013 SUSE LINUX Products GmbH + * Written by Paul Brook and Andreas Färber + * + * This code is licensed under the GPL. + */ + +#include "hw/misc/arm11scu.h" + +static uint64_t mpcore_scu_read(void *opaque, hwaddr offset, + unsigned size) +{ + ARM11SCUState *s = (ARM11SCUState *)opaque; + int id; + /* SCU */ + switch (offset) { + case 0x00: /* Control. */ + return s->control; + case 0x04: /* Configuration. */ + id = ((1 << s->num_cpu) - 1) << 4; + return id | (s->num_cpu - 1); + case 0x08: /* CPU status. */ + return 0; + case 0x0c: /* Invalidate all. */ + return 0; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "mpcore_priv_read: Bad offset %x\n", (int)offset); + return 0; + } +} + +static void mpcore_scu_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + ARM11SCUState *s = (ARM11SCUState *)opaque; + /* SCU */ + switch (offset) { + case 0: /* Control register. */ + s->control = value & 1; + break; + case 0x0c: /* Invalidate all. */ + /* This is a no-op as cache is not emulated. */ + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "mpcore_priv_read: Bad offset %x\n", (int)offset); + } +} + +static const MemoryRegionOps mpcore_scu_ops = { + .read = mpcore_scu_read, + .write = mpcore_scu_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void arm11_scu_realize(DeviceState *dev, Error **errp) +{ +} + +static void arm11_scu_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + ARM11SCUState *s = ARM11_SCU(obj); + + memory_region_init_io(&s->iomem, OBJECT(s), + &mpcore_scu_ops, s, "mpcore-scu", 0x100); + sysbus_init_mmio(sbd, &s->iomem); +} + +static Property arm11_scu_properties[] = { + DEFINE_PROP_UINT32("num-cpu", ARM11SCUState, num_cpu, 1), + DEFINE_PROP_END_OF_LIST() +}; + +static void arm11_scu_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = arm11_scu_realize; + dc->props = arm11_scu_properties; +} + +static const TypeInfo arm11_scu_type_info = { + .name = TYPE_ARM11_SCU, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ARM11SCUState), + .instance_init = arm11_scu_init, + .class_init = arm11_scu_class_init, +}; + +static void arm11_scu_register_types(void) +{ + type_register_static(&arm11_scu_type_info); +} + +type_init(arm11_scu_register_types) diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c index 619fe473e8..8dbc3c1cab 100644 --- a/hw/pci/pci-hotplug-old.c +++ b/hw/pci/pci-hotplug-old.c @@ -248,7 +248,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, } dev = pci_create(bus, devfn, "virtio-blk-pci"); if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { - qdev_free(&dev->qdev); + object_unparent(OBJECT(dev)); dev = NULL; break; } diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index e6b22b860f..290ababb8b 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -391,7 +391,7 @@ void pci_bridge_exitfn(PCIDevice *pci_dev) pci_bridge_region_cleanup(s, s->windows); memory_region_destroy(&s->address_space_mem); memory_region_destroy(&s->address_space_io); - /* qbus_free() is called automatically by qdev_free() */ + /* qbus_free() is called automatically during device deletion */ } /* diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 268a696646..ca60cf2177 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -251,7 +251,7 @@ static int pcie_cap_slot_hotplug(DeviceState *qdev, PCI_EXP_SLTSTA_PDS); pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); } else { - qdev_free(&pci_dev->qdev); + object_unparent(OBJECT(pci_dev)); pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index 0bbd36e272..576244b9f6 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -254,7 +254,7 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot) ++devfn) { PCIDevice *affected_dev = shpc->sec_bus->devices[devfn]; if (affected_dev) { - qdev_free(&affected_dev->qdev); + object_unparent(OBJECT(affected_dev)); } } } diff --git a/hw/pcmcia/Makefile.objs b/hw/pcmcia/Makefile.objs new file mode 100644 index 0000000000..4eac060c93 --- /dev/null +++ b/hw/pcmcia/Makefile.objs @@ -0,0 +1,2 @@ +common-obj-y += pcmcia.o +obj-$(CONFIG_PXA2XX) += pxa2xx.o diff --git a/hw/pcmcia/pcmcia.c b/hw/pcmcia/pcmcia.c new file mode 100644 index 0000000000..78efe5a67a --- /dev/null +++ b/hw/pcmcia/pcmcia.c @@ -0,0 +1,24 @@ +/* + * PCMCIA emulation + * + * Copyright 2013 SUSE LINUX Products GmbH + */ + +#include "qemu-common.h" +#include "hw/hw.h" +#include "hw/pcmcia.h" + +static const TypeInfo pcmcia_card_type_info = { + .name = TYPE_PCMCIA_CARD, + .parent = TYPE_DEVICE, + .instance_size = sizeof(PCMCIACardState), + .abstract = true, + .class_size = sizeof(PCMCIACardClass), +}; + +static void pcmcia_register_types(void) +{ + type_register_static(&pcmcia_card_type_info); +} + +type_init(pcmcia_register_types) diff --git a/hw/misc/pxa2xx_pcmcia.c b/hw/pcmcia/pxa2xx.c index ef71a2af74..8f17596cc3 100644 --- a/hw/misc/pxa2xx_pcmcia.c +++ b/hw/pcmcia/pxa2xx.c @@ -11,28 +11,38 @@ */ #include "hw/hw.h" +#include "hw/sysbus.h" #include "hw/pcmcia.h" #include "hw/arm/pxa.h" +#define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia" +#define PXA2XX_PCMCIA(obj) \ + OBJECT_CHECK(PXA2xxPCMCIAState, obj, TYPE_PXA2XX_PCMCIA) struct PXA2xxPCMCIAState { + SysBusDevice parent_obj; + PCMCIASocket slot; - PCMCIACardState *card; + MemoryRegion container_mem; MemoryRegion common_iomem; MemoryRegion attr_iomem; MemoryRegion iomem; qemu_irq irq; qemu_irq cd_irq; + + PCMCIACardState *card; }; static uint64_t pxa2xx_pcmcia_common_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - return s->card->common_read(s->card->state, offset); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + return pcc->common_read(s->card, offset); } return 0; @@ -42,9 +52,11 @@ static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - s->card->common_write(s->card->state, offset, value); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->common_write(s->card, offset, value); } } @@ -52,9 +64,11 @@ static uint64_t pxa2xx_pcmcia_attr_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - return s->card->attr_read(s->card->state, offset); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + return pcc->attr_read(s->card, offset); } return 0; @@ -64,9 +78,11 @@ static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - s->card->attr_write(s->card->state, offset, value); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->attr_write(s->card, offset, value); } } @@ -74,9 +90,11 @@ static uint64_t pxa2xx_pcmcia_io_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - return s->card->io_read(s->card->state, offset); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + return pcc->io_read(s->card, offset); } return 0; @@ -86,9 +104,11 @@ static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - s->card->io_write(s->card->state, offset, value); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->io_write(s->card, offset, value); } } @@ -122,15 +142,43 @@ static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level) PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, hwaddr base) { + DeviceState *dev; PXA2xxPCMCIAState *s; - s = (PXA2xxPCMCIAState *) - g_malloc0(sizeof(PXA2xxPCMCIAState)); + dev = qdev_create(NULL, TYPE_PXA2XX_PCMCIA); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + s = PXA2XX_PCMCIA(dev); + + if (base == 0x30000000) { + s->slot.slot_string = "PXA PC Card Socket 1"; + } else { + s->slot.slot_string = "PXA PC Card Socket 0"; + } + + qdev_init_nofail(dev); + + return s; +} + +static void pxa2xx_pcmcia_realize(DeviceState *dev, Error **errp) +{ + PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(dev); + + pcmcia_socket_register(&s->slot); +} + +static void pxa2xx_pcmcia_initfn(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(obj); + + memory_region_init(&s->container_mem, obj, "container", 0x10000000); + sysbus_init_mmio(sbd, &s->container_mem); /* Socket I/O Memory Space */ memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s, "pxa2xx-pcmcia-io", 0x04000000); - memory_region_add_subregion(sysmem, base | 0x00000000, + memory_region_add_subregion(&s->container_mem, 0x00000000, &s->iomem); /* Then next 64 MB is reserved */ @@ -138,62 +186,68 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, /* Socket Attribute Memory Space */ memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s, "pxa2xx-pcmcia-attribute", 0x04000000); - memory_region_add_subregion(sysmem, base | 0x08000000, + memory_region_add_subregion(&s->container_mem, 0x08000000, &s->attr_iomem); /* Socket Common Memory Space */ memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s, "pxa2xx-pcmcia-common", 0x04000000); - memory_region_add_subregion(sysmem, base | 0x0c000000, + memory_region_add_subregion(&s->container_mem, 0x0c000000, &s->common_iomem); - if (base == 0x30000000) - s->slot.slot_string = "PXA PC Card Socket 1"; - else - s->slot.slot_string = "PXA PC Card Socket 0"; s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0]; - pcmcia_socket_register(&s->slot); - return s; + object_property_add_link(obj, "card", TYPE_PCMCIA_CARD, + (Object **)&s->card, NULL); } /* Insert a new card into a slot */ int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; - if (s->slot.attached) + PCMCIACardClass *pcc; + + if (s->slot.attached) { return -EEXIST; + } if (s->cd_irq) { qemu_irq_raise(s->cd_irq); } s->card = card; + pcc = PCMCIA_CARD_GET_CLASS(s->card); - s->slot.attached = 1; + s->slot.attached = true; s->card->slot = &s->slot; - s->card->attach(s->card->state); + pcc->attach(s->card); return 0; } /* Eject card from the slot */ -int pxa2xx_pcmcia_dettach(void *opaque) +int pxa2xx_pcmcia_detach(void *opaque) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; - if (!s->slot.attached) + PCMCIACardClass *pcc; + + if (!s->slot.attached) { return -ENOENT; + } - s->card->detach(s->card->state); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->detach(s->card); s->card->slot = NULL; s->card = NULL; - s->slot.attached = 0; + s->slot.attached = false; - if (s->irq) + if (s->irq) { qemu_irq_lower(s->irq); - if (s->cd_irq) + } + if (s->cd_irq) { qemu_irq_lower(s->cd_irq); + } return 0; } @@ -205,3 +259,25 @@ void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq) s->irq = irq; s->cd_irq = cd_irq; } + +static void pxa2xx_pcmcia_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = pxa2xx_pcmcia_realize; +} + +static const TypeInfo pxa2xx_pcmcia_type_info = { + .name = TYPE_PXA2XX_PCMCIA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(PXA2xxPCMCIAState), + .instance_init = pxa2xx_pcmcia_initfn, + .class_init = pxa2xx_pcmcia_class_init, +}; + +static void pxa2xx_pcmcia_register_types(void) +{ + type_register_static(&pxa2xx_pcmcia_type_info); +} + +type_init(pxa2xx_pcmcia_register_types) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index cd67db5e5b..f93a81c7cd 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1239,7 +1239,7 @@ static int virtio_ccw_busdev_unplug(DeviceState *dev) css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0); - qdev_free(dev); + object_unparent(OBJECT(dev)); return 0; } diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 24ec52f8f9..ea916d1466 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -178,7 +178,7 @@ static int scsi_qdev_init(DeviceState *qdev) d = scsi_device_find(bus, dev->channel, dev->id, dev->lun); assert(d); if (d->lun == dev->lun && dev != d) { - qdev_free(&d->qdev); + object_unparent(OBJECT(d)); } } @@ -231,13 +231,13 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, } if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) { error_setg(errp, "Setting drive property failed"); - qdev_free(dev); + object_unparent(OBJECT(dev)); return NULL; } object_property_set_bool(OBJECT(dev), true, "realized", &err); if (err != NULL) { error_propagate(errp, err); - qdev_free(dev); + object_unparent(OBJECT(dev)); return NULL; } return SCSI_DEVICE(dev); diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c index 1ff37f54a0..904a966700 100644 --- a/hw/sh4/shix.c +++ b/hw/sh4/shix.c @@ -30,9 +30,11 @@ #include "hw/hw.h" #include "hw/sh4/sh.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "hw/boards.h" #include "hw/loader.h" #include "exec/address-spaces.h" +#include "qemu/error-report.h" #define BIOS_FILENAME "shix_bios.bin" #define BIOS_ADDRESS 0xA0000000 @@ -50,7 +52,6 @@ static void shix_init(QEMUMachineInitArgs *args) if (!cpu_model) cpu_model = "any"; - printf("Initializing CPU\n"); cpu = cpu_sh4_init(cpu_model); if (cpu == NULL) { fprintf(stderr, "Unable to find CPU definition\n"); @@ -58,16 +59,13 @@ static void shix_init(QEMUMachineInitArgs *args) } /* Allocate memory space */ - printf("Allocating ROM\n"); memory_region_init_ram(rom, NULL, "shix.rom", 0x4000); vmstate_register_ram_global(rom); memory_region_set_readonly(rom, true); memory_region_add_subregion(sysmem, 0x00000000, rom); - printf("Allocating SDRAM 1\n"); memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000); vmstate_register_ram_global(&sdram[0]); memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]); - printf("Allocating SDRAM 2\n"); memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000); vmstate_register_ram_global(&sdram[1]); memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]); @@ -75,20 +73,16 @@ static void shix_init(QEMUMachineInitArgs *args) /* Load BIOS in 0 (and access it through P2, 0xA0000000) */ if (bios_name == NULL) bios_name = BIOS_FILENAME; - printf("%s: load BIOS '%s'\n", __func__, bios_name); ret = load_image_targphys(bios_name, 0, 0x4000); - if (ret < 0) { /* Check bios size */ - fprintf(stderr, "ret=%d\n", ret); - fprintf(stderr, "qemu: could not load SHIX bios '%s'\n", - bios_name); - exit(1); + if (ret < 0 && !qtest_enabled()) { + error_report("Could not load SHIX bios '%s'", bios_name); + exit(1); } /* Register peripherals */ s = sh7750_init(cpu, sysmem); /* XXXXX Check success */ tc58128_init(s, "shix_linux_nand.bin", NULL); - fprintf(stderr, "initialization terminated\n"); } static QEMUMachine shix_machine = { diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 390f3e4bda..c583c3d0c5 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -26,6 +26,7 @@ #include "hw/ptimer.h" #include "sysemu/char.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "hw/boards.h" #include "hw/loader.h" #include "elf.h" @@ -178,7 +179,7 @@ static void leon3_generic_hw_init(QEMUMachineInitArgs *args) fprintf(stderr, "qemu: could not load prom '%s'\n", filename); exit(1); } - } else if (kernel_filename == NULL) { + } else if (kernel_filename == NULL && !qtest_enabled()) { fprintf(stderr, "Can't read bios image %s\n", filename); exit(1); } diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c index 8020c9f4b5..d9f9494f26 100644 --- a/hw/timer/arm_mptimer.c +++ b/hw/timer/arm_mptimer.c @@ -19,7 +19,7 @@ * with this program; if not, see <http://www.gnu.org/licenses/>. */ -#include "hw/sysbus.h" +#include "hw/timer/arm_mptimer.h" #include "qemu/timer.h" #include "qom/cpu.h" @@ -27,34 +27,6 @@ * which is used in both the ARM11MPCore and Cortex-A9MP. */ -#define MAX_CPUS 4 - -/* State of a single timer or watchdog block */ -typedef struct { - uint32_t count; - uint32_t load; - uint32_t control; - uint32_t status; - int64_t tick; - QEMUTimer *timer; - qemu_irq irq; - MemoryRegion iomem; -} TimerBlock; - -#define TYPE_ARM_MPTIMER "arm_mptimer" -#define ARM_MPTIMER(obj) \ - OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER) - -typedef struct { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - uint32_t num_cpu; - TimerBlock timerblock[MAX_CPUS]; - MemoryRegion iomem; -} ARMMPTimerState; - static inline int get_current_cpu(ARMMPTimerState *s) { if (current_cpu->cpu_index >= s->num_cpu) { @@ -225,13 +197,24 @@ static void arm_mptimer_reset(DeviceState *dev) } } -static int arm_mptimer_init(SysBusDevice *dev) +static void arm_mptimer_init(Object *obj) +{ + ARMMPTimerState *s = ARM_MPTIMER(obj); + + memory_region_init_io(&s->iomem, obj, &arm_thistimer_ops, s, + "arm_mptimer_timer", 0x20); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); +} + +static void arm_mptimer_realize(DeviceState *dev, Error **errp) { + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); ARMMPTimerState *s = ARM_MPTIMER(dev); int i; - if (s->num_cpu < 1 || s->num_cpu > MAX_CPUS) { - hw_error("%s: num-cpu must be between 1 and %d\n", __func__, MAX_CPUS); + if (s->num_cpu < 1 || s->num_cpu > ARM_MPTIMER_MAX_CPUS) { + hw_error("%s: num-cpu must be between 1 and %d\n", + __func__, ARM_MPTIMER_MAX_CPUS); } /* We implement one timer block per CPU, and expose multiple MMIO regions: * * region 0 is "timer for this core" @@ -243,19 +226,14 @@ static int arm_mptimer_init(SysBusDevice *dev) * * timer for core 1 * and so on. */ - memory_region_init_io(&s->iomem, OBJECT(s), &arm_thistimer_ops, s, - "arm_mptimer_timer", 0x20); - sysbus_init_mmio(dev, &s->iomem); for (i = 0; i < s->num_cpu; i++) { TimerBlock *tb = &s->timerblock[i]; tb->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, timerblock_tick, tb); - sysbus_init_irq(dev, &tb->irq); + sysbus_init_irq(sbd, &tb->irq); memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb, "arm_mptimer_timerblock", 0x20); - sysbus_init_mmio(dev, &tb->iomem); + sysbus_init_mmio(sbd, &tb->iomem); } - - return 0; } static const VMStateDescription vmstate_timerblock = { @@ -292,9 +270,8 @@ static Property arm_mptimer_properties[] = { static void arm_mptimer_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); - sbc->init = arm_mptimer_init; + dc->realize = arm_mptimer_realize; dc->vmsd = &vmstate_arm_mptimer; dc->reset = arm_mptimer_reset; dc->no_user = 1; @@ -305,6 +282,7 @@ static const TypeInfo arm_mptimer_info = { .name = TYPE_ARM_MPTIMER, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ARMMPTimerState), + .instance_init = arm_mptimer_init, .class_init = arm_mptimer_class_init, }; diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c index a9000617b4..e05cbc131e 100644 --- a/hw/unicore32/puv3.c +++ b/hw/unicore32/puv3.c @@ -17,6 +17,7 @@ #include "hw/boards.h" #include "hw/loader.h" #include "hw/i386/pc.h" +#include "sysemu/qtest.h" #undef DEBUG_PUV3 #include "hw/unicore32/puv3.h" @@ -84,6 +85,9 @@ static void puv3_load_kernel(const char *kernel_filename) { int size; + if (kernel_filename == NULL && qtest_enabled()) { + return; + } assert(kernel_filename != NULL); /* only zImage format supported */ diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 72d5b92225..ca329bef29 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -356,8 +356,9 @@ void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr) void usb_unregister_port(USBBus *bus, USBPort *port) { - if (port->dev) - qdev_free(&port->dev->qdev); + if (port->dev) { + object_unparent(OBJECT(port->dev)); + } QTAILQ_REMOVE(&bus->free, port, next); bus->nfree--; } @@ -505,7 +506,7 @@ int usb_device_delete_addr(int busnr, int addr) return -1; dev = port->dev; - qdev_free(&dev->qdev); + object_unparent(OBJECT(dev)); return 0; } diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 1d81ac2a6b..c434c5680f 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -703,7 +703,7 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename) return NULL; } if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { - qdev_free(&dev->qdev); + object_unparent(OBJECT(dev)); return NULL; } if (qdev_init(&dev->qdev) < 0) diff --git a/hw/usb/host-legacy.c b/hw/usb/host-legacy.c index 3a5f705721..3cc9c4282c 100644 --- a/hw/usb/host-legacy.c +++ b/hw/usb/host-legacy.c @@ -132,7 +132,7 @@ USBDevice *usb_host_device_open(USBBus *bus, const char *devname) return dev; fail: - qdev_free(&dev->qdev); + object_unparent(OBJECT(dev)); return NULL; } diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c index 6849a018a9..e6b103c991 100644 --- a/hw/virtio/virtio-bus.c +++ b/hw/virtio/virtio-bus.c @@ -67,7 +67,6 @@ void virtio_bus_reset(VirtioBusState *bus) /* Destroy the VirtIODevice */ void virtio_bus_destroy_device(VirtioBusState *bus) { - DeviceState *qdev; BusState *qbus = BUS(bus); VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus); DPRINTF("%s: remove device.\n", qbus->name); @@ -76,8 +75,7 @@ void virtio_bus_destroy_device(VirtioBusState *bus) if (klass->device_unplug != NULL) { klass->device_unplug(qbus->parent); } - qdev = DEVICE(bus->vdev); - qdev_free(qdev); + object_unparent(OBJECT(bus->vdev)); bus->vdev = NULL; } } diff --git a/hw/xen/xen_platform.c b/hw/xen/xen_platform.c index 79bf0b33d3..70875e4122 100644 --- a/hw/xen/xen_platform.c +++ b/hw/xen/xen_platform.c @@ -95,7 +95,7 @@ static void unplug_nic(PCIBus *b, PCIDevice *d, void *o) if (pci_get_word(d->config + PCI_CLASS_DEVICE) == PCI_CLASS_NETWORK_ETHERNET && strcmp(d->name, "xen-pci-passthrough") != 0) { - qdev_free(DEVICE(d)); + object_unparent(OBJECT(d)); } } |