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)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iQIcBAABAgAGBQJSeSW3AAoJEPou0S0+fgE/CXAQALxw6JvDBht/S/QaLG9ZrjJQ
 THsG9sZNSXNea7B4+z5ZJKKWce14vz9hyKqliXykgDqZg7KmPG0ywQT94AcPL0KL
 ylbeJbNmRr7EbSquV1hxowVNLt9PBWmmhVRpEOw3PB14hSaDTNe4lqq50PE8wJAq
 4x1V4xsH5psC2FjHWAfKyaMYZX7XjZ4r00Ir0lbHAa4sIwCskrngoaGMShrxh6RK
 KA9EoWFACkwEW2fX6lpLYbm35I1cIG1VQIG8cebpMlqrLpFiFceyGfB6S+RlhlXc
 z+iyQTsO0FYdi7tUpjnsRKmR3cxL3Ea1egP7nzziQkj7K4kVOtWz+ClOwuxw8ZjM
 Oh5GVz8XLpfegm66YZQItZ+LuZAB2PBTesUFHkf7nC7UTJwzTX6erTYonbQi3xHy
 /W+AuyNRFQ81HRoHHps/Jb8+6OYEML9079y8PtK1ZmTufZtSCIxvLqZ9ipQZwA7P
 a9je2YOoaKEQZ0glir26oOUBinEQMXbPk+yUSDS092dqRs6tN0xRAZtdHrS9ouOt
 pt8xkXI+D0m+1aGE7ISPOUqdjT18LnEOLC7/Uq5XCWLDBGOEn6S1oPWGnYAOYqLf
 ZsF3pWZUCzvbgxDTNvZlxv0Xx7VKxhO5K5ZFXouaCBlFn7B1BfgK7oD+k7t5HFKc
 lZhC2kh5vUQPFgFl0T6W
 =YzDu
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Anthony Liguori 2013-11-05 10:33:32 -08:00
commit a30b377e0a
66 changed files with 1681 additions and 746 deletions

View file

@ -61,6 +61,7 @@ CONFIG_BITBANG_I2C=y
CONFIG_FRAMEBUFFER=y CONFIG_FRAMEBUFFER=y
CONFIG_XILINX_SPIPS=y CONFIG_XILINX_SPIPS=y
CONFIG_ARM11SCU=y
CONFIG_A9SCU=y CONFIG_A9SCU=y
CONFIG_MARVELL_88W8618=y CONFIG_MARVELL_88W8618=y
CONFIG_OMAP=y CONFIG_OMAP=y

View file

@ -18,6 +18,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += net/
devices-dirs-$(CONFIG_SOFTMMU) += nvram/ devices-dirs-$(CONFIG_SOFTMMU) += nvram/
devices-dirs-$(CONFIG_SOFTMMU) += pci/ devices-dirs-$(CONFIG_SOFTMMU) += pci/
devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/ devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/
devices-dirs-$(CONFIG_SOFTMMU) += pcmcia/
devices-dirs-$(CONFIG_SOFTMMU) += scsi/ devices-dirs-$(CONFIG_SOFTMMU) += scsi/
devices-dirs-$(CONFIG_SOFTMMU) += sd/ devices-dirs-$(CONFIG_SOFTMMU) += sd/
devices-dirs-$(CONFIG_SOFTMMU) += ssi/ devices-dirs-$(CONFIG_SOFTMMU) += ssi/

View file

@ -328,7 +328,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
if (pc->no_hotplug) { if (pc->no_hotplug) {
slot_free = false; slot_free = false;
} else { } else {
qdev_free(qdev); object_unparent(OBJECT(qdev));
} }
} }
} }

View file

@ -11,6 +11,8 @@
#include "hw/arm/arm.h" #include "hw/arm/arm.h"
#include "hw/loader.h" #include "hw/loader.h"
#include "elf.h" #include "elf.h"
#include "sysemu/qtest.h"
#include "qemu/error-report.h"
/* Bitbanded IO. Each word corresponds to a single bit. */ /* Bitbanded IO. Each word corresponds to a single bit. */
@ -232,11 +234,12 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
big_endian = 0; big_endian = 0;
#endif #endif
if (!kernel_filename) { if (!kernel_filename && !qtest_enabled()) {
fprintf(stderr, "Guest image must be specified (using -kernel)\n"); fprintf(stderr, "Guest image must be specified (using -kernel)\n");
exit(1); exit(1);
} }
if (kernel_filename) {
image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr, image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
NULL, big_endian, ELF_MACHINE, 1); NULL, big_endian, ELF_MACHINE, 1);
if (image_size < 0) { if (image_size < 0) {
@ -244,10 +247,10 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
lowaddr = 0; lowaddr = 0;
} }
if (image_size < 0) { if (image_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n", error_report("Could not load kernel '%s'", kernel_filename);
kernel_filename);
exit(1); exit(1);
} }
}
/* Hack to map an additional page of ram at the top of the address /* Hack to map an additional page of ram at the top of the address
space. This stops qemu complaining about executing code outside RAM space. This stops qemu complaining about executing code outside RAM

View file

@ -22,6 +22,7 @@
*/ */
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "net/net.h" #include "net/net.h"
#include "hw/arm/arm.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, static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
Exynos4BoardType board_type) 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" fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
" value.\n", " value.\n",
exynos4_machines[board_type].name, exynos4_machines[board_type].name,

View file

@ -42,6 +42,7 @@
#include "hw/boards.h" #include "hw/boards.h"
#include "sysemu/blockdev.h" #include "sysemu/blockdev.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "sysemu/qtest.h"
static const int sector_len = 128 * 1024; 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); cpu = pxa255_init(address_space_mem, connex_ram);
dinfo = drive_get(IF_PFLASH, 0, 0); dinfo = drive_get(IF_PFLASH, 0, 0);
if (!dinfo) { if (!dinfo && !qtest_enabled()) {
fprintf(stderr, "A flash image must be given with the " fprintf(stderr, "A flash image must be given with the "
"'pflash' parameter\n"); "'pflash' parameter\n");
exit(1); exit(1);
@ -70,7 +71,8 @@ static void connex_init(QEMUMachineInitArgs *args)
be = 0; be = 0;
#endif #endif
if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom, 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)) { 2, 0, 0, 0, 0, be)) {
fprintf(stderr, "qemu: Error registering flash memory.\n"); fprintf(stderr, "qemu: Error registering flash memory.\n");
exit(1); exit(1);
@ -95,7 +97,7 @@ static void verdex_init(QEMUMachineInitArgs *args)
cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0"); cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0");
dinfo = drive_get(IF_PFLASH, 0, 0); dinfo = drive_get(IF_PFLASH, 0, 0);
if (!dinfo) { if (!dinfo && !qtest_enabled()) {
fprintf(stderr, "A flash image must be given with the " fprintf(stderr, "A flash image must be given with the "
"'pflash' parameter\n"); "'pflash' parameter\n");
exit(1); exit(1);
@ -107,7 +109,8 @@ static void verdex_init(QEMUMachineInitArgs *args)
be = 0; be = 0;
#endif #endif
if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom, 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)) { 2, 0, 0, 0, 0, be)) {
fprintf(stderr, "qemu: Error registering flash memory.\n"); fprintf(stderr, "qemu: Error registering flash memory.\n");
exit(1); exit(1);

View file

@ -21,6 +21,7 @@
#include "sysemu/blockdev.h" #include "sysemu/blockdev.h"
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "sysemu/qtest.h"
/* Device addresses */ /* Device addresses */
#define MST_FPGA_PHYS 0x08000000 #define MST_FPGA_PHYS 0x08000000
@ -127,6 +128,9 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
for (i = 0; i < 2; i ++) { for (i = 0; i < 2; i ++) {
dinfo = drive_get(IF_PFLASH, 0, i); dinfo = drive_get(IF_PFLASH, 0, i);
if (!dinfo) { if (!dinfo) {
if (qtest_enabled()) {
break;
}
fprintf(stderr, "Two flash images must be given with the " fprintf(stderr, "Two flash images must be given with the "
"'pflash' parameter\n"); "'pflash' parameter\n");
exit(1); exit(1);
@ -147,7 +151,6 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
qdev_get_gpio_in(mpu->gpio, 0)); qdev_get_gpio_in(mpu->gpio, 0));
/* setup keypad */ /* setup keypad */
printf("map addr %p\n", &map);
pxa27x_register_keypad(mpu->kp, map, 0xe0); pxa27x_register_keypad(mpu->kp, map, 0xe0);
/* MMC/SD host */ /* MMC/SD host */

View file

@ -32,6 +32,7 @@
#include "hw/arm/arm.h" #include "hw/arm/arm.h"
#include "hw/block/flash.h" #include "hw/block/flash.h"
#include "sysemu/blockdev.h" #include "sysemu/blockdev.h"
#include "sysemu/qtest.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
/*****************************************************************************/ /*****************************************************************************/
@ -188,7 +189,7 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version)
OMAP_CS1_BASE, &cs[1]); 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"); fprintf(stderr, "Kernel or Flash image must be specified\n");
exit(1); exit(1);
} }

View file

@ -19,6 +19,7 @@
#include "hw/hw.h" #include "hw/hw.h"
#include "audio/audio.h" #include "audio/audio.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "ui/console.h" #include "ui/console.h"
#include "hw/arm/omap.h" #include "hw/arm/omap.h"
#include "hw/boards.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"); fprintf(stderr, "Kernel or ROM image must be specified\n");
exit(1); exit(1);
} }

View file

@ -24,6 +24,7 @@
#include "ui/console.h" #include "ui/console.h"
#include "audio/audio.h" #include "audio/audio.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "sysemu/qtest.h"
#ifdef DEBUG_Z2 #ifdef DEBUG_Z2
#define DPRINTF(fmt, ...) \ #define DPRINTF(fmt, ...) \
@ -323,7 +324,7 @@ static void z2_init(QEMUMachineInitArgs *args)
be = 0; be = 0;
#endif #endif
dinfo = drive_get(IF_PFLASH, 0, 0); dinfo = drive_get(IF_PFLASH, 0, 0);
if (!dinfo) { if (!dinfo && !qtest_enabled()) {
fprintf(stderr, "Flash image must be given with the " fprintf(stderr, "Flash image must be given with the "
"'pflash' parameter\n"); "'pflash' parameter\n");
exit(1); exit(1);
@ -331,7 +332,7 @@ static void z2_init(QEMUMachineInitArgs *args)
if (!pflash_cfi01_register(Z2_FLASH_BASE, if (!pflash_cfi01_register(Z2_FLASH_BASE,
NULL, "z2.flash0", Z2_FLASH_SIZE, 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, Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
be)) { be)) {
fprintf(stderr, "qemu: Error registering flash memory.\n"); fprintf(stderr, "qemu: Error registering flash memory.\n");

View file

@ -1,6 +1,8 @@
#include "hw/hw.h" #include "hw/hw.h"
#include "hw/sh4/sh.h" #include "hw/sh4/sh.h"
#include "hw/loader.h" #include "hw/loader.h"
#include "sysemu/qtest.h"
#include "qemu/error-report.h"
#define CE1 0x0100 #define CE1 0x0100
#define CE2 0x0200 #define CE2 0x0200
@ -36,10 +38,10 @@ static void init_dev(tc58128_dev * dev, const char *filename)
/* Load flash image skipping the first block */ /* Load flash image skipping the first block */
ret = load_image(filename, dev->flash_contents + 528 * 32); ret = load_image(filename, dev->flash_contents + 528 * 32);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "ret=%d\n", ret); if (!qtest_enabled()) {
fprintf(stderr, "qemu: could not load flash image %s\n", error_report("Could not load flash image %s", filename);
filename);
exit(1); exit(1);
}
} else { } else {
/* Build first block with number of blocks */ /* Build first block with number of blocks */
blocks = (ret + 528 * 32 - 1) / (528 * 32); blocks = (ret + 528 * 32 - 1) / (528 * 32);

View file

@ -195,22 +195,26 @@ static void milkymist_uart_reset(DeviceState *d)
s->regs[R_STAT] = STAT_THRE; 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); 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(); s->chr = qemu_char_get_next_serial();
if (s->chr) { if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); 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 = { 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) static void milkymist_uart_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); 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->reset = milkymist_uart_reset;
dc->vmsd = &vmstate_milkymist_uart; dc->vmsd = &vmstate_milkymist_uart;
} }
@ -238,6 +241,7 @@ static const TypeInfo milkymist_uart_info = {
.name = TYPE_MILKYMIST_UART, .name = TYPE_MILKYMIST_UART,
.parent = TYPE_SYS_BUS_DEVICE, .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistUartState), .instance_size = sizeof(MilkymistUartState),
.instance_init = milkymist_uart_init,
.class_init = milkymist_uart_class_init, .class_init = milkymist_uart_class_init,
}; };

View file

@ -164,7 +164,7 @@ int qdev_init(DeviceState *dev)
if (local_err != NULL) { if (local_err != NULL) {
qerror_report_err(local_err); qerror_report_err(local_err);
error_free(local_err); error_free(local_err);
qdev_free(dev); object_unparent(OBJECT(dev));
return -1; return -1;
} }
return 0; return 0;
@ -258,7 +258,7 @@ void qbus_reset_all_fn(void *opaque)
int qdev_simple_unplug_cb(DeviceState *dev) int qdev_simple_unplug_cb(DeviceState *dev)
{ {
/* just zap it */ /* just zap it */
qdev_free(dev); object_unparent(OBJECT(dev));
return 0; 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) void qdev_machine_creation_done(void)
{ {
/* /*
@ -458,7 +452,7 @@ static void bus_unparent(Object *obj)
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) { while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
DeviceState *dev = kid->child; DeviceState *dev = kid->child;
qdev_free(dev); object_unparent(OBJECT(dev));
} }
if (bus->parent) { if (bus->parent) {
QLIST_REMOVE(bus, sibling); QLIST_REMOVE(bus, sibling);

View file

@ -1,4 +1,5 @@
obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
obj-$(CONFIG_REALVIEW) += realview_mpcore.o
obj-$(CONFIG_A9MPCORE) += a9mpcore.o obj-$(CONFIG_A9MPCORE) += a9mpcore.o
obj-$(CONFIG_A15MPCORE) += a15mpcore.o obj-$(CONFIG_A15MPCORE) += a15mpcore.o
obj-$(CONFIG_ICC_BUS) += icc_bus.o obj-$(CONFIG_ICC_BUS) += icc_bus.o

View file

@ -18,55 +18,60 @@
* with this program; if not, see <http://www.gnu.org/licenses/>. * with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#include "hw/sysbus.h" #include "hw/cpu/a15mpcore.h"
#include "sysemu/kvm.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) static void a15mp_priv_set_irq(void *opaque, int irq, int level)
{ {
A15MPPrivState *s = (A15MPPrivState *)opaque; 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 *sbd = SYS_BUS_DEVICE(obj);
SysBusDevice *busdev; A15MPPrivState *s = A15MPCORE_PRIV(obj);
DeviceState *gicdev;
const char *gictype = "arm_gic"; const char *gictype = "arm_gic";
int i;
if (kvm_irqchip_in_kernel()) { if (kvm_irqchip_in_kernel()) {
gictype = "kvm-arm-gic"; gictype = "kvm-arm-gic";
} }
s->gic = qdev_create(NULL, gictype); memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000);
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); sysbus_init_mmio(sbd, &s->container);
qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
qdev_prop_set_uint32(s->gic, "revision", 2); object_initialize(&s->gic, sizeof(s->gic), gictype);
qdev_init_nofail(s->gic); gicdev = DEVICE(&s->gic);
busdev = SYS_BUS_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 */ /* 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 */ /* 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 /* Wire the outputs from each CPU's generic timer to the
* appropriate GIC PPI inputs * 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. * since a real A15 always has TrustZone but QEMU doesn't.
*/ */
qdev_connect_gpio_out(cpudev, 0, qdev_connect_gpio_out(cpudev, 0,
qdev_get_gpio_in(s->gic, ppibase + 30)); qdev_get_gpio_in(gicdev, ppibase + 30));
/* virtual timer */ /* virtual timer */
qdev_connect_gpio_out(cpudev, 1, 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): /* 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) * 0x5000-0x5fff -- GIC virtual interface control (not modelled)
* 0x6000-0x7fff -- GIC virtual CPU interface (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, memory_region_add_subregion(&s->container, 0x1000,
sysbus_mmio_get_region(busdev, 0)); sysbus_mmio_get_region(busdev, 0));
memory_region_add_subregion(&s->container, 0x2000, memory_region_add_subregion(&s->container, 0x2000,
sysbus_mmio_get_region(busdev, 1)); sysbus_mmio_get_region(busdev, 1));
sysbus_init_mmio(dev, &s->container);
return 0;
} }
static Property a15mp_priv_properties[] = { static Property a15mp_priv_properties[] = {
@ -118,8 +118,8 @@ static Property a15mp_priv_properties[] = {
static void a15mp_priv_class_init(ObjectClass *klass, void *data) static void a15mp_priv_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); 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; dc->props = a15mp_priv_properties;
/* We currently have no savable state */ /* We currently have no savable state */
} }
@ -128,6 +128,7 @@ static const TypeInfo a15mp_priv_info = {
.name = TYPE_A15MPCORE_PRIV, .name = TYPE_A15MPCORE_PRIV,
.parent = TYPE_SYS_BUS_DEVICE, .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(A15MPPrivState), .instance_size = sizeof(A15MPPrivState),
.instance_init = a15mp_priv_initfn,
.class_init = a15mp_priv_class_init, .class_init = a15mp_priv_class_init,
}; };

View file

@ -8,64 +8,86 @@
* This code is licensed under the GPL. * This code is licensed under the GPL.
*/ */
#include "hw/sysbus.h" #include "hw/cpu/a9mpcore.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;
static void a9mp_priv_set_irq(void *opaque, int irq, int level) static void a9mp_priv_set_irq(void *opaque, int irq, int level)
{ {
A9MPPrivState *s = (A9MPPrivState *)opaque; 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 int a9mp_priv_init(SysBusDevice *dev) 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 void a9mp_priv_realize(DeviceState *dev, Error **errp)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
A9MPPrivState *s = A9MPCORE_PRIV(dev); A9MPPrivState *s = A9MPCORE_PRIV(dev);
DeviceState *gicdev, *scudev, *mptimerdev, *wdtdev;
SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev; SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev;
Error *err = NULL;
int i; int i;
s->gic = qdev_create(NULL, "arm_gic"); gicdev = DEVICE(&s->gic);
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq); qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
qdev_init_nofail(s->gic); object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
gicbusdev = SYS_BUS_DEVICE(s->gic); if (err != NULL) {
error_propagate(errp, err);
return;
}
gicbusdev = SYS_BUS_DEVICE(&s->gic);
/* Pass through outbound IRQ lines from the 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 */ /* Pass through inbound GPIO lines to the GIC */
qdev_init_gpio_in(DEVICE(dev), a9mp_priv_set_irq, s->num_irq - 32); qdev_init_gpio_in(dev, a9mp_priv_set_irq, s->num_irq - 32);
s->scu = qdev_create(NULL, "a9-scu"); scudev = DEVICE(&s->scu);
qdev_prop_set_uint32(s->scu, "num-cpu", s->num_cpu); qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
qdev_init_nofail(s->scu); object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
scubusdev = SYS_BUS_DEVICE(s->scu); if (err != NULL) {
error_propagate(errp, err);
return;
}
scubusdev = SYS_BUS_DEVICE(&s->scu);
s->mptimer = qdev_create(NULL, "arm_mptimer"); mptimerdev = DEVICE(&s->mptimer);
qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu); qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu);
qdev_init_nofail(s->mptimer); object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err);
timerbusdev = SYS_BUS_DEVICE(s->mptimer); if (err != NULL) {
error_propagate(errp, err);
return;
}
timerbusdev = SYS_BUS_DEVICE(&s->mptimer);
s->wdt = qdev_create(NULL, "arm_mptimer"); wdtdev = DEVICE(&s->wdt);
qdev_prop_set_uint32(s->wdt, "num-cpu", s->num_cpu); qdev_prop_set_uint32(wdtdev, "num-cpu", s->num_cpu);
qdev_init_nofail(s->wdt); object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err);
wdtbusdev = SYS_BUS_DEVICE(s->wdt); if (err != NULL) {
error_propagate(errp, err);
return;
}
wdtbusdev = SYS_BUS_DEVICE(&s->wdt);
/* Memory map (addresses are offsets from PERIPHBASE): /* Memory map (addresses are offsets from PERIPHBASE):
* 0x0000-0x00ff -- Snoop Control Unit * 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. * 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, memory_region_add_subregion(&s->container, 0,
sysbus_mmio_get_region(scubusdev, 0)); sysbus_mmio_get_region(scubusdev, 0));
/* GIC CPU interface */ /* GIC CPU interface */
@ -94,19 +115,16 @@ static int a9mp_priv_init(SysBusDevice *dev)
memory_region_add_subregion(&s->container, 0x1000, memory_region_add_subregion(&s->container, 0x1000,
sysbus_mmio_get_region(gicbusdev, 0)); sysbus_mmio_get_region(gicbusdev, 0));
sysbus_init_mmio(dev, &s->container);
/* Wire up the interrupt from each watchdog and timer. /* Wire up the interrupt from each watchdog and timer.
* For each core the timer is PPI 29 and the watchdog PPI 30. * For each core the timer is PPI 29 and the watchdog PPI 30.
*/ */
for (i = 0; i < s->num_cpu; i++) { for (i = 0; i < s->num_cpu; i++) {
int ppibase = (s->num_irq - 32) + i * 32; int ppibase = (s->num_irq - 32) + i * 32;
sysbus_connect_irq(timerbusdev, i, 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, 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[] = { static Property a9mp_priv_properties[] = {
@ -124,9 +142,8 @@ static Property a9mp_priv_properties[] = {
static void a9mp_priv_class_init(ObjectClass *klass, void *data) static void a9mp_priv_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); 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; dc->props = a9mp_priv_properties;
} }
@ -134,6 +151,7 @@ static const TypeInfo a9mp_priv_info = {
.name = TYPE_A9MPCORE_PRIV, .name = TYPE_A9MPCORE_PRIV,
.parent = TYPE_SYS_BUS_DEVICE, .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(A9MPPrivState), .instance_size = sizeof(A9MPPrivState),
.instance_init = a9mp_priv_initfn,
.class_init = a9mp_priv_class_init, .class_init = a9mp_priv_class_init,
}; };

View file

@ -7,96 +7,28 @@
* This code is licensed under the GPL. * This code is licensed under the GPL.
*/ */
#include "hw/sysbus.h" #include "hw/cpu/arm11mpcore.h"
#include "qemu/timer.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) static void mpcore_priv_set_irq(void *opaque, int irq, int level)
{ {
ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque; 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) static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
{ {
int i; int i;
SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic); SysBusDevice *scubusdev = SYS_BUS_DEVICE(&s->scu);
SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer); DeviceState *gicdev = DEVICE(&s->gic);
SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer); SysBusDevice *gicbusdev = SYS_BUS_DEVICE(&s->gic);
memory_region_init(&s->container, OBJECT(s), SysBusDevice *timerbusdev = SYS_BUS_DEVICE(&s->mptimer);
"mpcode-priv-container", 0x2000); SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(&s->wdtimer);
memory_region_init_io(&s->iomem, OBJECT(s),
&mpcore_scu_ops, s, "mpcore-scu", 0x100); memory_region_add_subregion(&s->container, 0,
memory_region_add_subregion(&s->container, 0, &s->iomem); sysbus_mmio_get_region(scubusdev, 0));
/* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
* at 0x200, 0x300... * at 0x200, 0x300...
*/ */
@ -124,134 +56,84 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
for (i = 0; i < s->num_cpu; i++) { for (i = 0; i < s->num_cpu; i++) {
int ppibase = (s->num_irq - 32) + i * 32; int ppibase = (s->num_irq - 32) + i * 32;
sysbus_connect_irq(timerbusdev, i, 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, 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); 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;
s->gic = qdev_create(NULL, "arm_gic"); qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq); if (err != NULL) {
/* Request the legacy 11MPCore GIC behaviour: */ error_propagate(errp, err);
qdev_prop_set_uint32(s->gic, "revision", 0); return;
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 */ /* 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 */ /* Pass through inbound GPIO lines to the GIC */
qdev_init_gpio_in(dev, mpcore_priv_set_irq, s->num_irq - 32); qdev_init_gpio_in(dev, mpcore_priv_set_irq, s->num_irq - 32);
s->mptimer = qdev_create(NULL, "arm_mptimer"); qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu); object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err);
qdev_init_nofail(s->mptimer); if (err != NULL) {
error_propagate(errp, err);
return;
}
s->wdtimer = qdev_create(NULL, "arm_mptimer"); qdev_prop_set_uint32(wdtimerdev, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(s->wdtimer, "num-cpu", s->num_cpu); object_property_set_bool(OBJECT(&s->wdtimer), true, "realized", &err);
qdev_init_nofail(s->wdtimer); if (err != NULL) {
error_propagate(errp, err);
return;
}
mpcore_priv_map_setup(s); mpcore_priv_map_setup(s);
}
static void mpcore_priv_initfn(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(obj);
memory_region_init(&s->container, OBJECT(s),
"mpcore-priv-container", 0x2000);
sysbus_init_mmio(sbd, &s->container); sysbus_init_mmio(sbd, &s->container);
return 0;
object_initialize(&s->scu, sizeof(s->scu), TYPE_ARM11_SCU);
qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
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);
object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER);
qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default());
object_initialize(&s->wdtimer, sizeof(s->wdtimer), TYPE_ARM_MPTIMER);
qdev_set_parent_bus(DEVICE(&s->wdtimer), sysbus_get_default());
} }
#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)
{
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 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;
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;
}
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);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = realview_mpcore_init;
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),
.class_init = mpcore_rirq_class_init,
};
static Property mpcore_priv_properties[] = { static Property mpcore_priv_properties[] = {
DEFINE_PROP_UINT32("num-cpu", ARM11MPCorePriveState, num_cpu, 1), DEFINE_PROP_UINT32("num-cpu", ARM11MPCorePriveState, num_cpu, 1),
/* The ARM11 MPCORE TRM says the on-chip controller may have /* 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) static void mpcore_priv_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); 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; dc->props = mpcore_priv_properties;
} }
@ -279,12 +160,12 @@ static const TypeInfo mpcore_priv_info = {
.name = TYPE_ARM11MPCORE_PRIV, .name = TYPE_ARM11MPCORE_PRIV,
.parent = TYPE_SYS_BUS_DEVICE, .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ARM11MPCorePriveState), .instance_size = sizeof(ARM11MPCorePriveState),
.instance_init = mpcore_priv_initfn,
.class_init = mpcore_priv_class_init, .class_init = mpcore_priv_class_init,
}; };
static void arm11mpcore_register_types(void) static void arm11mpcore_register_types(void)
{ {
type_register_static(&mpcore_rirq_info);
type_register_static(&mpcore_priv_info); type_register_static(&mpcore_priv_info);
} }

139
hw/cpu/realview_mpcore.c Normal file
View file

@ -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)

View file

@ -32,6 +32,7 @@
#include "boot.h" #include "boot.h"
#include "sysemu/blockdev.h" #include "sysemu/blockdev.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "sysemu/qtest.h"
#define D(x) #define D(x)
#define DNAND(x) #define DNAND(x)
@ -340,14 +341,14 @@ void axisdev88_init(QEMUMachineInitArgs *args)
irq[0x14 + i]); irq[0x14 + i]);
} }
if (!kernel_filename) { if (kernel_filename) {
fprintf(stderr, "Kernel image must be specified\n");
exit(1);
}
li.image_filename = kernel_filename; li.image_filename = kernel_filename;
li.cmdline = kernel_cmdline; li.cmdline = kernel_cmdline;
cris_load_image(cpu, &li); cris_load_image(cpu, &li);
} else if (!qtest_enabled()) {
fprintf(stderr, "Kernel image must be specified\n");
exit(1);
}
} }
static QEMUMachine axisdev88_machine = { static QEMUMachine axisdev88_machine = {

View file

@ -2215,55 +2215,6 @@ void ide_init2(IDEBus *bus, qemu_irq irq)
bus->dma = &ide_dma_nop; 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[] = { static const MemoryRegionPortio ide_portio_list[] = {
{ 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write }, { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write },
{ 0, 2, 2, .read = ide_data_readw, .write = ide_data_writew }, { 0, 2, 2, .read = ide_data_readw, .write = ide_data_writew },

View file

@ -553,8 +553,6 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
uint32_t cylinders, uint32_t heads, uint32_t secs, uint32_t cylinders, uint32_t heads, uint32_t secs,
int chs_trans); int chs_trans);
void ide_init2(IDEBus *bus, qemu_irq irq); 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_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
void ide_exec_cmd(IDEBus *bus, uint32_t val); void ide_exec_cmd(IDEBus *bus, uint32_t val);

View file

@ -30,15 +30,22 @@
#include <hw/ide/internal.h> #include <hw/ide/internal.h>
#define TYPE_MICRODRIVE "microdrive"
#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE)
/***********************************************************/ /***********************************************************/
/* CF-ATA Microdrive */ /* CF-ATA Microdrive */
#define METADATA_SIZE 0x20 #define METADATA_SIZE 0x20
/* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface. */ /* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface. */
typedef struct {
typedef struct MicroDriveState {
/*< private >*/
PCMCIACardState parent_obj;
/*< public >*/
IDEBus bus; IDEBus bus;
PCMCIACardState card;
uint32_t attr_base; uint32_t attr_base;
uint32_t io_base; uint32_t io_base;
@ -81,10 +88,13 @@ enum md_ctrl {
static inline void md_interrupt_update(MicroDriveState *s) static inline void md_interrupt_update(MicroDriveState *s)
{ {
if (!s->card.slot) PCMCIACardState *card = PCMCIA_CARD(s);
return;
qemu_set_irq(s->card.slot->irq, if (card->slot == NULL) {
return;
}
qemu_set_irq(card->slot->irq,
!(s->stat & STAT_INT) && /* Inverted */ !(s->stat & STAT_INT) && /* Inverted */
!(s->ctrl & (CTRL_IEN | CTRL_SRST)) && !(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
!(s->opt & OPT_SRESET)); !(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) static void md_set_irq(void *opaque, int irq, int level)
{ {
MicroDriveState *s = opaque; MicroDriveState *s = opaque;
if (level)
if (level) {
s->stat |= STAT_INT; s->stat |= STAT_INT;
else } else {
s->stat &= ~STAT_INT; s->stat &= ~STAT_INT;
}
md_interrupt_update(s); 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->opt = OPT_MODE_MMAP;
s->stat = 0; s->stat = 0;
s->pins = 0; s->pins = 0;
@ -111,15 +125,18 @@ static void md_reset(MicroDriveState *s)
ide_bus_reset(&s->bus); 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->attr_base) {
if (at < s->card.cis_len) if (at < pcc->cis_len) {
return s->card.cis[at]; return pcc->cis[at];
else } else {
return 0x00; return 0x00;
} }
}
at -= s->attr_base; at -= s->attr_base;
@ -127,10 +144,11 @@ static uint8_t md_attr_read(void *opaque, uint32_t at)
case 0x00: /* Configuration Option Register */ case 0x00: /* Configuration Option Register */
return s->opt; return s->opt;
case 0x02: /* Card Configuration Status Register */ case 0x02: /* Card Configuration Status Register */
if (s->ctrl & CTRL_IEN) if (s->ctrl & CTRL_IEN) {
return s->stat & ~STAT_INT; return s->stat & ~STAT_INT;
else } else {
return s->stat; return s->stat;
}
case 0x04: /* Pin Replacement Register */ case 0x04: /* Pin Replacement Register */
return (s->pins & PINS_CRDY) | 0x0c; return (s->pins & PINS_CRDY) | 0x0c;
case 0x06: /* Socket and Copy Register */ case 0x06: /* Socket and Copy Register */
@ -144,21 +162,24 @@ static uint8_t md_attr_read(void *opaque, uint32_t at)
return 0; 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; at -= s->attr_base;
switch (at) { switch (at) {
case 0x00: /* Configuration Option Register */ case 0x00: /* Configuration Option Register */
s->opt = value & 0xcf; s->opt = value & 0xcf;
if (value & OPT_SRESET) if (value & OPT_SRESET) {
md_reset(s); device_reset(DEVICE(s));
}
md_interrupt_update(s); md_interrupt_update(s);
break; break;
case 0x02: /* Card Configuration Status Register */ case 0x02: /* Card Configuration Status Register */
if ((s->stat ^ value) & STAT_PWRDWN) if ((s->stat ^ value) & STAT_PWRDWN) {
s->pins |= PINS_CRDY; s->pins |= PINS_CRDY;
}
s->stat &= 0x82; s->stat &= 0x82;
s->stat |= value & 0x74; s->stat |= value & 0x74;
md_interrupt_update(s); md_interrupt_update(s);
@ -175,33 +196,36 @@ 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; IDEState *ifs;
uint16_t ret; uint16_t ret;
at -= s->io_base; at -= s->io_base;
switch (s->opt & OPT_MODE) { switch (s->opt & OPT_MODE) {
case OPT_MODE_MMAP: case OPT_MODE_MMAP:
if ((at & ~0x3ff) == 0x400) if ((at & ~0x3ff) == 0x400) {
at = 0; at = 0;
}
break; break;
case OPT_MODE_IOMAP16: case OPT_MODE_IOMAP16:
at &= 0xf; at &= 0xf;
break; break;
case OPT_MODE_IOMAP1: case OPT_MODE_IOMAP1:
if ((at & ~0xf) == 0x3f0) if ((at & ~0xf) == 0x3f0) {
at -= 0x3e8; at -= 0x3e8;
else if ((at & ~0xf) == 0x1f0) } else if ((at & ~0xf) == 0x1f0) {
at -= 0x1f0; at -= 0x1f0;
}
break; break;
case OPT_MODE_IOMAP2: case OPT_MODE_IOMAP2:
if ((at & ~0xf) == 0x370) if ((at & ~0xf) == 0x370) {
at -= 0x368; at -= 0x368;
else if ((at & ~0xf) == 0x170) } else if ((at & ~0xf) == 0x170) {
at -= 0x170; at -= 0x170;
} }
}
switch (at) { switch (at) {
case 0x0: /* Even RD Data */ case 0x0: /* Even RD Data */
@ -209,9 +233,9 @@ static uint16_t md_common_read(void *opaque, uint32_t at)
return ide_data_readw(&s->bus, 0); return ide_data_readw(&s->bus, 0);
/* TODO: 8-bit accesses */ /* TODO: 8-bit accesses */
if (s->cycle) if (s->cycle) {
ret = s->io >> 8; ret = s->io >> 8;
else { } else {
s->io = ide_data_readw(&s->bus, 0); s->io = ide_data_readw(&s->bus, 0);
ret = s->io & 0xff; 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); return ide_ioport_read(&s->bus, 0x1);
case 0xe: /* Alternate Status */ case 0xe: /* Alternate Status */
ifs = idebus_active_if(&s->bus); ifs = idebus_active_if(&s->bus);
if (ifs->bs) if (ifs->bs) {
return ifs->status; return ifs->status;
else } else {
return 0; return 0;
}
case 0xf: /* Device Address */ case 0xf: /* Device Address */
ifs = idebus_active_if(&s->bus); ifs = idebus_active_if(&s->bus);
return 0xc2 | ((~ifs->select << 2) & 0x3c); return 0xc2 | ((~ifs->select << 2) & 0x3c);
@ -237,31 +262,34 @@ static uint16_t md_common_read(void *opaque, uint32_t at)
return 0; 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; at -= s->io_base;
switch (s->opt & OPT_MODE) { switch (s->opt & OPT_MODE) {
case OPT_MODE_MMAP: case OPT_MODE_MMAP:
if ((at & ~0x3ff) == 0x400) if ((at & ~0x3ff) == 0x400) {
at = 0; at = 0;
}
break; break;
case OPT_MODE_IOMAP16: case OPT_MODE_IOMAP16:
at &= 0xf; at &= 0xf;
break; break;
case OPT_MODE_IOMAP1: case OPT_MODE_IOMAP1:
if ((at & ~0xf) == 0x3f0) if ((at & ~0xf) == 0x3f0) {
at -= 0x3e8; at -= 0x3e8;
else if ((at & ~0xf) == 0x1f0) } else if ((at & ~0xf) == 0x1f0) {
at -= 0x1f0; at -= 0x1f0;
}
break; break;
case OPT_MODE_IOMAP2: case OPT_MODE_IOMAP2:
if ((at & ~0xf) == 0x370) if ((at & ~0xf) == 0x370) {
at -= 0x368; at -= 0x368;
else if ((at & ~0xf) == 0x170) } else if ((at & ~0xf) == 0x170) {
at -= 0x170; at -= 0x170;
} }
}
switch (at) { switch (at) {
case 0x0: /* Even WR Data */ case 0x0: /* Even WR Data */
@ -270,10 +298,11 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value)
break; break;
/* TODO: 8-bit accesses */ /* TODO: 8-bit accesses */
if (s->cycle) if (s->cycle) {
ide_data_writew(&s->bus, 0, s->io | (value << 8)); ide_data_writew(&s->bus, 0, s->io | (value << 8));
else } else {
s->io = value & 0xff; s->io = value & 0xff;
}
s->cycle = !s->cycle; s->cycle = !s->cycle;
break; break;
case 0x9: case 0x9:
@ -285,8 +314,9 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value)
break; break;
case 0xe: /* Device Control */ case 0xe: /* Device Control */
s->ctrl = value; s->ctrl = value;
if (value & CTRL_SRST) if (value & CTRL_SRST) {
md_reset(s); device_reset(DEVICE(s));
}
md_interrupt_update(s); md_interrupt_update(s);
break; break;
default: default:
@ -501,49 +531,109 @@ static const uint8_t dscm1xxxx_cis[0x14a] = {
[0x146] = CISTPL_END, /* Tuple End */ [0x146] = CISTPL_END, /* Tuple End */
}; };
static int dscm1xxxx_attach(void *opaque) #define TYPE_DSCM1XXXX "dscm1xxxx"
{
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); static int dscm1xxxx_attach(PCMCIACardState *card)
{
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->io_base = 0x0;
md_reset(md); device_reset(DEVICE(md));
md_interrupt_update(md); md_interrupt_update(md);
md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive"; card->slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
return 0; return 0;
} }
static int dscm1xxxx_detach(void *opaque) static int dscm1xxxx_detach(PCMCIACardState *card)
{ {
MicroDriveState *md = opaque; MicroDriveState *md = MICRODRIVE(card);
md_reset(md);
device_reset(DEVICE(md));
return 0; return 0;
} }
PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv) PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo)
{ {
MicroDriveState *md = (MicroDriveState *) g_malloc0(sizeof(MicroDriveState)); MicroDriveState *md;
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, md = MICRODRIVE(object_new(TYPE_DSCM1XXXX));
qemu_allocate_irqs(md_set_irq, md, 1)[0]); 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].drive_kind = IDE_CFATA;
md->bus.ifs[0].mdata_size = METADATA_SIZE; md->bus.ifs[0].mdata_size = METADATA_SIZE;
md->bus.ifs[0].mdata_storage = (uint8_t *) g_malloc0(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);
return &md->card;
} }
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);
}
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(&microdrive_type_info);
type_register_static(&dscm1xxxx_type_info);
}
type_init(microdrive_register_types)

View file

@ -64,17 +64,17 @@ static const VMStateDescription vmstate_gic = {
.post_load = gic_post_load, .post_load = gic_post_load,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_BOOL(enabled, GICState), 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_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
vmstate_gic_irq_state, gic_irq_state), vmstate_gic_irq_state, gic_irq_state),
VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ), 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_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU), VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU),
VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU), VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU), VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU), VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU), VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
} }
}; };
@ -84,9 +84,9 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
GICState *s = ARM_GIC_COMMON(dev); GICState *s = ARM_GIC_COMMON(dev);
int num_irq = s->num_irq; 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", error_setg(errp, "requested %u CPUs exceeds GIC maximum %d",
s->num_cpu, NCPU); s->num_cpu, GIC_NCPU);
return; return;
} }
s->num_irq += GIC_BASE_IRQ; s->num_irq += GIC_BASE_IRQ;

View file

@ -21,16 +21,9 @@
#ifndef QEMU_ARM_GIC_INTERNAL_H #ifndef QEMU_ARM_GIC_INTERNAL_H
#define 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 ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
#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)))
/* The NVIC has 16 internal vectors. However these are not exposed /* The NVIC has 16 internal vectors. However these are not exposed
through the normal GIC interface. */ through the normal GIC interface. */
@ -59,48 +52,6 @@
s->priority2[(irq) - GIC_INTERNAL]) s->priority2[(irq) - GIC_INTERNAL])
#define GIC_TARGET(irq) s->irq_target[irq] #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: */ /* The special cases for the revision property: */
#define REV_11MPCORE 0 #define REV_11MPCORE 0
#define REV_NVIC 0xffffffff #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_update(GICState *s);
void gic_init_irqs_and_distributor(GICState *s, int num_irq); 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 */ #endif /* !QEMU_ARM_GIC_INTERNAL_H */

View file

@ -7,41 +7,34 @@
* This code is licensed under the GPL. * This code is licensed under the GPL.
*/ */
#include "hw/sysbus.h" #include "hw/intc/realview_gic.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;
static void realview_gic_set_irq(void *opaque, int irq, int level) static void realview_gic_set_irq(void *opaque, int irq, int level)
{ {
RealViewGICState *s = (RealViewGICState *)opaque; 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); RealViewGICState *s = REALVIEW_GIC(dev);
SysBusDevice *busdev; SysBusDevice *busdev;
Error *err = NULL;
/* The GICs on the RealView boards have a fixed nonconfigurable /* The GICs on the RealView boards have a fixed nonconfigurable
* number of interrupt lines, so we don't need to expose this as * number of interrupt lines, so we don't need to expose this as
* a qdev property. * a qdev property.
*/ */
int numirq = 96; int numirq = 96;
s->gic = qdev_create(NULL, "arm_gic"); qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", numirq);
qdev_prop_set_uint32(s->gic, "num-cpu", 1); object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
qdev_prop_set_uint32(s->gic, "num-irq", numirq); if (err != NULL) {
qdev_init_nofail(s->gic); error_propagate(errp, err);
busdev = SYS_BUS_DEVICE(s->gic); return;
}
busdev = SYS_BUS_DEVICE(&s->gic);
/* Pass through outbound IRQ lines from the GIC */ /* Pass through outbound IRQ lines from the GIC */
sysbus_pass_irq(sbd, busdev); sysbus_pass_irq(sbd, busdev);
@ -49,27 +42,40 @@ static int realview_gic_init(SysBusDevice *sbd)
/* Pass through inbound GPIO lines to the GIC */ /* Pass through inbound GPIO lines to the GIC */
qdev_init_gpio_in(dev, realview_gic_set_irq, numirq - 32); 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, memory_region_add_subregion(&s->container, 0,
sysbus_mmio_get_region(busdev, 1)); sysbus_mmio_get_region(busdev, 1));
memory_region_add_subregion(&s->container, 0x1000, memory_region_add_subregion(&s->container, 0x1000,
sysbus_mmio_get_region(busdev, 0)); sysbus_mmio_get_region(busdev, 0));
sysbus_init_mmio(sbd, &s->container);
return 0;
} }
static void realview_gic_class_init(ObjectClass *klass, void *data) static void realview_gic_init(Object *obj)
{ {
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
RealViewGICState *s = REALVIEW_GIC(obj);
DeviceState *gicdev;
sdc->init = realview_gic_init; memory_region_init(&s->container, OBJECT(s),
"realview-gic-container", 0x2000);
sysbus_init_mmio(sbd, &s->container);
object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
gicdev = DEVICE(&s->gic);
qdev_set_parent_bus(gicdev, sysbus_get_default());
qdev_prop_set_uint32(gicdev, "num-cpu", 1);
}
static void realview_gic_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = realview_gic_realize;
} }
static const TypeInfo realview_gic_info = { static const TypeInfo realview_gic_info = {
.name = TYPE_REALVIEW_GIC, .name = TYPE_REALVIEW_GIC,
.parent = TYPE_SYS_BUS_DEVICE, .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(RealViewGICState), .instance_size = sizeof(RealViewGICState),
.instance_init = realview_gic_init,
.class_init = realview_gic_class_init, .class_init = realview_gic_class_init,
}; };

View file

@ -21,6 +21,7 @@
#include "hw/hw.h" #include "hw/hw.h"
#include "hw/block/flash.h" #include "hw/block/flash.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "hw/devices.h" #include "hw/devices.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/loader.h" #include "hw/loader.h"
@ -143,7 +144,7 @@ milkymist_init(QEMUMachineInitArgs *args)
reset_info->bootstrap_pc = BIOS_OFFSET; reset_info->bootstrap_pc = BIOS_OFFSET;
/* if no kernel is given no valid bios rom is a fatal error */ /* 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", fprintf(stderr, "qemu: could not load Milkymist One bios '%s'\n",
bios_name); bios_name);
exit(1); exit(1);

View file

@ -12,6 +12,7 @@
#include "hw/loader.h" #include "hw/loader.h"
#include "elf.h" #include "elf.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "sysemu/qtest.h"
#define KERNEL_LOAD_ADDR 0x10000 #define KERNEL_LOAD_ADDR 0x10000
#define AN5206_MBAR_ADDR 0x10000000 #define AN5206_MBAR_ADDR 0x10000000
@ -62,6 +63,9 @@ static void an5206_init(QEMUMachineInitArgs *args)
/* Load kernel. */ /* Load kernel. */
if (!kernel_filename) { if (!kernel_filename) {
if (qtest_enabled()) {
return;
}
fprintf(stderr, "Kernel image must be specified\n"); fprintf(stderr, "Kernel image must be specified\n");
exit(1); exit(1);
} }

View file

@ -10,6 +10,7 @@
#include "qemu/timer.h" #include "qemu/timer.h"
#include "hw/ptimer.h" #include "hw/ptimer.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "net/net.h" #include "net/net.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/loader.h" #include "hw/loader.h"
@ -267,6 +268,9 @@ static void mcf5208evb_init(QEMUMachineInitArgs *args)
/* Load kernel. */ /* Load kernel. */
if (!kernel_filename) { if (!kernel_filename) {
if (qtest_enabled()) {
return;
}
fprintf(stderr, "Kernel image must be specified\n"); fprintf(stderr, "Kernel image must be specified\n");
exit(1); exit(1);
} }

View file

@ -38,6 +38,7 @@
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "sysemu/qtest.h"
static struct _loaderparams { static struct _loaderparams {
int ram_size; int ram_size;
@ -190,7 +191,8 @@ mips_mipssim_init(QEMUMachineInitArgs *args)
} else { } else {
bios_size = -1; 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. */ /* Bail out if we have neither a kernel image nor boot vector code. */
error_report("Could not load MIPS bios '%s', and no " error_report("Could not load MIPS bios '%s', and no "
"-kernel argument was specified", filename); "-kernel argument was specified", filename);

View file

@ -11,6 +11,8 @@ obj-$(CONFIG_VMPORT) += vmport.o
# ARM devices # ARM devices
common-obj-$(CONFIG_PL310) += arm_l2x0.o common-obj-$(CONFIG_PL310) += arm_l2x0.o
common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.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 # PKUnity SoC devices
common-obj-$(CONFIG_PUV3) += puv3_pm.o common-obj-$(CONFIG_PUV3) += puv3_pm.o
@ -23,7 +25,6 @@ obj-$(CONFIG_LINUX) += vfio.o
endif endif
obj-$(CONFIG_REALVIEW) += arm_sysctl.o obj-$(CONFIG_REALVIEW) += arm_sysctl.o
obj-$(CONFIG_A9SCU) += a9scu.o
obj-$(CONFIG_NSERIES) += cbus.o obj-$(CONFIG_NSERIES) += cbus.o
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.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_l4.o
obj-$(CONFIG_OMAP) += omap_sdrc.o obj-$(CONFIG_OMAP) += omap_sdrc.o
obj-$(CONFIG_OMAP) += omap_tap.o obj-$(CONFIG_OMAP) += omap_tap.o
obj-$(CONFIG_PXA2XX) += pxa2xx_pcmcia.o
obj-$(CONFIG_SLAVIO) += slavio_misc.o obj-$(CONFIG_SLAVIO) += slavio_misc.o
obj-$(CONFIG_ZYNQ) += zynq_slcr.o obj-$(CONFIG_ZYNQ) += zynq_slcr.o

View file

@ -8,20 +8,7 @@
* This code is licensed under the GPL. * This code is licensed under the GPL.
*/ */
#include "hw/sysbus.h" #include "hw/misc/a9scu.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)
static uint64_t a9_scu_read(void *opaque, hwaddr offset, static uint64_t a9_scu_read(void *opaque, hwaddr offset,
unsigned size) unsigned size)
@ -114,12 +101,12 @@ static void a9_scu_reset(DeviceState *dev)
s->control = 0; s->control = 0;
} }
static void a9_scu_realize(DeviceState *dev, Error ** errp) static void a9_scu_init(Object *obj)
{ {
A9SCUState *s = A9_SCU(dev); A9SCUState *s = A9_SCU(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 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); "a9-scu", 0x100);
sysbus_init_mmio(sbd, &s->iomem); 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); DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = a9_scu_realize;
dc->props = a9_scu_properties; dc->props = a9_scu_properties;
dc->vmsd = &vmstate_a9_scu; dc->vmsd = &vmstate_a9_scu;
dc->reset = a9_scu_reset; dc->reset = a9_scu_reset;
@ -154,6 +140,7 @@ static const TypeInfo a9_scu_info = {
.name = TYPE_A9_SCU, .name = TYPE_A9_SCU,
.parent = TYPE_SYS_BUS_DEVICE, .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(A9SCUState), .instance_size = sizeof(A9SCUState),
.instance_init = a9_scu_init,
.class_init = a9_scu_class_init, .class_init = a9_scu_class_init,
}; };

100
hw/misc/arm11scu.c Normal file
View file

@ -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)

View file

@ -248,7 +248,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
} }
dev = pci_create(bus, devfn, "virtio-blk-pci"); dev = pci_create(bus, devfn, "virtio-blk-pci");
if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
qdev_free(&dev->qdev); object_unparent(OBJECT(dev));
dev = NULL; dev = NULL;
break; break;
} }

View file

@ -391,7 +391,7 @@ void pci_bridge_exitfn(PCIDevice *pci_dev)
pci_bridge_region_cleanup(s, s->windows); pci_bridge_region_cleanup(s, s->windows);
memory_region_destroy(&s->address_space_mem); memory_region_destroy(&s->address_space_mem);
memory_region_destroy(&s->address_space_io); memory_region_destroy(&s->address_space_io);
/* qbus_free() is called automatically by qdev_free() */ /* qbus_free() is called automatically during device deletion */
} }
/* /*

View file

@ -251,7 +251,7 @@ static int pcie_cap_slot_hotplug(DeviceState *qdev,
PCI_EXP_SLTSTA_PDS); PCI_EXP_SLTSTA_PDS);
pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
} else { } else {
qdev_free(&pci_dev->qdev); object_unparent(OBJECT(pci_dev));
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_PDS); PCI_EXP_SLTSTA_PDS);
pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);

View file

@ -254,7 +254,7 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
++devfn) { ++devfn) {
PCIDevice *affected_dev = shpc->sec_bus->devices[devfn]; PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
if (affected_dev) { if (affected_dev) {
qdev_free(&affected_dev->qdev); object_unparent(OBJECT(affected_dev));
} }
} }
} }

2
hw/pcmcia/Makefile.objs Normal file
View file

@ -0,0 +1,2 @@
common-obj-y += pcmcia.o
obj-$(CONFIG_PXA2XX) += pxa2xx.o

24
hw/pcmcia/pcmcia.c Normal file
View file

@ -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)

View file

@ -11,28 +11,38 @@
*/ */
#include "hw/hw.h" #include "hw/hw.h"
#include "hw/sysbus.h"
#include "hw/pcmcia.h" #include "hw/pcmcia.h"
#include "hw/arm/pxa.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 { struct PXA2xxPCMCIAState {
SysBusDevice parent_obj;
PCMCIASocket slot; PCMCIASocket slot;
PCMCIACardState *card; MemoryRegion container_mem;
MemoryRegion common_iomem; MemoryRegion common_iomem;
MemoryRegion attr_iomem; MemoryRegion attr_iomem;
MemoryRegion iomem; MemoryRegion iomem;
qemu_irq irq; qemu_irq irq;
qemu_irq cd_irq; qemu_irq cd_irq;
PCMCIACardState *card;
}; };
static uint64_t pxa2xx_pcmcia_common_read(void *opaque, static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
hwaddr offset, unsigned size) hwaddr offset, unsigned size)
{ {
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) { 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; return 0;
@ -42,9 +52,11 @@ static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size) uint64_t value, unsigned size)
{ {
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) { 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) hwaddr offset, unsigned size)
{ {
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) { 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; return 0;
@ -64,9 +78,11 @@ static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size) uint64_t value, unsigned size)
{ {
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) { 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) hwaddr offset, unsigned size)
{ {
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) { 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; return 0;
@ -86,9 +104,11 @@ static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size) uint64_t value, unsigned size)
{ {
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) { 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, PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
hwaddr base) hwaddr base)
{ {
DeviceState *dev;
PXA2xxPCMCIAState *s; PXA2xxPCMCIAState *s;
s = (PXA2xxPCMCIAState *) dev = qdev_create(NULL, TYPE_PXA2XX_PCMCIA);
g_malloc0(sizeof(PXA2xxPCMCIAState)); 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 */ /* Socket I/O Memory Space */
memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s, memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s,
"pxa2xx-pcmcia-io", 0x04000000); "pxa2xx-pcmcia-io", 0x04000000);
memory_region_add_subregion(sysmem, base | 0x00000000, memory_region_add_subregion(&s->container_mem, 0x00000000,
&s->iomem); &s->iomem);
/* Then next 64 MB is reserved */ /* Then next 64 MB is reserved */
@ -138,62 +186,68 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
/* Socket Attribute Memory Space */ /* Socket Attribute Memory Space */
memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s, memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s,
"pxa2xx-pcmcia-attribute", 0x04000000); "pxa2xx-pcmcia-attribute", 0x04000000);
memory_region_add_subregion(sysmem, base | 0x08000000, memory_region_add_subregion(&s->container_mem, 0x08000000,
&s->attr_iomem); &s->attr_iomem);
/* Socket Common Memory Space */ /* Socket Common Memory Space */
memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s, memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s,
"pxa2xx-pcmcia-common", 0x04000000); "pxa2xx-pcmcia-common", 0x04000000);
memory_region_add_subregion(sysmem, base | 0x0c000000, memory_region_add_subregion(&s->container_mem, 0x0c000000,
&s->common_iomem); &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]; 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 */ /* Insert a new card into a slot */
int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card) int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
{ {
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (s->slot.attached) PCMCIACardClass *pcc;
if (s->slot.attached) {
return -EEXIST; return -EEXIST;
}
if (s->cd_irq) { if (s->cd_irq) {
qemu_irq_raise(s->cd_irq); qemu_irq_raise(s->cd_irq);
} }
s->card = card; 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->slot = &s->slot;
s->card->attach(s->card->state); pcc->attach(s->card);
return 0; return 0;
} }
/* Eject card from the slot */ /* Eject card from the slot */
int pxa2xx_pcmcia_dettach(void *opaque) int pxa2xx_pcmcia_detach(void *opaque)
{ {
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (!s->slot.attached) PCMCIACardClass *pcc;
return -ENOENT;
s->card->detach(s->card->state); if (!s->slot.attached) {
return -ENOENT;
}
pcc = PCMCIA_CARD_GET_CLASS(s->card);
pcc->detach(s->card);
s->card->slot = NULL; s->card->slot = NULL;
s->card = NULL; s->card = NULL;
s->slot.attached = 0; s->slot.attached = false;
if (s->irq) if (s->irq) {
qemu_irq_lower(s->irq); qemu_irq_lower(s->irq);
if (s->cd_irq) }
if (s->cd_irq) {
qemu_irq_lower(s->cd_irq); qemu_irq_lower(s->cd_irq);
}
return 0; 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->irq = irq;
s->cd_irq = cd_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)

View file

@ -1239,7 +1239,7 @@ static int virtio_ccw_busdev_unplug(DeviceState *dev)
css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0); css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
qdev_free(dev); object_unparent(OBJECT(dev));
return 0; return 0;
} }

View file

@ -178,7 +178,7 @@ static int scsi_qdev_init(DeviceState *qdev)
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun); d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
assert(d); assert(d);
if (d->lun == dev->lun && dev != 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) { if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
error_setg(errp, "Setting drive property failed"); error_setg(errp, "Setting drive property failed");
qdev_free(dev); object_unparent(OBJECT(dev));
return NULL; return NULL;
} }
object_property_set_bool(OBJECT(dev), true, "realized", &err); object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err != NULL) { if (err != NULL) {
error_propagate(errp, err); error_propagate(errp, err);
qdev_free(dev); object_unparent(OBJECT(dev));
return NULL; return NULL;
} }
return SCSI_DEVICE(dev); return SCSI_DEVICE(dev);

View file

@ -30,9 +30,11 @@
#include "hw/hw.h" #include "hw/hw.h"
#include "hw/sh4/sh.h" #include "hw/sh4/sh.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/loader.h" #include "hw/loader.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "qemu/error-report.h"
#define BIOS_FILENAME "shix_bios.bin" #define BIOS_FILENAME "shix_bios.bin"
#define BIOS_ADDRESS 0xA0000000 #define BIOS_ADDRESS 0xA0000000
@ -50,7 +52,6 @@ static void shix_init(QEMUMachineInitArgs *args)
if (!cpu_model) if (!cpu_model)
cpu_model = "any"; cpu_model = "any";
printf("Initializing CPU\n");
cpu = cpu_sh4_init(cpu_model); cpu = cpu_sh4_init(cpu_model);
if (cpu == NULL) { if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n"); fprintf(stderr, "Unable to find CPU definition\n");
@ -58,16 +59,13 @@ static void shix_init(QEMUMachineInitArgs *args)
} }
/* Allocate memory space */ /* Allocate memory space */
printf("Allocating ROM\n");
memory_region_init_ram(rom, NULL, "shix.rom", 0x4000); memory_region_init_ram(rom, NULL, "shix.rom", 0x4000);
vmstate_register_ram_global(rom); vmstate_register_ram_global(rom);
memory_region_set_readonly(rom, true); memory_region_set_readonly(rom, true);
memory_region_add_subregion(sysmem, 0x00000000, rom); memory_region_add_subregion(sysmem, 0x00000000, rom);
printf("Allocating SDRAM 1\n");
memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000); memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000);
vmstate_register_ram_global(&sdram[0]); vmstate_register_ram_global(&sdram[0]);
memory_region_add_subregion(sysmem, 0x08000000, &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); memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000);
vmstate_register_ram_global(&sdram[1]); vmstate_register_ram_global(&sdram[1]);
memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]); memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
@ -75,12 +73,9 @@ static void shix_init(QEMUMachineInitArgs *args)
/* Load BIOS in 0 (and access it through P2, 0xA0000000) */ /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
if (bios_name == NULL) if (bios_name == NULL)
bios_name = BIOS_FILENAME; bios_name = BIOS_FILENAME;
printf("%s: load BIOS '%s'\n", __func__, bios_name);
ret = load_image_targphys(bios_name, 0, 0x4000); ret = load_image_targphys(bios_name, 0, 0x4000);
if (ret < 0) { /* Check bios size */ if (ret < 0 && !qtest_enabled()) {
fprintf(stderr, "ret=%d\n", ret); error_report("Could not load SHIX bios '%s'", bios_name);
fprintf(stderr, "qemu: could not load SHIX bios '%s'\n",
bios_name);
exit(1); exit(1);
} }
@ -88,7 +83,6 @@ static void shix_init(QEMUMachineInitArgs *args)
s = sh7750_init(cpu, sysmem); s = sh7750_init(cpu, sysmem);
/* XXXXX Check success */ /* XXXXX Check success */
tc58128_init(s, "shix_linux_nand.bin", NULL); tc58128_init(s, "shix_linux_nand.bin", NULL);
fprintf(stderr, "initialization terminated\n");
} }
static QEMUMachine shix_machine = { static QEMUMachine shix_machine = {

View file

@ -26,6 +26,7 @@
#include "hw/ptimer.h" #include "hw/ptimer.h"
#include "sysemu/char.h" #include "sysemu/char.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/loader.h" #include "hw/loader.h"
#include "elf.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); fprintf(stderr, "qemu: could not load prom '%s'\n", filename);
exit(1); exit(1);
} }
} else if (kernel_filename == NULL) { } else if (kernel_filename == NULL && !qtest_enabled()) {
fprintf(stderr, "Can't read bios image %s\n", filename); fprintf(stderr, "Can't read bios image %s\n", filename);
exit(1); exit(1);
} }

View file

@ -19,7 +19,7 @@
* with this program; if not, see <http://www.gnu.org/licenses/>. * 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 "qemu/timer.h"
#include "qom/cpu.h" #include "qom/cpu.h"
@ -27,34 +27,6 @@
* which is used in both the ARM11MPCore and Cortex-A9MP. * 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) static inline int get_current_cpu(ARMMPTimerState *s)
{ {
if (current_cpu->cpu_index >= s->num_cpu) { 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); ARMMPTimerState *s = ARM_MPTIMER(dev);
int i; int i;
if (s->num_cpu < 1 || s->num_cpu > 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__, 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: /* We implement one timer block per CPU, and expose multiple MMIO regions:
* * region 0 is "timer for this core" * * region 0 is "timer for this core"
@ -243,19 +226,14 @@ static int arm_mptimer_init(SysBusDevice *dev)
* * timer for core 1 * * timer for core 1
* and so on. * 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++) { for (i = 0; i < s->num_cpu; i++) {
TimerBlock *tb = &s->timerblock[i]; TimerBlock *tb = &s->timerblock[i];
tb->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, timerblock_tick, tb); 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, memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
"arm_mptimer_timerblock", 0x20); "arm_mptimer_timerblock", 0x20);
sysbus_init_mmio(dev, &tb->iomem); sysbus_init_mmio(sbd, &tb->iomem);
} }
return 0;
} }
static const VMStateDescription vmstate_timerblock = { static const VMStateDescription vmstate_timerblock = {
@ -292,9 +270,8 @@ static Property arm_mptimer_properties[] = {
static void arm_mptimer_class_init(ObjectClass *klass, void *data) static void arm_mptimer_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); 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->vmsd = &vmstate_arm_mptimer;
dc->reset = arm_mptimer_reset; dc->reset = arm_mptimer_reset;
dc->no_user = 1; dc->no_user = 1;
@ -305,6 +282,7 @@ static const TypeInfo arm_mptimer_info = {
.name = TYPE_ARM_MPTIMER, .name = TYPE_ARM_MPTIMER,
.parent = TYPE_SYS_BUS_DEVICE, .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ARMMPTimerState), .instance_size = sizeof(ARMMPTimerState),
.instance_init = arm_mptimer_init,
.class_init = arm_mptimer_class_init, .class_init = arm_mptimer_class_init,
}; };

View file

@ -17,6 +17,7 @@
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/loader.h" #include "hw/loader.h"
#include "hw/i386/pc.h" #include "hw/i386/pc.h"
#include "sysemu/qtest.h"
#undef DEBUG_PUV3 #undef DEBUG_PUV3
#include "hw/unicore32/puv3.h" #include "hw/unicore32/puv3.h"
@ -84,6 +85,9 @@ static void puv3_load_kernel(const char *kernel_filename)
{ {
int size; int size;
if (kernel_filename == NULL && qtest_enabled()) {
return;
}
assert(kernel_filename != NULL); assert(kernel_filename != NULL);
/* only zImage format supported */ /* only zImage format supported */

View file

@ -356,8 +356,9 @@ void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
void usb_unregister_port(USBBus *bus, USBPort *port) void usb_unregister_port(USBBus *bus, USBPort *port)
{ {
if (port->dev) if (port->dev) {
qdev_free(&port->dev->qdev); object_unparent(OBJECT(port->dev));
}
QTAILQ_REMOVE(&bus->free, port, next); QTAILQ_REMOVE(&bus->free, port, next);
bus->nfree--; bus->nfree--;
} }
@ -505,7 +506,7 @@ int usb_device_delete_addr(int busnr, int addr)
return -1; return -1;
dev = port->dev; dev = port->dev;
qdev_free(&dev->qdev); object_unparent(OBJECT(dev));
return 0; return 0;
} }

View file

@ -703,7 +703,7 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
return NULL; return NULL;
} }
if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
qdev_free(&dev->qdev); object_unparent(OBJECT(dev));
return NULL; return NULL;
} }
if (qdev_init(&dev->qdev) < 0) if (qdev_init(&dev->qdev) < 0)

View file

@ -132,7 +132,7 @@ USBDevice *usb_host_device_open(USBBus *bus, const char *devname)
return dev; return dev;
fail: fail:
qdev_free(&dev->qdev); object_unparent(OBJECT(dev));
return NULL; return NULL;
} }

View file

@ -67,7 +67,6 @@ void virtio_bus_reset(VirtioBusState *bus)
/* Destroy the VirtIODevice */ /* Destroy the VirtIODevice */
void virtio_bus_destroy_device(VirtioBusState *bus) void virtio_bus_destroy_device(VirtioBusState *bus)
{ {
DeviceState *qdev;
BusState *qbus = BUS(bus); BusState *qbus = BUS(bus);
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus); VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
DPRINTF("%s: remove device.\n", qbus->name); DPRINTF("%s: remove device.\n", qbus->name);
@ -76,8 +75,7 @@ void virtio_bus_destroy_device(VirtioBusState *bus)
if (klass->device_unplug != NULL) { if (klass->device_unplug != NULL) {
klass->device_unplug(qbus->parent); klass->device_unplug(qbus->parent);
} }
qdev = DEVICE(bus->vdev); object_unparent(OBJECT(bus->vdev));
qdev_free(qdev);
bus->vdev = NULL; bus->vdev = NULL;
} }
} }

View file

@ -95,7 +95,7 @@ static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
if (pci_get_word(d->config + PCI_CLASS_DEVICE) == if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
PCI_CLASS_NETWORK_ETHERNET PCI_CLASS_NETWORK_ETHERNET
&& strcmp(d->name, "xen-pci-passthrough") != 0) { && strcmp(d->name, "xen-pci-passthrough") != 0) {
qdev_free(DEVICE(d)); object_unparent(OBJECT(d));
} }
} }

View file

@ -97,7 +97,7 @@ typedef struct PXA2xxPCMCIAState PXA2xxPCMCIAState;
PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
hwaddr base); hwaddr base);
int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card); int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card);
int pxa2xx_pcmcia_dettach(void *opaque); int pxa2xx_pcmcia_detach(void *opaque);
void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq); void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq);
/* pxa2xx_keypad.c */ /* pxa2xx_keypad.c */

View file

@ -0,0 +1,44 @@
/*
* Cortex-A15MPCore internal peripheral emulation.
*
* Copyright (c) 2012 Linaro Limited.
* Written by Peter Maydell.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HW_CPU_A15MPCORE_H
#define HW_CPU_A15MPCORE_H
#include "hw/sysbus.h"
#include "hw/intc/arm_gic.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;
GICState gic;
} A15MPPrivState;
#endif

37
include/hw/cpu/a9mpcore.h Normal file
View file

@ -0,0 +1,37 @@
/*
* Cortex-A9MPCore internal peripheral emulation.
*
* Copyright (c) 2009 CodeSourcery.
* Copyright (c) 2011 Linaro Limited.
* Written by Paul Brook, Peter Maydell.
*
* This code is licensed under the GPL.
*/
#ifndef HW_CPU_A9MPCORE_H
#define HW_CPU_A9MPCORE_H
#include "hw/sysbus.h"
#include "hw/intc/arm_gic.h"
#include "hw/misc/a9scu.h"
#include "hw/timer/arm_mptimer.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;
uint32_t num_irq;
GICState gic;
A9SCUState scu;
ARMMPTimerState mptimer;
ARMMPTimerState wdt;
} A9MPPrivState;
#endif

View file

@ -0,0 +1,35 @@
/*
* ARM11MPCore internal peripheral emulation.
*
* Copyright (c) 2006-2007 CodeSourcery.
* Written by Paul Brook
*
* This code is licensed under the GPL.
*/
#ifndef HW_CPU_ARM11MPCORE_H
#define HW_CPU_ARM11MPCORE_H
#include "hw/sysbus.h"
#include "hw/misc/arm11scu.h"
#include "hw/intc/arm_gic.h"
#include "hw/timer/arm_mptimer.h"
#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 num_cpu;
MemoryRegion container;
uint32_t num_irq;
ARM11SCUState scu;
GICState gic;
ARMMPTimerState mptimer;
ARMMPTimerState wdtimer;
} ARM11MPCorePriveState;
#endif

42
include/hw/intc/arm_gic.h Normal file
View file

@ -0,0 +1,42 @@
/*
* ARM GIC support
*
* Copyright (c) 2012 Linaro Limited
* Written by Peter Maydell
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HW_ARM_GIC_H
#define HW_ARM_GIC_H
#include "arm_gic_common.h"
#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 {
/*< private >*/
ARMGICCommonClass parent_class;
/*< public >*/
DeviceRealize parent_realize;
} ARMGICClass;
#endif

View file

@ -0,0 +1,92 @@
/*
* ARM GIC support
*
* Copyright (c) 2012 Linaro Limited
* Written by Peter Maydell
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HW_ARM_GIC_COMMON_H
#define HW_ARM_GIC_COMMON_H
#include "hw/sysbus.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 GIC_NCPU 8
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[GIC_NCPU];
bool enabled;
bool cpu_enabled[GIC_NCPU];
gic_irq_state irq_state[GIC_MAXIRQ];
uint8_t irq_target[GIC_MAXIRQ];
uint8_t priority1[GIC_INTERNAL][GIC_NCPU];
uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
uint16_t last_active[GIC_MAXIRQ][GIC_NCPU];
uint16_t priority_mask[GIC_NCPU];
uint16_t running_irq[GIC_NCPU];
uint16_t running_priority[GIC_NCPU];
uint16_t current_pending[GIC_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[GIC_NCPU];
MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */
uint32_t num_irq;
uint32_t revision;
} GICState;
#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 {
/*< private >*/
SysBusDeviceClass parent_class;
/*< public >*/
void (*pre_save)(GICState *s);
void (*post_load)(GICState *s);
} ARMGICCommonClass;
#endif

View file

@ -0,0 +1,28 @@
/*
* ARM RealView Emulation Baseboard Interrupt Controller
*
* Copyright (c) 2006-2007 CodeSourcery.
* Written by Paul Brook
*
* This code is licensed under the GPL.
*/
#ifndef HW_INTC_REALVIEW_GIC_H
#define HW_INTC_REALVIEW_GIC_H
#include "hw/sysbus.h"
#include "hw/intc/arm_gic.h"
#define TYPE_REALVIEW_GIC "realview_gic"
#define REALVIEW_GIC(obj) \
OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC)
typedef struct RealViewGICState {
SysBusDevice parent_obj;
MemoryRegion container;
GICState gic;
} RealViewGICState;
#endif

31
include/hw/misc/a9scu.h Normal file
View file

@ -0,0 +1,31 @@
/*
* Cortex-A9MPCore Snoop Control Unit (SCU) emulation.
*
* Copyright (c) 2009 CodeSourcery.
* Copyright (c) 2011 Linaro Limited.
* Written by Paul Brook, Peter Maydell.
*
* This code is licensed under the GPL.
*/
#ifndef HW_MISC_A9SCU_H
#define HW_MISC_A9SCU_H
#include "hw/sysbus.h"
/* A9MP private memory region. */
typedef struct A9SCUState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
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)
#endif

View file

@ -0,0 +1,29 @@
/*
* 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.
*/
#ifndef HW_MISC_ARM11SCU_H
#define HW_MISC_ARM11SCU_H
#include "hw/sysbus.h"
#define TYPE_ARM11_SCU "arm11-scu"
#define ARM11_SCU(obj) OBJECT_CHECK(ARM11SCUState, (obj), TYPE_ARM11_SCU)
typedef struct ARM11SCUState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
uint32_t control;
uint32_t num_cpu;
MemoryRegion iomem;
} ARM11SCUState;
#endif

View file

@ -3,11 +3,11 @@
/* PCMCIA/Cardbus */ /* PCMCIA/Cardbus */
#include "qemu-common.h" #include "hw/qdev.h"
typedef struct { typedef struct PCMCIASocket {
qemu_irq irq; qemu_irq irq;
int attached; bool attached;
const char *slot_string; const char *slot_string;
const char *card_string; const char *card_string;
} PCMCIASocket; } PCMCIASocket;
@ -16,22 +16,42 @@ void pcmcia_socket_register(PCMCIASocket *socket);
void pcmcia_socket_unregister(PCMCIASocket *socket); void pcmcia_socket_unregister(PCMCIASocket *socket);
void pcmcia_info(Monitor *mon, const QDict *qdict); void pcmcia_info(Monitor *mon, const QDict *qdict);
#define TYPE_PCMCIA_CARD "pcmcia-card"
#define PCMCIA_CARD(obj) \
OBJECT_CHECK(PCMCIACardState, (obj), TYPE_PCMCIA_CARD)
#define PCMCIA_CARD_GET_CLASS(obj) \
OBJECT_GET_CLASS(PCMCIACardClass, obj, TYPE_PCMCIA_CARD)
#define PCMCIA_CARD_CLASS(cls) \
OBJECT_CLASS_CHECK(PCMCIACardClass, cls, TYPE_PCMCIA_CARD)
struct PCMCIACardState { struct PCMCIACardState {
void *state; /*< private >*/
DeviceState parent_obj;
/*< public >*/
PCMCIASocket *slot; PCMCIASocket *slot;
int (*attach)(void *state); };
int (*detach)(void *state);
typedef struct PCMCIACardClass {
/*< private >*/
DeviceClass parent_class;
/*< public >*/
int (*attach)(PCMCIACardState *state);
int (*detach)(PCMCIACardState *state);
const uint8_t *cis; const uint8_t *cis;
int cis_len; int cis_len;
/* Only valid if attached */ /* Only valid if attached */
uint8_t (*attr_read)(void *state, uint32_t address); uint8_t (*attr_read)(PCMCIACardState *card, uint32_t address);
void (*attr_write)(void *state, uint32_t address, uint8_t value); void (*attr_write)(PCMCIACardState *card, uint32_t address, uint8_t value);
uint16_t (*common_read)(void *state, uint32_t address); uint16_t (*common_read)(PCMCIACardState *card, uint32_t address);
void (*common_write)(void *state, uint32_t address, uint16_t value); void (*common_write)(PCMCIACardState *card,
uint16_t (*io_read)(void *state, uint32_t address); uint32_t address, uint16_t value);
void (*io_write)(void *state, uint32_t address, uint16_t value); uint16_t (*io_read)(PCMCIACardState *card, uint32_t address);
}; void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value);
} PCMCIACardClass;
#define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */ #define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */
#define CISTPL_NO_LINK 0x14 /* No Link Tuple */ #define CISTPL_NO_LINK 0x14 /* No Link Tuple */

View file

@ -221,7 +221,6 @@ void qdev_init_nofail(DeviceState *dev);
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
int required_for_version); int required_for_version);
void qdev_unplug(DeviceState *dev, Error **errp); void qdev_unplug(DeviceState *dev, Error **errp);
void qdev_free(DeviceState *dev);
int qdev_simple_unplug_cb(DeviceState *dev); int qdev_simple_unplug_cb(DeviceState *dev);
void qdev_machine_creation_done(void); void qdev_machine_creation_done(void);
bool qdev_machine_modified(void); bool qdev_machine_modified(void);

View file

@ -0,0 +1,54 @@
/*
* Private peripheral timer/watchdog blocks for ARM 11MPCore and A9MP
*
* Copyright (c) 2006-2007 CodeSourcery.
* Copyright (c) 2011 Linaro Limited
* Written by Paul Brook, Peter Maydell
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HW_TIMER_ARM_MPTIMER_H
#define HW_TIMER_ARM_MPTIMER_H
#include "hw/sysbus.h"
#define ARM_MPTIMER_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[ARM_MPTIMER_MAX_CPUS];
MemoryRegion iomem;
} ARMMPTimerState;
#endif

View file

@ -794,27 +794,6 @@ void object_property_add(Object *obj, const char *name, const char *type,
void object_property_del(Object *obj, const char *name, Error **errp); void object_property_del(Object *obj, const char *name, Error **errp);
/**
* object_property_add_uint8_ptr:
* object_property_add_uint16_ptr:
* object_property_add_uint32_ptr:
* object_property_add_uint64_ptr:
* @obj: the object to add a property to
* @name: the name of the property
* @v: pointer to value
*
* Add an integer property in memory. This function will add a
* property of the appropriate type.
*/
void object_property_add_uint8_ptr(Object *obj, const char *name,
const uint8_t *v, Error **errp);
void object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v, Error **errp);
void object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v, Error **errp);
void object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v, Error **Errp);
/** /**
* object_property_find: * object_property_find:
* @obj: the object * @obj: the object
@ -1133,6 +1112,58 @@ void object_property_add_bool(Object *obj, const char *name,
void (*set)(Object *, bool, Error **), void (*set)(Object *, bool, Error **),
Error **errp); Error **errp);
/**
* object_property_add_uint8_ptr:
* @obj: the object to add a property to
* @name: the name of the property
* @v: pointer to value
* @errp: if an error occurs, a pointer to an area to store the error
*
* Add an integer property in memory. This function will add a
* property of type 'uint8'.
*/
void object_property_add_uint8_ptr(Object *obj, const char *name,
const uint8_t *v, Error **errp);
/**
* object_property_add_uint16_ptr:
* @obj: the object to add a property to
* @name: the name of the property
* @v: pointer to value
* @errp: if an error occurs, a pointer to an area to store the error
*
* Add an integer property in memory. This function will add a
* property of type 'uint16'.
*/
void object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v, Error **errp);
/**
* object_property_add_uint32_ptr:
* @obj: the object to add a property to
* @name: the name of the property
* @v: pointer to value
* @errp: if an error occurs, a pointer to an area to store the error
*
* Add an integer property in memory. This function will add a
* property of type 'uint32'.
*/
void object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v, Error **errp);
/**
* object_property_add_uint64_ptr:
* @obj: the object to add a property to
* @name: the name of the property
* @v: pointer to value
* @errp: if an error occurs, a pointer to an area to store the error
*
* Add an integer property in memory. This function will add a
* property of type 'uint64'.
*/
void object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v, Error **Errp);
/** /**
* object_child_foreach: * object_child_foreach:
* @obj: the object whose children will be navigated * @obj: the object whose children will be navigated

View file

@ -453,11 +453,12 @@ static BusState *qbus_find(const char *path)
DeviceState *qdev_device_add(QemuOpts *opts) DeviceState *qdev_device_add(QemuOpts *opts)
{ {
ObjectClass *obj; ObjectClass *oc;
DeviceClass *k; DeviceClass *dc;
const char *driver, *path, *id; const char *driver, *path, *id;
DeviceState *qdev; DeviceState *dev;
BusState *bus = NULL; BusState *bus = NULL;
Error *err = NULL;
driver = qemu_opt_get(opts, "driver"); driver = qemu_opt_get(opts, "driver");
if (!driver) { if (!driver) {
@ -466,22 +467,28 @@ DeviceState *qdev_device_add(QemuOpts *opts)
} }
/* find driver */ /* find driver */
obj = object_class_by_name(driver); oc = object_class_by_name(driver);
if (!obj) { if (!oc) {
const char *typename = find_typename_by_alias(driver); const char *typename = find_typename_by_alias(driver);
if (typename) { if (typename) {
driver = typename; driver = typename;
obj = object_class_by_name(driver); oc = object_class_by_name(driver);
} }
} }
if (!obj) { if (!oc) {
qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type"); qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
return NULL; return NULL;
} }
k = DEVICE_CLASS(obj); if (object_class_is_abstract(oc)) {
qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver",
"non-abstract device type");
return NULL;
}
dc = DEVICE_CLASS(oc);
/* find bus */ /* find bus */
path = qemu_opt_get(opts, "bus"); path = qemu_opt_get(opts, "bus");
@ -490,16 +497,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
if (!bus) { if (!bus) {
return NULL; return NULL;
} }
if (!object_dynamic_cast(OBJECT(bus), k->bus_type)) { if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
qerror_report(QERR_BAD_BUS_FOR_DEVICE, qerror_report(QERR_BAD_BUS_FOR_DEVICE,
driver, object_get_typename(OBJECT(bus))); driver, object_get_typename(OBJECT(bus)));
return NULL; return NULL;
} }
} else if (k->bus_type != NULL) { } else if (dc->bus_type != NULL) {
bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type); bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
if (!bus) { if (!bus) {
qerror_report(QERR_NO_BUS_FOR_DEVICE, qerror_report(QERR_NO_BUS_FOR_DEVICE,
k->bus_type, driver); dc->bus_type, driver);
return NULL; return NULL;
} }
} }
@ -509,36 +516,42 @@ DeviceState *qdev_device_add(QemuOpts *opts)
} }
/* create device, set properties */ /* create device, set properties */
qdev = DEVICE(object_new(driver)); dev = DEVICE(object_new(driver));
if (bus) { if (bus) {
qdev_set_parent_bus(qdev, bus); qdev_set_parent_bus(dev, bus);
} }
id = qemu_opts_id(opts); id = qemu_opts_id(opts);
if (id) { if (id) {
qdev->id = id; dev->id = id;
} }
if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) { if (qemu_opt_foreach(opts, set_property, dev, 1) != 0) {
qdev_free(qdev); object_unparent(OBJECT(dev));
object_unref(OBJECT(dev));
return NULL; return NULL;
} }
if (qdev->id) { if (dev->id) {
object_property_add_child(qdev_get_peripheral(), qdev->id, object_property_add_child(qdev_get_peripheral(), dev->id,
OBJECT(qdev), NULL); OBJECT(dev), NULL);
} else { } else {
static int anon_count; static int anon_count;
gchar *name = g_strdup_printf("device[%d]", anon_count++); gchar *name = g_strdup_printf("device[%d]", anon_count++);
object_property_add_child(qdev_get_peripheral_anon(), name, object_property_add_child(qdev_get_peripheral_anon(), name,
OBJECT(qdev), NULL); OBJECT(dev), NULL);
g_free(name); g_free(name);
} }
if (qdev_init(qdev) < 0) { object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err != NULL) {
qerror_report_err(err);
error_free(err);
object_unparent(OBJECT(dev));
object_unref(OBJECT(dev));
qerror_report(QERR_DEVICE_INIT_FAILED, driver); qerror_report(QERR_DEVICE_INIT_FAILED, driver);
return NULL; return NULL;
} }
qdev->opts = opts; dev->opts = opts;
return qdev; return dev;
} }

View file

@ -67,25 +67,50 @@ check-qtest-i386-y += tests/boot-order-test$(EXESUF)
check-qtest-i386-y += tests/rtc-test$(EXESUF) check-qtest-i386-y += tests/rtc-test$(EXESUF)
check-qtest-i386-y += tests/i440fx-test$(EXESUF) check-qtest-i386-y += tests/i440fx-test$(EXESUF)
check-qtest-i386-y += tests/fw_cfg-test$(EXESUF) check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
check-qtest-i386-y += tests/qom-test$(EXESUF)
check-qtest-x86_64-y = $(check-qtest-i386-y) check-qtest-x86_64-y = $(check-qtest-i386-y)
gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c
gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y)) gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
check-qtest-mips-y = tests/endianness-test$(EXESUF) check-qtest-mips-y = tests/endianness-test$(EXESUF)
check-qtest-mips64-y = tests/endianness-test$(EXESUF) check-qtest-mips64-y = tests/endianness-test$(EXESUF)
check-qtest-mips64el-y = tests/endianness-test$(EXESUF) check-qtest-mips64el-y = tests/endianness-test$(EXESUF)
check-qtest-mips-y += tests/qom-test$(EXESUF)
check-qtest-mipsel-y += tests/qom-test$(EXESUF)
check-qtest-mips64-y += tests/qom-test$(EXESUF)
check-qtest-mips64el-y += tests/qom-test$(EXESUF)
check-qtest-ppc-y = tests/endianness-test$(EXESUF) check-qtest-ppc-y = tests/endianness-test$(EXESUF)
check-qtest-ppc64-y = tests/endianness-test$(EXESUF) check-qtest-ppc64-y = tests/endianness-test$(EXESUF)
check-qtest-sh4-y = tests/endianness-test$(EXESUF) check-qtest-sh4-y = tests/endianness-test$(EXESUF)
check-qtest-sh4eb-y = tests/endianness-test$(EXESUF) check-qtest-sh4eb-y = tests/endianness-test$(EXESUF)
check-qtest-sh4-y += tests/qom-test$(EXESUF)
check-qtest-sh4eb-y += tests/qom-test$(EXESUF)
check-qtest-sparc64-y = tests/endianness-test$(EXESUF) check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
#check-qtest-sparc-y = tests/m48t59-test$(EXESUF) #check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
#check-qtest-sparc64-y += tests/m48t59-test$(EXESUF) #check-qtest-sparc64-y += tests/m48t59-test$(EXESUF)
gcov-files-sparc-y += hw/m48t59.c gcov-files-sparc-y += hw/m48t59.c
gcov-files-sparc64-y += hw/m48t59.c gcov-files-sparc64-y += hw/m48t59.c
check-qtest-sparc-y += tests/qom-test$(EXESUF)
check-qtest-sparc64-y += tests/qom-test$(EXESUF)
check-qtest-arm-y = tests/tmp105-test$(EXESUF) check-qtest-arm-y = tests/tmp105-test$(EXESUF)
gcov-files-arm-y += hw/tmp105.c gcov-files-arm-y += hw/tmp105.c
check-qtest-arm-y += tests/qom-test$(EXESUF)
check-qtest-ppc-y += tests/boot-order-test$(EXESUF) check-qtest-ppc-y += tests/boot-order-test$(EXESUF)
check-qtest-ppc64-y += tests/boot-order-test$(EXESUF) check-qtest-ppc64-y += tests/boot-order-test$(EXESUF)
check-qtest-ppc-y += tests/qom-test$(EXESUF)
check-qtest-ppc64-y += tests/qom-test$(EXESUF)
check-qtest-ppcemb-y += tests/qom-test$(EXESUF)
check-qtest-alpha-y += tests/qom-test$(EXESUF)
check-qtest-cris-y += tests/qom-test$(EXESUF)
check-qtest-lm32-y += tests/qom-test$(EXESUF)
check-qtest-m68k-y += tests/qom-test$(EXESUF)
check-qtest-microblaze-y += tests/qom-test$(EXESUF)
check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
check-qtest-moxie-y += tests/qom-test$(EXESUF)
check-qtest-or32-y += tests/qom-test$(EXESUF)
check-qtest-s390x-y += tests/qom-test$(EXESUF)
check-qtest-unicore32-y += tests/qom-test$(EXESUF)
check-qtest-xtensa-y += tests/qom-test$(EXESUF)
check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
check-qapi-schema-y := $(addprefix tests/qapi-schema/, \ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
comments.json empty.json funny-char.json indented-expr.json \ comments.json empty.json funny-char.json indented-expr.json \
@ -174,6 +199,7 @@ tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
tests/qom-test$(EXESUF): tests/qom-test.o
tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
# QTest rules # QTest rules

253
tests/qom-test.c Normal file
View file

@ -0,0 +1,253 @@
/*
* QTest testcase for QOM
*
* Copyright (c) 2013 SUSE LINUX Products GmbH
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "libqtest.h"
#include <glib.h>
#include <string.h>
#include "qemu/osdep.h"
static void test_nop(gconstpointer data)
{
QTestState *s;
const char *machine = data;
char *args;
args = g_strdup_printf("-display none -machine %s", machine);
s = qtest_start(args);
if (s) {
qtest_quit(s);
}
g_free(args);
}
static const char *x86_machines[] = {
"pc",
"isapc",
"q35",
};
static const char *alpha_machines[] = {
"clipper",
};
static const char *arm_machines[] = {
"integratorcp",
"versatilepb",
"versatileab",
"lm3s811evb",
"lm3s6965evb",
"collie",
"akita",
"spitz",
"borzoi",
"terrier",
"tosa",
"cheetah",
"sx1-v1",
"sx1",
"realview-eb",
"realview-eb-mpcore",
"realview-pb-a8",
"realview-pbx-a9",
"musicpal",
"mainstone",
"connex",
"verdex",
"z2",
"n800",
"n810",
"kzm",
"vexpress-a9",
"vexpress-a15",
"smdkc210",
"nuri",
"xilinx-zynq-a9",
"highbank",
"midway",
};
static const char *cris_machines[] = {
"axis-dev88",
};
static const char *lm32_machines[] = {
"lm32-evr",
"lm32-uclinux",
"milkymist",
};
static const char *m68k_machines[] = {
"mcf5208evb",
"an5206",
"dummy",
};
static const char *microblaze_machines[] = {
"petalogix-ml605",
"petalogix-s3adsp1800",
};
static const char *mips_machines[] = {
"malta",
"magnum",
"mips",
"mipssim",
"pica61",
};
static const char *moxie_machines[] = {
"moxiesim",
};
static const char *openrisc_machines[] = {
"or32-sim",
};
static const char *ppc_machines[] = {
"g3beige",
"mac99",
"prep",
"mpc8544ds",
"ppce500",
};
static const char *ppc64_machines[] = {
"pseries",
};
static const char *ppc405_machines[] = {
"ref405ep",
"taihu",
};
static const char *ppc440_machines[] = {
"bamboo",
"virtex-ml507",
};
static const char *s390_machines[] = {
"s390-virtio",
"s390-ccw-virtio",
};
static const char *superh_machines[] = {
"r2d",
"shix",
};
static const char *sparc_machines[] = {
"SS-4",
"SS-5",
"SS-10",
"SS-20",
"SS-600MP",
"LX",
"SPARCClassic",
"SPARCbook",
"leon3_generic",
};
static const char *sparc64_machines[] = {
"sun4u",
"sun4v",
"Niagara",
};
static const char *unicore32_machines[] = {
"puv3",
};
static const char *xtensa_machines[] = {
"sim",
"lx60",
"lx200",
};
static void add_test_cases(const char *arch, const char *machine)
{
char *path;
path = g_strdup_printf("/%s/qom/%s", arch, machine);
g_test_add_data_func(path, machine, test_nop);
}
#define ADD_MACHINE_TESTS(arch, array) do { \
int i; \
for (i = 0; i < ARRAY_SIZE(array); i++) { \
add_test_cases((arch), (array)[i]); \
} \
} while (false)
int main(int argc, char **argv)
{
const char *arch = qtest_get_arch();
g_test_init(&argc, &argv, NULL);
add_test_cases(arch, "none");
if (strcmp(arch, "i386") == 0 ||
strcmp(arch, "x86_64") == 0) {
ADD_MACHINE_TESTS(arch, x86_machines);
} else if (strcmp(arch, "alpha") == 0) {
ADD_MACHINE_TESTS(arch, alpha_machines);
} else if (strcmp(arch, "arm") == 0) {
ADD_MACHINE_TESTS(arch, arm_machines);
} else if (strcmp(arch, "cris") == 0) {
ADD_MACHINE_TESTS(arch, cris_machines);
} else if (strcmp(arch, "lm32") == 0) {
ADD_MACHINE_TESTS(arch, lm32_machines);
} else if (strcmp(arch, "m68k") == 0) {
ADD_MACHINE_TESTS(arch, m68k_machines);
} else if (strcmp(arch, "microblaze") == 0 ||
strcmp(arch, "microblazeel") == 0) {
ADD_MACHINE_TESTS(arch, microblaze_machines);
} else if (strcmp(arch, "mips") == 0 ||
strcmp(arch, "mipsel") == 0 ||
strcmp(arch, "mips64") == 0) {
ADD_MACHINE_TESTS(arch, mips_machines);
} else if (strcmp(arch, "mips64el") == 0) {
ADD_MACHINE_TESTS(arch, mips_machines);
add_test_cases(arch, "fulong2e");
} else if (strcmp(arch, "moxie") == 0) {
ADD_MACHINE_TESTS(arch, moxie_machines);
} else if (strcmp(arch, "or32") == 0) {
ADD_MACHINE_TESTS(arch, openrisc_machines);
} else if (strcmp(arch, "ppcemb") == 0) {
#if 0
/* XXX Available in ppcemb but don't work */
ADD_MACHINE_TESTS(arch, ppc405_machines);
#endif
ADD_MACHINE_TESTS(arch, ppc440_machines);
} else if (strcmp(arch, "ppc") == 0) {
ADD_MACHINE_TESTS(arch, ppc405_machines);
ADD_MACHINE_TESTS(arch, ppc440_machines);
ADD_MACHINE_TESTS(arch, ppc_machines);
} else if (strcmp(arch, "ppc64") == 0) {
ADD_MACHINE_TESTS(arch, ppc405_machines);
ADD_MACHINE_TESTS(arch, ppc440_machines);
ADD_MACHINE_TESTS(arch, ppc_machines);
ADD_MACHINE_TESTS(arch, ppc64_machines);
} else if (strcmp(arch, "s390x") == 0) {
ADD_MACHINE_TESTS(arch, s390_machines);
} else if (strcmp(arch, "sh4") == 0 ||
strcmp(arch, "sh4eb") == 0) {
ADD_MACHINE_TESTS(arch, superh_machines);
} else if (strcmp(arch, "sparc") == 0) {
ADD_MACHINE_TESTS(arch, sparc_machines);
} else if (strcmp(arch, "sparc64") == 0) {
ADD_MACHINE_TESTS(arch, sparc64_machines);
} else if (strcmp(arch, "unicore32") == 0) {
ADD_MACHINE_TESTS(arch, unicore32_machines);
} else if (strcmp(arch, "xtensa") == 0 ||
strcmp(arch, "xtensaeb") == 0) {
ADD_MACHINE_TESTS(arch, xtensa_machines);
}
return g_test_run();
}