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_XILINX_SPIPS=y
CONFIG_ARM11SCU=y
CONFIG_A9SCU=y
CONFIG_MARVELL_88W8618=y
CONFIG_OMAP=y

View File

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

View File

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

View File

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

View File

@ -22,6 +22,7 @@
*/
#include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "hw/sysbus.h"
#include "net/net.h"
#include "hw/arm/arm.h"
@ -96,7 +97,7 @@ static void lan9215_init(uint32_t base, qemu_irq irq)
static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
Exynos4BoardType board_type)
{
if (smp_cpus != EXYNOS4210_NCPUS) {
if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) {
fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
" value.\n",
exynos4_machines[board_type].name,

View File

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

View File

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

View File

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

View File

@ -19,6 +19,7 @@
#include "hw/hw.h"
#include "audio/audio.h"
#include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "ui/console.h"
#include "hw/arm/omap.h"
#include "hw/boards.h"
@ -255,7 +256,7 @@ static void palmte_init(QEMUMachineInitArgs *args)
}
}
if (!rom_loaded && !kernel_filename) {
if (!rom_loaded && !kernel_filename && !qtest_enabled()) {
fprintf(stderr, "Kernel or ROM image must be specified\n");
exit(1);
}

View File

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

View File

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

View File

@ -195,22 +195,26 @@ static void milkymist_uart_reset(DeviceState *d)
s->regs[R_STAT] = STAT_THRE;
}
static int milkymist_uart_init(SysBusDevice *dev)
static void milkymist_uart_realize(DeviceState *dev, Error **errp)
{
MilkymistUartState *s = MILKYMIST_UART(dev);
sysbus_init_irq(dev, &s->irq);
memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
"milkymist-uart", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region);
s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
}
return 0;
static void milkymist_uart_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
MilkymistUartState *s = MILKYMIST_UART(obj);
sysbus_init_irq(sbd, &s->irq);
memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
"milkymist-uart", R_MAX * 4);
sysbus_init_mmio(sbd, &s->regs_region);
}
static const VMStateDescription vmstate_milkymist_uart = {
@ -227,9 +231,8 @@ static const VMStateDescription vmstate_milkymist_uart = {
static void milkymist_uart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = milkymist_uart_init;
dc->realize = milkymist_uart_realize;
dc->reset = milkymist_uart_reset;
dc->vmsd = &vmstate_milkymist_uart;
}
@ -238,6 +241,7 @@ static const TypeInfo milkymist_uart_info = {
.name = TYPE_MILKYMIST_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistUartState),
.instance_init = milkymist_uart_init,
.class_init = milkymist_uart_class_init,
};

View File

@ -164,7 +164,7 @@ int qdev_init(DeviceState *dev)
if (local_err != NULL) {
qerror_report_err(local_err);
error_free(local_err);
qdev_free(dev);
object_unparent(OBJECT(dev));
return -1;
}
return 0;
@ -258,7 +258,7 @@ void qbus_reset_all_fn(void *opaque)
int qdev_simple_unplug_cb(DeviceState *dev)
{
/* just zap it */
qdev_free(dev);
object_unparent(OBJECT(dev));
return 0;
}
@ -280,12 +280,6 @@ void qdev_init_nofail(DeviceState *dev)
}
}
/* Unlink device from bus and free the structure. */
void qdev_free(DeviceState *dev)
{
object_unparent(OBJECT(dev));
}
void qdev_machine_creation_done(void)
{
/*
@ -458,7 +452,7 @@ static void bus_unparent(Object *obj)
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
DeviceState *dev = kid->child;
qdev_free(dev);
object_unparent(OBJECT(dev));
}
if (bus->parent) {
QLIST_REMOVE(bus, sibling);

View File

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

View File

@ -18,55 +18,60 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "hw/sysbus.h"
#include "hw/cpu/a15mpcore.h"
#include "sysemu/kvm.h"
/* A15MP private memory region. */
#define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
#define A15MPCORE_PRIV(obj) \
OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV)
typedef struct A15MPPrivState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
uint32_t num_cpu;
uint32_t num_irq;
MemoryRegion container;
DeviceState *gic;
} A15MPPrivState;
static void a15mp_priv_set_irq(void *opaque, int irq, int level)
{
A15MPPrivState *s = (A15MPPrivState *)opaque;
qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
}
static int a15mp_priv_init(SysBusDevice *dev)
static void a15mp_priv_initfn(Object *obj)
{
A15MPPrivState *s = A15MPCORE_PRIV(dev);
SysBusDevice *busdev;
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
A15MPPrivState *s = A15MPCORE_PRIV(obj);
DeviceState *gicdev;
const char *gictype = "arm_gic";
int i;
if (kvm_irqchip_in_kernel()) {
gictype = "kvm-arm-gic";
}
s->gic = qdev_create(NULL, gictype);
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
qdev_prop_set_uint32(s->gic, "revision", 2);
qdev_init_nofail(s->gic);
busdev = SYS_BUS_DEVICE(s->gic);
memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000);
sysbus_init_mmio(sbd, &s->container);
object_initialize(&s->gic, sizeof(s->gic), gictype);
gicdev = DEVICE(&s->gic);
qdev_set_parent_bus(gicdev, sysbus_get_default());
qdev_prop_set_uint32(gicdev, "revision", 2);
}
static void a15mp_priv_realize(DeviceState *dev, Error **errp)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
A15MPPrivState *s = A15MPCORE_PRIV(dev);
DeviceState *gicdev;
SysBusDevice *busdev;
int i;
Error *err = NULL;
gicdev = DEVICE(&s->gic);
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
busdev = SYS_BUS_DEVICE(&s->gic);
/* Pass through outbound IRQ lines from the GIC */
sysbus_pass_irq(dev, busdev);
sysbus_pass_irq(sbd, busdev);
/* Pass through inbound GPIO lines to the GIC */
qdev_init_gpio_in(DEVICE(dev), a15mp_priv_set_irq, s->num_irq - 32);
qdev_init_gpio_in(dev, a15mp_priv_set_irq, s->num_irq - 32);
/* Wire the outputs from each CPU's generic timer to the
* appropriate GIC PPI inputs
@ -78,10 +83,10 @@ static int a15mp_priv_init(SysBusDevice *dev)
* since a real A15 always has TrustZone but QEMU doesn't.
*/
qdev_connect_gpio_out(cpudev, 0,
qdev_get_gpio_in(s->gic, ppibase + 30));
qdev_get_gpio_in(gicdev, ppibase + 30));
/* virtual timer */
qdev_connect_gpio_out(cpudev, 1,
qdev_get_gpio_in(s->gic, ppibase + 27));
qdev_get_gpio_in(gicdev, ppibase + 27));
}
/* Memory map (addresses are offsets from PERIPHBASE):
@ -92,15 +97,10 @@ static int a15mp_priv_init(SysBusDevice *dev)
* 0x5000-0x5fff -- GIC virtual interface control (not modelled)
* 0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
*/
memory_region_init(&s->container, OBJECT(s),
"a15mp-priv-container", 0x8000);
memory_region_add_subregion(&s->container, 0x1000,
sysbus_mmio_get_region(busdev, 0));
memory_region_add_subregion(&s->container, 0x2000,
sysbus_mmio_get_region(busdev, 1));
sysbus_init_mmio(dev, &s->container);
return 0;
}
static Property a15mp_priv_properties[] = {
@ -118,8 +118,8 @@ static Property a15mp_priv_properties[] = {
static void a15mp_priv_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = a15mp_priv_init;
dc->realize = a15mp_priv_realize;
dc->props = a15mp_priv_properties;
/* We currently have no savable state */
}
@ -128,6 +128,7 @@ static const TypeInfo a15mp_priv_info = {
.name = TYPE_A15MPCORE_PRIV,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(A15MPPrivState),
.instance_init = a15mp_priv_initfn,
.class_init = a15mp_priv_class_init,
};

View File

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

View File

@ -7,96 +7,28 @@
* This code is licensed under the GPL.
*/
#include "hw/sysbus.h"
#include "qemu/timer.h"
#include "hw/cpu/arm11mpcore.h"
#include "hw/intc/realview_gic.h"
/* MPCore private memory region. */
#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv"
#define ARM11MPCORE_PRIV(obj) \
OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV)
typedef struct ARM11MPCorePriveState {
SysBusDevice parent_obj;
uint32_t scu_control;
int iomemtype;
uint32_t old_timer_status[8];
uint32_t num_cpu;
MemoryRegion iomem;
MemoryRegion container;
DeviceState *mptimer;
DeviceState *wdtimer;
DeviceState *gic;
uint32_t num_irq;
} ARM11MPCorePriveState;
/* Per-CPU private memory mapped IO. */
static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
unsigned size)
{
ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
int id;
/* SCU */
switch (offset) {
case 0x00: /* Control. */
return s->scu_control;
case 0x04: /* Configuration. */
id = ((1 << s->num_cpu) - 1) << 4;
return id | (s->num_cpu - 1);
case 0x08: /* CPU status. */
return 0;
case 0x0c: /* Invalidate all. */
return 0;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"mpcore_priv_read: Bad offset %x\n", (int)offset);
return 0;
}
}
static void mpcore_scu_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
/* SCU */
switch (offset) {
case 0: /* Control register. */
s->scu_control = value & 1;
break;
case 0x0c: /* Invalidate all. */
/* This is a no-op as cache is not emulated. */
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"mpcore_priv_read: Bad offset %x\n", (int)offset);
}
}
static const MemoryRegionOps mpcore_scu_ops = {
.read = mpcore_scu_read,
.write = mpcore_scu_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void mpcore_priv_set_irq(void *opaque, int irq, int level)
{
ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
}
static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
{
int i;
SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic);
SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer);
SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer);
memory_region_init(&s->container, OBJECT(s),
"mpcode-priv-container", 0x2000);
memory_region_init_io(&s->iomem, OBJECT(s),
&mpcore_scu_ops, s, "mpcore-scu", 0x100);
memory_region_add_subregion(&s->container, 0, &s->iomem);
SysBusDevice *scubusdev = SYS_BUS_DEVICE(&s->scu);
DeviceState *gicdev = DEVICE(&s->gic);
SysBusDevice *gicbusdev = SYS_BUS_DEVICE(&s->gic);
SysBusDevice *timerbusdev = SYS_BUS_DEVICE(&s->mptimer);
SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(&s->wdtimer);
memory_region_add_subregion(&s->container, 0,
sysbus_mmio_get_region(scubusdev, 0));
/* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
* at 0x200, 0x300...
*/
@ -124,134 +56,84 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
for (i = 0; i < s->num_cpu; i++) {
int ppibase = (s->num_irq - 32) + i * 32;
sysbus_connect_irq(timerbusdev, i,
qdev_get_gpio_in(s->gic, ppibase + 29));
qdev_get_gpio_in(gicdev, ppibase + 29));
sysbus_connect_irq(wdtbusdev, i,
qdev_get_gpio_in(s->gic, ppibase + 30));
qdev_get_gpio_in(gicdev, ppibase + 30));
}
}
static int mpcore_priv_init(SysBusDevice *sbd)
static void mpcore_priv_realize(DeviceState *dev, Error **errp)
{
DeviceState *dev = DEVICE(sbd);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(dev);
DeviceState *scudev = DEVICE(&s->scu);
DeviceState *gicdev = DEVICE(&s->gic);
DeviceState *mptimerdev = DEVICE(&s->mptimer);
DeviceState *wdtimerdev = DEVICE(&s->wdtimer);
Error *err = NULL;
s->gic = qdev_create(NULL, "arm_gic");
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
/* Request the legacy 11MPCore GIC behaviour: */
qdev_prop_set_uint32(s->gic, "revision", 0);
qdev_init_nofail(s->gic);
qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
/* Pass through outbound IRQ lines from the GIC */
sysbus_pass_irq(sbd, SYS_BUS_DEVICE(s->gic));
sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->gic));
/* Pass through inbound GPIO lines to the GIC */
qdev_init_gpio_in(dev, mpcore_priv_set_irq, s->num_irq - 32);
s->mptimer = qdev_create(NULL, "arm_mptimer");
qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
qdev_init_nofail(s->mptimer);
qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu);
object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
s->wdtimer = qdev_create(NULL, "arm_mptimer");
qdev_prop_set_uint32(s->wdtimer, "num-cpu", s->num_cpu);
qdev_init_nofail(s->wdtimer);
qdev_prop_set_uint32(wdtimerdev, "num-cpu", s->num_cpu);
object_property_set_bool(OBJECT(&s->wdtimer), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
mpcore_priv_map_setup(s);
}
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);
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[] = {
DEFINE_PROP_UINT32("num-cpu", ARM11MPCorePriveState, num_cpu, 1),
/* The ARM11 MPCORE TRM says the on-chip controller may have
@ -269,9 +151,8 @@ static Property mpcore_priv_properties[] = {
static void mpcore_priv_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = mpcore_priv_init;
dc->realize = mpcore_priv_realize;
dc->props = mpcore_priv_properties;
}
@ -279,12 +160,12 @@ static const TypeInfo mpcore_priv_info = {
.name = TYPE_ARM11MPCORE_PRIV,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ARM11MPCorePriveState),
.instance_init = mpcore_priv_initfn,
.class_init = mpcore_priv_class_init,
};
static void arm11mpcore_register_types(void)
{
type_register_static(&mpcore_rirq_info);
type_register_static(&mpcore_priv_info);
}

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

View File

@ -2215,55 +2215,6 @@ void ide_init2(IDEBus *bus, qemu_irq irq)
bus->dma = &ide_dma_nop;
}
/* TODO convert users to qdev and remove */
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
DriveInfo *hd1, qemu_irq irq)
{
int i, trans;
DriveInfo *dinfo;
uint32_t cyls, heads, secs;
for(i = 0; i < 2; i++) {
dinfo = i == 0 ? hd0 : hd1;
ide_init1(bus, i);
if (dinfo) {
cyls = dinfo->cyls;
heads = dinfo->heads;
secs = dinfo->secs;
trans = dinfo->trans;
if (!cyls && !heads && !secs) {
hd_geometry_guess(dinfo->bdrv, &cyls, &heads, &secs, &trans);
} else if (trans == BIOS_ATA_TRANSLATION_AUTO) {
trans = hd_bios_chs_auto_trans(cyls, heads, secs);
}
if (cyls < 1 || cyls > 65535) {
error_report("cyls must be between 1 and 65535");
exit(1);
}
if (heads < 1 || heads > 16) {
error_report("heads must be between 1 and 16");
exit(1);
}
if (secs < 1 || secs > 255) {
error_report("secs must be between 1 and 255");
exit(1);
}
if (ide_init_drive(&bus->ifs[i], dinfo->bdrv,
dinfo->media_cd ? IDE_CD : IDE_HD,
NULL, dinfo->serial, NULL, 0,
cyls, heads, secs, trans) < 0) {
error_report("Can't set up IDE drive %s", dinfo->id);
exit(1);
}
bdrv_attach_dev_nofail(dinfo->bdrv, &bus->ifs[i]);
} else {
ide_reset(&bus->ifs[i]);
}
}
bus->irq = irq;
bus->dma = &ide_dma_nop;
}
static const MemoryRegionPortio ide_portio_list[] = {
{ 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write },
{ 0, 2, 2, .read = ide_data_readw, .write = ide_data_writew },

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,
int chs_trans);
void ide_init2(IDEBus *bus, qemu_irq irq);
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
DriveInfo *hd1, qemu_irq irq);
void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
void ide_exec_cmd(IDEBus *bus, uint32_t val);

View File

@ -30,15 +30,22 @@
#include <hw/ide/internal.h>
#define TYPE_MICRODRIVE "microdrive"
#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE)
/***********************************************************/
/* CF-ATA Microdrive */
#define METADATA_SIZE 0x20
/* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface. */
typedef struct {
typedef struct MicroDriveState {
/*< private >*/
PCMCIACardState parent_obj;
/*< public >*/
IDEBus bus;
PCMCIACardState card;
uint32_t attr_base;
uint32_t io_base;
@ -81,10 +88,13 @@ enum md_ctrl {
static inline void md_interrupt_update(MicroDriveState *s)
{
if (!s->card.slot)
return;
PCMCIACardState *card = PCMCIA_CARD(s);
qemu_set_irq(s->card.slot->irq,
if (card->slot == NULL) {
return;
}
qemu_set_irq(card->slot->irq,
!(s->stat & STAT_INT) && /* Inverted */
!(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
!(s->opt & OPT_SRESET));
@ -93,16 +103,20 @@ static inline void md_interrupt_update(MicroDriveState *s)
static void md_set_irq(void *opaque, int irq, int level)
{
MicroDriveState *s = opaque;
if (level)
if (level) {
s->stat |= STAT_INT;
else
} else {
s->stat &= ~STAT_INT;
}
md_interrupt_update(s);
}
static void md_reset(MicroDriveState *s)
static void md_reset(DeviceState *dev)
{
MicroDriveState *s = MICRODRIVE(dev);
s->opt = OPT_MODE_MMAP;
s->stat = 0;
s->pins = 0;
@ -111,14 +125,17 @@ static void md_reset(MicroDriveState *s)
ide_bus_reset(&s->bus);
}
static uint8_t md_attr_read(void *opaque, uint32_t at)
static uint8_t md_attr_read(PCMCIACardState *card, uint32_t at)
{
MicroDriveState *s = opaque;
MicroDriveState *s = MICRODRIVE(card);
PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
if (at < s->attr_base) {
if (at < s->card.cis_len)
return s->card.cis[at];
else
if (at < pcc->cis_len) {
return pcc->cis[at];
} else {
return 0x00;
}
}
at -= s->attr_base;
@ -127,10 +144,11 @@ static uint8_t md_attr_read(void *opaque, uint32_t at)
case 0x00: /* Configuration Option Register */
return s->opt;
case 0x02: /* Card Configuration Status Register */
if (s->ctrl & CTRL_IEN)
if (s->ctrl & CTRL_IEN) {
return s->stat & ~STAT_INT;
else
} else {
return s->stat;
}
case 0x04: /* Pin Replacement Register */
return (s->pins & PINS_CRDY) | 0x0c;
case 0x06: /* Socket and Copy Register */
@ -144,21 +162,24 @@ static uint8_t md_attr_read(void *opaque, uint32_t at)
return 0;
}
static void md_attr_write(void *opaque, uint32_t at, uint8_t value)
static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
{
MicroDriveState *s = opaque;
MicroDriveState *s = MICRODRIVE(card);
at -= s->attr_base;
switch (at) {
case 0x00: /* Configuration Option Register */
s->opt = value & 0xcf;
if (value & OPT_SRESET)
md_reset(s);
if (value & OPT_SRESET) {
device_reset(DEVICE(s));
}
md_interrupt_update(s);
break;
case 0x02: /* Card Configuration Status Register */
if ((s->stat ^ value) & STAT_PWRDWN)
if ((s->stat ^ value) & STAT_PWRDWN) {
s->pins |= PINS_CRDY;
}
s->stat &= 0x82;
s->stat |= value & 0x74;
md_interrupt_update(s);
@ -175,32 +196,35 @@ static void md_attr_write(void *opaque, uint32_t at, uint8_t value)
}
}
static uint16_t md_common_read(void *opaque, uint32_t at)
static uint16_t md_common_read(PCMCIACardState *card, uint32_t at)
{
MicroDriveState *s = opaque;
MicroDriveState *s = MICRODRIVE(card);
IDEState *ifs;
uint16_t ret;
at -= s->io_base;
switch (s->opt & OPT_MODE) {
case OPT_MODE_MMAP:
if ((at & ~0x3ff) == 0x400)
if ((at & ~0x3ff) == 0x400) {
at = 0;
}
break;
case OPT_MODE_IOMAP16:
at &= 0xf;
break;
case OPT_MODE_IOMAP1:
if ((at & ~0xf) == 0x3f0)
if ((at & ~0xf) == 0x3f0) {
at -= 0x3e8;
else if ((at & ~0xf) == 0x1f0)
} else if ((at & ~0xf) == 0x1f0) {
at -= 0x1f0;
}
break;
case OPT_MODE_IOMAP2:
if ((at & ~0xf) == 0x370)
if ((at & ~0xf) == 0x370) {
at -= 0x368;
else if ((at & ~0xf) == 0x170)
} else if ((at & ~0xf) == 0x170) {
at -= 0x170;
}
}
switch (at) {
@ -209,9 +233,9 @@ static uint16_t md_common_read(void *opaque, uint32_t at)
return ide_data_readw(&s->bus, 0);
/* TODO: 8-bit accesses */
if (s->cycle)
if (s->cycle) {
ret = s->io >> 8;
else {
} else {
s->io = ide_data_readw(&s->bus, 0);
ret = s->io & 0xff;
}
@ -223,10 +247,11 @@ static uint16_t md_common_read(void *opaque, uint32_t at)
return ide_ioport_read(&s->bus, 0x1);
case 0xe: /* Alternate Status */
ifs = idebus_active_if(&s->bus);
if (ifs->bs)
if (ifs->bs) {
return ifs->status;
else
} else {
return 0;
}
case 0xf: /* Device Address */
ifs = idebus_active_if(&s->bus);
return 0xc2 | ((~ifs->select << 2) & 0x3c);
@ -237,30 +262,33 @@ static uint16_t md_common_read(void *opaque, uint32_t at)
return 0;
}
static void md_common_write(void *opaque, uint32_t at, uint16_t value)
static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
{
MicroDriveState *s = opaque;
MicroDriveState *s = MICRODRIVE(card);
at -= s->io_base;
switch (s->opt & OPT_MODE) {
case OPT_MODE_MMAP:
if ((at & ~0x3ff) == 0x400)
if ((at & ~0x3ff) == 0x400) {
at = 0;
}
break;
case OPT_MODE_IOMAP16:
at &= 0xf;
break;
case OPT_MODE_IOMAP1:
if ((at & ~0xf) == 0x3f0)
if ((at & ~0xf) == 0x3f0) {
at -= 0x3e8;
else if ((at & ~0xf) == 0x1f0)
} else if ((at & ~0xf) == 0x1f0) {
at -= 0x1f0;
}
break;
case OPT_MODE_IOMAP2:
if ((at & ~0xf) == 0x370)
if ((at & ~0xf) == 0x370) {
at -= 0x368;
else if ((at & ~0xf) == 0x170)
} else if ((at & ~0xf) == 0x170) {
at -= 0x170;
}
}
switch (at) {
@ -270,10 +298,11 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value)
break;
/* TODO: 8-bit accesses */
if (s->cycle)
if (s->cycle) {
ide_data_writew(&s->bus, 0, s->io | (value << 8));
else
} else {
s->io = value & 0xff;
}
s->cycle = !s->cycle;
break;
case 0x9:
@ -285,8 +314,9 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value)
break;
case 0xe: /* Device Control */
s->ctrl = value;
if (value & CTRL_SRST)
md_reset(s);
if (value & CTRL_SRST) {
device_reset(DEVICE(s));
}
md_interrupt_update(s);
break;
default:
@ -501,49 +531,109 @@ static const uint8_t dscm1xxxx_cis[0x14a] = {
[0x146] = CISTPL_END, /* Tuple End */
};
static int dscm1xxxx_attach(void *opaque)
{
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;
#define TYPE_DSCM1XXXX "dscm1xxxx"
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_reset(md);
device_reset(DEVICE(md));
md_interrupt_update(md);
md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
card->slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
return 0;
}
static int dscm1xxxx_detach(void *opaque)
static int dscm1xxxx_detach(PCMCIACardState *card)
{
MicroDriveState *md = opaque;
md_reset(md);
MicroDriveState *md = MICRODRIVE(card);
device_reset(DEVICE(md));
return 0;
}
PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo)
{
MicroDriveState *md = (MicroDriveState *) g_malloc0(sizeof(MicroDriveState));
md->card.state = md;
md->card.attach = dscm1xxxx_attach;
md->card.detach = dscm1xxxx_detach;
md->card.cis = dscm1xxxx_cis;
md->card.cis_len = sizeof(dscm1xxxx_cis);
MicroDriveState *md;
ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL,
qemu_allocate_irqs(md_set_irq, md, 1)[0]);
md = MICRODRIVE(object_new(TYPE_DSCM1XXXX));
qdev_init_nofail(DEVICE(md));
if (dinfo != NULL) {
ide_create_drive(&md->bus, 0, dinfo);
}
md->bus.ifs[0].drive_kind = IDE_CFATA;
md->bus.ifs[0].mdata_size = METADATA_SIZE;
md->bus.ifs[0].mdata_storage = (uint8_t *) g_malloc0(METADATA_SIZE);
vmstate_register(NULL, -1, &vmstate_microdrive, md);
return &md->card;
return PCMCIA_CARD(md);
}
static void dscm1xxxx_class_init(ObjectClass *oc, void *data)
{
PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
pcc->cis = dscm1xxxx_cis;
pcc->cis_len = sizeof(dscm1xxxx_cis);
pcc->attach = dscm1xxxx_attach;
pcc->detach = dscm1xxxx_detach;
}
static const TypeInfo dscm1xxxx_type_info = {
.name = TYPE_DSCM1XXXX,
.parent = TYPE_MICRODRIVE,
.class_init = dscm1xxxx_class_init,
};
static void microdrive_realize(DeviceState *dev, Error **errp)
{
MicroDriveState *md = MICRODRIVE(dev);
ide_init2(&md->bus, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
}
static void microdrive_init(Object *obj)
{
MicroDriveState *md = MICRODRIVE(obj);
ide_bus_new(&md->bus, sizeof(md->bus), DEVICE(obj), 0, 1);
}
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,
.fields = (VMStateField[]) {
VMSTATE_BOOL(enabled, GICState),
VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, NCPU),
VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, GIC_NCPU),
VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
vmstate_gic_irq_state, gic_irq_state),
VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ),
VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU),
VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU),
VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU),
VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU),
VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU),
VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU),
VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU),
VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU),
VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU),
VMSTATE_END_OF_LIST()
}
};
@ -84,9 +84,9 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
GICState *s = ARM_GIC_COMMON(dev);
int num_irq = s->num_irq;
if (s->num_cpu > NCPU) {
if (s->num_cpu > GIC_NCPU) {
error_setg(errp, "requested %u CPUs exceeds GIC maximum %d",
s->num_cpu, NCPU);
s->num_cpu, GIC_NCPU);
return;
}
s->num_irq += GIC_BASE_IRQ;

View File

@ -21,16 +21,9 @@
#ifndef QEMU_ARM_GIC_INTERNAL_H
#define QEMU_ARM_GIC_INTERNAL_H
#include "hw/sysbus.h"
#include "hw/intc/arm_gic.h"
/* Maximum number of possible interrupts, determined by the GIC architecture */
#define GIC_MAXIRQ 1020
/* First 32 are private to each CPU (SGIs and PPIs). */
#define GIC_INTERNAL 32
/* Maximum number of possible CPU interfaces, determined by GIC architecture */
#define NCPU 8
#define ALL_CPU_MASK ((unsigned)(((1 << NCPU) - 1)))
#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
/* The NVIC has 16 internal vectors. However these are not exposed
through the normal GIC interface. */
@ -59,48 +52,6 @@
s->priority2[(irq) - GIC_INTERNAL])
#define GIC_TARGET(irq) s->irq_target[irq]
typedef struct gic_irq_state {
/* The enable bits are only banked for per-cpu interrupts. */
uint8_t enabled;
uint8_t pending;
uint8_t active;
uint8_t level;
bool model; /* 0 = N:N, 1 = 1:N */
bool trigger; /* nonzero = edge triggered. */
} gic_irq_state;
typedef struct GICState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
qemu_irq parent_irq[NCPU];
bool enabled;
bool cpu_enabled[NCPU];
gic_irq_state irq_state[GIC_MAXIRQ];
uint8_t irq_target[GIC_MAXIRQ];
uint8_t priority1[GIC_INTERNAL][NCPU];
uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
uint16_t last_active[GIC_MAXIRQ][NCPU];
uint16_t priority_mask[NCPU];
uint16_t running_irq[NCPU];
uint16_t running_priority[NCPU];
uint16_t current_pending[NCPU];
uint32_t num_cpu;
MemoryRegion iomem; /* Distributor */
/* This is just so we can have an opaque pointer which identifies
* both this GIC and which CPU interface we should be accessing.
*/
struct GICState *backref[NCPU];
MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
uint32_t num_irq;
uint32_t revision;
} GICState;
/* The special cases for the revision property: */
#define REV_11MPCORE 0
#define REV_NVIC 0xffffffff
@ -111,31 +62,4 @@ void gic_complete_irq(GICState *s, int cpu, int irq);
void gic_update(GICState *s);
void gic_init_irqs_and_distributor(GICState *s, int num_irq);
#define TYPE_ARM_GIC_COMMON "arm_gic_common"
#define ARM_GIC_COMMON(obj) \
OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON)
#define ARM_GIC_COMMON_CLASS(klass) \
OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON)
#define ARM_GIC_COMMON_GET_CLASS(obj) \
OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON)
typedef struct ARMGICCommonClass {
SysBusDeviceClass parent_class;
void (*pre_save)(GICState *s);
void (*post_load)(GICState *s);
} ARMGICCommonClass;
#define TYPE_ARM_GIC "arm_gic"
#define ARM_GIC(obj) \
OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
#define ARM_GIC_CLASS(klass) \
OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
#define ARM_GIC_GET_CLASS(obj) \
OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC)
typedef struct ARMGICClass {
ARMGICCommonClass parent_class;
DeviceRealize parent_realize;
} ARMGICClass;
#endif /* !QEMU_ARM_GIC_INTERNAL_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,20 +8,7 @@
* This code is licensed under the GPL.
*/
#include "hw/sysbus.h"
/* A9MP private memory region. */
typedef struct A9SCUState {
SysBusDevice busdev;
MemoryRegion iomem;
uint32_t control;
uint32_t status;
uint32_t num_cpu;
} A9SCUState;
#define TYPE_A9_SCU "a9-scu"
#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU)
#include "hw/misc/a9scu.h"
static uint64_t a9_scu_read(void *opaque, hwaddr offset,
unsigned size)
@ -114,12 +101,12 @@ static void a9_scu_reset(DeviceState *dev)
s->control = 0;
}
static void a9_scu_realize(DeviceState *dev, Error ** errp)
static void a9_scu_init(Object *obj)
{
A9SCUState *s = A9_SCU(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
A9SCUState *s = A9_SCU(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
memory_region_init_io(&s->iomem, OBJECT(dev), &a9_scu_ops, s,
memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s,
"a9-scu", 0x100);
sysbus_init_mmio(sbd, &s->iomem);
}
@ -144,7 +131,6 @@ static void a9_scu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = a9_scu_realize;
dc->props = a9_scu_properties;
dc->vmsd = &vmstate_a9_scu;
dc->reset = a9_scu_reset;
@ -154,6 +140,7 @@ static const TypeInfo a9_scu_info = {
.name = TYPE_A9_SCU,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(A9SCUState),
.instance_init = a9_scu_init,
.class_init = a9_scu_class_init,
};

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");
if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
qdev_free(&dev->qdev);
object_unparent(OBJECT(dev));
dev = NULL;
break;
}

View File

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

View File

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

View File

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

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/sysbus.h"
#include "hw/pcmcia.h"
#include "hw/arm/pxa.h"
#define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia"
#define PXA2XX_PCMCIA(obj) \
OBJECT_CHECK(PXA2xxPCMCIAState, obj, TYPE_PXA2XX_PCMCIA)
struct PXA2xxPCMCIAState {
SysBusDevice parent_obj;
PCMCIASocket slot;
PCMCIACardState *card;
MemoryRegion container_mem;
MemoryRegion common_iomem;
MemoryRegion attr_iomem;
MemoryRegion iomem;
qemu_irq irq;
qemu_irq cd_irq;
PCMCIACardState *card;
};
static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
hwaddr offset, unsigned size)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) {
return s->card->common_read(s->card->state, offset);
pcc = PCMCIA_CARD_GET_CLASS(s->card);
return pcc->common_read(s->card, offset);
}
return 0;
@ -42,9 +52,11 @@ static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) {
s->card->common_write(s->card->state, offset, value);
pcc = PCMCIA_CARD_GET_CLASS(s->card);
pcc->common_write(s->card, offset, value);
}
}
@ -52,9 +64,11 @@ static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
hwaddr offset, unsigned size)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) {
return s->card->attr_read(s->card->state, offset);
pcc = PCMCIA_CARD_GET_CLASS(s->card);
return pcc->attr_read(s->card, offset);
}
return 0;
@ -64,9 +78,11 @@ static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) {
s->card->attr_write(s->card->state, offset, value);
pcc = PCMCIA_CARD_GET_CLASS(s->card);
pcc->attr_write(s->card, offset, value);
}
}
@ -74,9 +90,11 @@ static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
hwaddr offset, unsigned size)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) {
return s->card->io_read(s->card->state, offset);
pcc = PCMCIA_CARD_GET_CLASS(s->card);
return pcc->io_read(s->card, offset);
}
return 0;
@ -86,9 +104,11 @@ static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
PCMCIACardClass *pcc;
if (s->slot.attached) {
s->card->io_write(s->card->state, offset, value);
pcc = PCMCIA_CARD_GET_CLASS(s->card);
pcc->io_write(s->card, offset, value);
}
}
@ -122,15 +142,43 @@ static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
hwaddr base)
{
DeviceState *dev;
PXA2xxPCMCIAState *s;
s = (PXA2xxPCMCIAState *)
g_malloc0(sizeof(PXA2xxPCMCIAState));
dev = qdev_create(NULL, TYPE_PXA2XX_PCMCIA);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
s = PXA2XX_PCMCIA(dev);
if (base == 0x30000000) {
s->slot.slot_string = "PXA PC Card Socket 1";
} else {
s->slot.slot_string = "PXA PC Card Socket 0";
}
qdev_init_nofail(dev);
return s;
}
static void pxa2xx_pcmcia_realize(DeviceState *dev, Error **errp)
{
PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(dev);
pcmcia_socket_register(&s->slot);
}
static void pxa2xx_pcmcia_initfn(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(obj);
memory_region_init(&s->container_mem, obj, "container", 0x10000000);
sysbus_init_mmio(sbd, &s->container_mem);
/* Socket I/O Memory Space */
memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s,
"pxa2xx-pcmcia-io", 0x04000000);
memory_region_add_subregion(sysmem, base | 0x00000000,
memory_region_add_subregion(&s->container_mem, 0x00000000,
&s->iomem);
/* Then next 64 MB is reserved */
@ -138,62 +186,68 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
/* Socket Attribute Memory Space */
memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s,
"pxa2xx-pcmcia-attribute", 0x04000000);
memory_region_add_subregion(sysmem, base | 0x08000000,
memory_region_add_subregion(&s->container_mem, 0x08000000,
&s->attr_iomem);
/* Socket Common Memory Space */
memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s,
"pxa2xx-pcmcia-common", 0x04000000);
memory_region_add_subregion(sysmem, base | 0x0c000000,
memory_region_add_subregion(&s->container_mem, 0x0c000000,
&s->common_iomem);
if (base == 0x30000000)
s->slot.slot_string = "PXA PC Card Socket 1";
else
s->slot.slot_string = "PXA PC Card Socket 0";
s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
pcmcia_socket_register(&s->slot);
return s;
object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
(Object **)&s->card, NULL);
}
/* Insert a new card into a slot */
int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (s->slot.attached)
PCMCIACardClass *pcc;
if (s->slot.attached) {
return -EEXIST;
}
if (s->cd_irq) {
qemu_irq_raise(s->cd_irq);
}
s->card = card;
pcc = PCMCIA_CARD_GET_CLASS(s->card);
s->slot.attached = 1;
s->slot.attached = true;
s->card->slot = &s->slot;
s->card->attach(s->card->state);
pcc->attach(s->card);
return 0;
}
/* Eject card from the slot */
int pxa2xx_pcmcia_dettach(void *opaque)
int pxa2xx_pcmcia_detach(void *opaque)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (!s->slot.attached)
return -ENOENT;
PCMCIACardClass *pcc;
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 = NULL;
s->slot.attached = 0;
s->slot.attached = false;
if (s->irq)
if (s->irq) {
qemu_irq_lower(s->irq);
if (s->cd_irq)
}
if (s->cd_irq) {
qemu_irq_lower(s->cd_irq);
}
return 0;
}
@ -205,3 +259,25 @@ void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
s->irq = irq;
s->cd_irq = cd_irq;
}
static void pxa2xx_pcmcia_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = pxa2xx_pcmcia_realize;
}
static const TypeInfo pxa2xx_pcmcia_type_info = {
.name = TYPE_PXA2XX_PCMCIA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxPCMCIAState),
.instance_init = pxa2xx_pcmcia_initfn,
.class_init = pxa2xx_pcmcia_class_init,
};
static void pxa2xx_pcmcia_register_types(void)
{
type_register_static(&pxa2xx_pcmcia_type_info);
}
type_init(pxa2xx_pcmcia_register_types)

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);
qdev_free(dev);
object_unparent(OBJECT(dev));
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);
assert(d);
if (d->lun == dev->lun && dev != d) {
qdev_free(&d->qdev);
object_unparent(OBJECT(d));
}
}
@ -231,13 +231,13 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
}
if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
error_setg(errp, "Setting drive property failed");
qdev_free(dev);
object_unparent(OBJECT(dev));
return NULL;
}
object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
qdev_free(dev);
object_unparent(OBJECT(dev));
return NULL;
}
return SCSI_DEVICE(dev);

View File

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

View File

@ -26,6 +26,7 @@
#include "hw/ptimer.h"
#include "sysemu/char.h"
#include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "elf.h"
@ -178,7 +179,7 @@ static void leon3_generic_hw_init(QEMUMachineInitArgs *args)
fprintf(stderr, "qemu: could not load prom '%s'\n", filename);
exit(1);
}
} else if (kernel_filename == NULL) {
} else if (kernel_filename == NULL && !qtest_enabled()) {
fprintf(stderr, "Can't read bios image %s\n", filename);
exit(1);
}

View File

@ -19,7 +19,7 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "hw/sysbus.h"
#include "hw/timer/arm_mptimer.h"
#include "qemu/timer.h"
#include "qom/cpu.h"
@ -27,34 +27,6 @@
* which is used in both the ARM11MPCore and Cortex-A9MP.
*/
#define MAX_CPUS 4
/* State of a single timer or watchdog block */
typedef struct {
uint32_t count;
uint32_t load;
uint32_t control;
uint32_t status;
int64_t tick;
QEMUTimer *timer;
qemu_irq irq;
MemoryRegion iomem;
} TimerBlock;
#define TYPE_ARM_MPTIMER "arm_mptimer"
#define ARM_MPTIMER(obj) \
OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER)
typedef struct {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
uint32_t num_cpu;
TimerBlock timerblock[MAX_CPUS];
MemoryRegion iomem;
} ARMMPTimerState;
static inline int get_current_cpu(ARMMPTimerState *s)
{
if (current_cpu->cpu_index >= s->num_cpu) {
@ -225,13 +197,24 @@ static void arm_mptimer_reset(DeviceState *dev)
}
}
static int arm_mptimer_init(SysBusDevice *dev)
static void arm_mptimer_init(Object *obj)
{
ARMMPTimerState *s = ARM_MPTIMER(obj);
memory_region_init_io(&s->iomem, obj, &arm_thistimer_ops, s,
"arm_mptimer_timer", 0x20);
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
}
static void arm_mptimer_realize(DeviceState *dev, Error **errp)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
ARMMPTimerState *s = ARM_MPTIMER(dev);
int i;
if (s->num_cpu < 1 || s->num_cpu > MAX_CPUS) {
hw_error("%s: num-cpu must be between 1 and %d\n", __func__, MAX_CPUS);
if (s->num_cpu < 1 || s->num_cpu > ARM_MPTIMER_MAX_CPUS) {
hw_error("%s: num-cpu must be between 1 and %d\n",
__func__, ARM_MPTIMER_MAX_CPUS);
}
/* We implement one timer block per CPU, and expose multiple MMIO regions:
* * region 0 is "timer for this core"
@ -243,19 +226,14 @@ static int arm_mptimer_init(SysBusDevice *dev)
* * timer for core 1
* and so on.
*/
memory_region_init_io(&s->iomem, OBJECT(s), &arm_thistimer_ops, s,
"arm_mptimer_timer", 0x20);
sysbus_init_mmio(dev, &s->iomem);
for (i = 0; i < s->num_cpu; i++) {
TimerBlock *tb = &s->timerblock[i];
tb->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, timerblock_tick, tb);
sysbus_init_irq(dev, &tb->irq);
sysbus_init_irq(sbd, &tb->irq);
memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
"arm_mptimer_timerblock", 0x20);
sysbus_init_mmio(dev, &tb->iomem);
sysbus_init_mmio(sbd, &tb->iomem);
}
return 0;
}
static const VMStateDescription vmstate_timerblock = {
@ -292,9 +270,8 @@ static Property arm_mptimer_properties[] = {
static void arm_mptimer_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
sbc->init = arm_mptimer_init;
dc->realize = arm_mptimer_realize;
dc->vmsd = &vmstate_arm_mptimer;
dc->reset = arm_mptimer_reset;
dc->no_user = 1;
@ -305,6 +282,7 @@ static const TypeInfo arm_mptimer_info = {
.name = TYPE_ARM_MPTIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ARMMPTimerState),
.instance_init = arm_mptimer_init,
.class_init = arm_mptimer_class_init,
};

View File

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

View File

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

View File

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

View File

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

View File

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

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) ==
PCI_CLASS_NETWORK_ETHERNET
&& 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,
hwaddr base);
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);
/* 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 */
#include "qemu-common.h"
#include "hw/qdev.h"
typedef struct {
typedef struct PCMCIASocket {
qemu_irq irq;
int attached;
bool attached;
const char *slot_string;
const char *card_string;
} PCMCIASocket;
@ -16,22 +16,42 @@ void pcmcia_socket_register(PCMCIASocket *socket);
void pcmcia_socket_unregister(PCMCIASocket *socket);
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 {
void *state;
/*< private >*/
DeviceState parent_obj;
/*< public >*/
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;
int cis_len;
/* Only valid if attached */
uint8_t (*attr_read)(void *state, uint32_t address);
void (*attr_write)(void *state, uint32_t address, uint8_t value);
uint16_t (*common_read)(void *state, uint32_t address);
void (*common_write)(void *state, uint32_t address, uint16_t value);
uint16_t (*io_read)(void *state, uint32_t address);
void (*io_write)(void *state, uint32_t address, uint16_t value);
};
uint8_t (*attr_read)(PCMCIACardState *card, uint32_t address);
void (*attr_write)(PCMCIACardState *card, uint32_t address, uint8_t value);
uint16_t (*common_read)(PCMCIACardState *card, uint32_t address);
void (*common_write)(PCMCIACardState *card,
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_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,
int required_for_version);
void qdev_unplug(DeviceState *dev, Error **errp);
void qdev_free(DeviceState *dev);
int qdev_simple_unplug_cb(DeviceState *dev);
void qdev_machine_creation_done(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);
/**
* 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:
* @obj: the object
@ -1133,6 +1112,58 @@ void object_property_add_bool(Object *obj, const char *name,
void (*set)(Object *, bool, Error **),
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:
* @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)
{
ObjectClass *obj;
DeviceClass *k;
ObjectClass *oc;
DeviceClass *dc;
const char *driver, *path, *id;
DeviceState *qdev;
DeviceState *dev;
BusState *bus = NULL;
Error *err = NULL;
driver = qemu_opt_get(opts, "driver");
if (!driver) {
@ -466,22 +467,28 @@ DeviceState *qdev_device_add(QemuOpts *opts)
}
/* find driver */
obj = object_class_by_name(driver);
if (!obj) {
oc = object_class_by_name(driver);
if (!oc) {
const char *typename = find_typename_by_alias(driver);
if (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");
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 */
path = qemu_opt_get(opts, "bus");
@ -490,16 +497,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
if (!bus) {
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,
driver, object_get_typename(OBJECT(bus)));
return NULL;
}
} else if (k->bus_type != NULL) {
bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
} else if (dc->bus_type != NULL) {
bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
if (!bus) {
qerror_report(QERR_NO_BUS_FOR_DEVICE,
k->bus_type, driver);
dc->bus_type, driver);
return NULL;
}
}
@ -509,36 +516,42 @@ DeviceState *qdev_device_add(QemuOpts *opts)
}
/* create device, set properties */
qdev = DEVICE(object_new(driver));
dev = DEVICE(object_new(driver));
if (bus) {
qdev_set_parent_bus(qdev, bus);
qdev_set_parent_bus(dev, bus);
}
id = qemu_opts_id(opts);
if (id) {
qdev->id = id;
dev->id = id;
}
if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
qdev_free(qdev);
if (qemu_opt_foreach(opts, set_property, dev, 1) != 0) {
object_unparent(OBJECT(dev));
object_unref(OBJECT(dev));
return NULL;
}
if (qdev->id) {
object_property_add_child(qdev_get_peripheral(), qdev->id,
OBJECT(qdev), NULL);
if (dev->id) {
object_property_add_child(qdev_get_peripheral(), dev->id,
OBJECT(dev), NULL);
} else {
static int anon_count;
gchar *name = g_strdup_printf("device[%d]", anon_count++);
object_property_add_child(qdev_get_peripheral_anon(), name,
OBJECT(qdev), NULL);
OBJECT(dev), NULL);
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);
return NULL;
}
qdev->opts = opts;
return qdev;
dev->opts = opts;
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/i440fx-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)
gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c
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-mips64-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-ppc64-y = tests/endianness-test$(EXESUF)
check-qtest-sh4-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-sparc-y = tests/m48t59-test$(EXESUF)
#check-qtest-sparc64-y += tests/m48t59-test$(EXESUF)
gcov-files-sparc-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)
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-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/, \
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/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/qom-test$(EXESUF): tests/qom-test.o
tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
# 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();
}