From 2b81b35f8f18d6874d1a0605ac5e40028966051b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 7 Mar 2014 19:04:13 +0100 Subject: [PATCH 01/31] qdev: Fix bus dependency of DeviceState::hotpluggable getter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 1a37eca107cece3ed454bae29eef0bd1fac4a244 (qdev: add "hotpluggable" property to Device) added a property "hotpluggable" to each device, with its getter accessing parent_bus->allow_hotplug. Add a NULL check. Cc: Igor Mammedov Signed-off-by: Andreas Färber --- hw/core/qdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 380976a066..53778938e6 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -735,7 +735,8 @@ static bool device_get_hotpluggable(Object *obj, Error **err) DeviceClass *dc = DEVICE_GET_CLASS(obj); DeviceState *dev = DEVICE(obj); - return dc->hotpluggable && dev->parent_bus->allow_hotplug; + return dc->hotpluggable && (dev->parent_bus == NULL || + dev->parent_bus->allow_hotplug); } static void device_initfn(Object *obj) From 267a3264cdaf0ca945ffc7a60c019ad9f89be8d8 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 18 Feb 2014 17:56:53 +0100 Subject: [PATCH 02/31] qdev: Set DeviceClass::hotpluggable default in class_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move setting DeviceClass::hotpluggable default from device's class_base_init() to device's class_init(). Reported-by: Andreas Färber Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/core/qdev.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 53778938e6..71b70454eb 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -793,14 +793,6 @@ static void device_class_base_init(ObjectClass *class, void *data) * so do not propagate them to the subclasses. */ klass->props = NULL; - - /* by default all devices were considered as hotpluggable, - * so with intent to check it in generic qdev_unplug() / - * device_set_realized() functions make every device - * hotpluggable. Devices that shouldn't be hotpluggable, - * should override it in their class_init() - */ - klass->hotpluggable = true; } static void device_unparent(Object *obj) @@ -846,6 +838,14 @@ static void device_class_init(ObjectClass *class, void *data) class->unparent = device_unparent; dc->realize = device_realize; dc->unrealize = device_unrealize; + + /* by default all devices were considered as hotpluggable, + * so with intent to check it in generic qdev_unplug() / + * device_set_realized() functions make every device + * hotpluggable. Devices that shouldn't be hotpluggable, + * should override it in their class_init() + */ + dc->hotpluggable = true; } void device_reset(DeviceState *dev) From 7b0309490cb108d881a0c66d6b350b4db7b3b4ac Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Mon, 3 Mar 2014 15:57:55 +0800 Subject: [PATCH 03/31] qdev-monitor: Set properties after parent is assigned in device_add MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test steps: (qemu) device_add e1000,addr=adsf Property 'e1000.addr' doesn't take value 'adsf' (qemu) info qtree Then qemu crashed. Currently we set a link to the new device from its parent bus, but the device hasn't been added to QOM tree yet. When it fails to set properties, object_unparent() can't clean up the device. Delay setting of device properties until the device has been added to the QOM composition tree. This way, when setting a property fails, object_unparent() can clean up the device properly. Signed-off-by: Amos Kong Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- qdev-monitor.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/qdev-monitor.c b/qdev-monitor.c index 6673e3cb61..9268c8759f 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -522,7 +522,7 @@ DeviceState *qdev_device_add(QemuOpts *opts) return NULL; } - /* create device, set properties */ + /* create device */ dev = DEVICE(object_new(driver)); if (bus) { @@ -533,11 +533,7 @@ DeviceState *qdev_device_add(QemuOpts *opts) if (id) { dev->id = id; } - if (qemu_opt_foreach(opts, set_property, dev, 1) != 0) { - object_unparent(OBJECT(dev)); - object_unref(OBJECT(dev)); - return NULL; - } + if (dev->id) { object_property_add_child(qdev_get_peripheral(), dev->id, OBJECT(dev), NULL); @@ -549,6 +545,13 @@ DeviceState *qdev_device_add(QemuOpts *opts) g_free(name); } + /* set properties */ + if (qemu_opt_foreach(opts, set_property, dev, 1) != 0) { + object_unparent(OBJECT(dev)); + object_unref(OBJECT(dev)); + return NULL; + } + dev->opts = opts; object_property_set_bool(OBJECT(dev), true, "realized", &err); if (err != NULL) { From a01aedc8d32e6f5b08a4041b62be3c5fab7a3382 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 4 Mar 2014 15:28:18 +0100 Subject: [PATCH 04/31] qom: Avoid leaking str and bool properties on failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When object_property_add_str() and object_property_add_bool() fail, they leak their internal StringProperty and BoolProperty structs. Remember to free the structs on error. Luckily this is a low-impact memory leak since most QOM properties are static qdev properties that will never take the error case. object_property_add() only fails if the property name is already in use. Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake Cc: qemu-stable@nongnu.org Signed-off-by: Andreas Färber --- qom/object.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/qom/object.c b/qom/object.c index 660859c0e7..c88909c6b6 100644 --- a/qom/object.c +++ b/qom/object.c @@ -1293,6 +1293,7 @@ void object_property_add_str(Object *obj, const char *name, void (*set)(Object *, const char *, Error **), Error **errp) { + Error *local_err = NULL; StringProperty *prop = g_malloc0(sizeof(*prop)); prop->get = get; @@ -1302,7 +1303,11 @@ void object_property_add_str(Object *obj, const char *name, get ? property_get_str : NULL, set ? property_set_str : NULL, property_release_str, - prop, errp); + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } } typedef struct BoolProperty @@ -1349,6 +1354,7 @@ void object_property_add_bool(Object *obj, const char *name, void (*set)(Object *, bool, Error **), Error **errp) { + Error *local_err = NULL; BoolProperty *prop = g_malloc0(sizeof(*prop)); prop->get = get; @@ -1358,7 +1364,11 @@ void object_property_add_bool(Object *obj, const char *name, get ? property_get_bool : NULL, set ? property_set_bool : NULL, property_release_bool, - prop, errp); + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } } static char *qdev_get_type(Object *obj, Error **errp) From 1a7d9ee6dd4aa44fc7d937bded8d542e0265e57f Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 11 Feb 2014 16:27:50 -0800 Subject: [PATCH 05/31] ssi: Convert legacy SSI_SLAVE -> DEVICE casts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert legacy ->qdev style casts from TYPE_SSI_SLAVE to TYPE_DEVICE. Signed-off-by: Peter Crosthwaite [AF: Introduce local DeviceState variable for transition to QOM realize] Signed-off-by: Andreas Färber --- hw/arm/spitz.c | 13 +++++++------ hw/display/ads7846.c | 7 ++++--- hw/display/ssd0323.c | 11 ++++++----- hw/misc/max111x.c | 9 +++++---- hw/sd/ssi-sd.c | 7 ++++--- hw/ssi/ssi.c | 2 +- 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index 2decff170f..392ca84c81 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -658,14 +658,15 @@ static void spitz_adc_temp_on(void *opaque, int line, int level) max111x_set_input(max1111, MAX1111_BATT_TEMP, 0); } -static int corgi_ssp_init(SSISlave *dev) +static int corgi_ssp_init(SSISlave *d) { - CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev); + DeviceState *dev = DEVICE(d); + CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, d); - qdev_init_gpio_in(&dev->qdev, corgi_ssp_gpio_cs, 3); - s->bus[0] = ssi_create_bus(&dev->qdev, "ssi0"); - s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1"); - s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2"); + qdev_init_gpio_in(dev, corgi_ssp_gpio_cs, 3); + s->bus[0] = ssi_create_bus(dev, "ssi0"); + s->bus[1] = ssi_create_bus(dev, "ssi1"); + s->bus[2] = ssi_create_bus(dev, "ssi2"); return 0; } diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c index 5da3dc5b2c..85252a2329 100644 --- a/hw/display/ads7846.c +++ b/hw/display/ads7846.c @@ -133,11 +133,12 @@ static const VMStateDescription vmstate_ads7846 = { } }; -static int ads7846_init(SSISlave *dev) +static int ads7846_init(SSISlave *d) { - ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev); + DeviceState *dev = DEVICE(d); + ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, d); - qdev_init_gpio_out(&dev->qdev, &s->interrupt, 1); + qdev_init_gpio_out(dev, &s->interrupt, 1); s->input[0] = ADS_TEMP0; /* TEMP0 */ s->input[2] = ADS_VBAT; /* VBAT */ diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c index 46c3b40c79..971152edbd 100644 --- a/hw/display/ssd0323.c +++ b/hw/display/ssd0323.c @@ -336,18 +336,19 @@ static const GraphicHwOps ssd0323_ops = { .gfx_update = ssd0323_update_display, }; -static int ssd0323_init(SSISlave *dev) +static int ssd0323_init(SSISlave *d) { - ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev); + DeviceState *dev = DEVICE(d); + ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, d); s->col_end = 63; s->row_end = 79; - s->con = graphic_console_init(DEVICE(dev), 0, &ssd0323_ops, s); + s->con = graphic_console_init(dev, 0, &ssd0323_ops, s); qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY); - qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1); + qdev_init_gpio_in(dev, ssd0323_cd, 1); - register_savevm(&dev->qdev, "ssd0323_oled", -1, 1, + register_savevm(dev, "ssd0323_oled", -1, 1, ssd0323_save, ssd0323_load, s); return 0; } diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c index d477ecdb29..28dfa0bd06 100644 --- a/hw/misc/max111x.c +++ b/hw/misc/max111x.c @@ -115,11 +115,12 @@ static const VMStateDescription vmstate_max111x = { } }; -static int max111x_init(SSISlave *dev, int inputs) +static int max111x_init(SSISlave *d, int inputs) { - MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev); + DeviceState *dev = DEVICE(d); + MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, d); - qdev_init_gpio_out(&dev->qdev, &s->interrupt, 1); + qdev_init_gpio_out(dev, &s->interrupt, 1); s->inputs = inputs; /* TODO: add a user interface for setting these */ @@ -133,7 +134,7 @@ static int max111x_init(SSISlave *dev, int inputs) s->input[7] = 0x80; s->com = 0; - vmstate_register(&dev->qdev, -1, &vmstate_max111x, s); + vmstate_register(dev, -1, &vmstate_max111x, s); return 0; } diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index 1bb56c4d54..3273c8a31f 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -238,9 +238,10 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int ssi_sd_init(SSISlave *dev) +static int ssi_sd_init(SSISlave *d) { - ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev); + DeviceState *dev = DEVICE(d); + ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d); DriveInfo *dinfo; s->mode = SSI_SD_CMD; @@ -249,7 +250,7 @@ static int ssi_sd_init(SSISlave *dev) if (s->sd == NULL) { return -1; } - register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s); + register_savevm(dev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s); return 0; } diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c index 2c25260875..3cac37c676 100644 --- a/hw/ssi/ssi.c +++ b/hw/ssi/ssi.c @@ -60,7 +60,7 @@ static int ssi_slave_init(DeviceState *dev) if (ssc->transfer_raw == ssi_transfer_raw_default && ssc->cs_polarity != SSI_CS_NONE) { - qdev_init_gpio_in(&s->qdev, ssi_cs_default, 1); + qdev_init_gpio_in(dev, ssi_cs_default, 1); } return ssc->init(s); From d43269dddc2e084a61bb6cfcc18081b0b6bb0e62 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 11 Feb 2014 16:28:25 -0800 Subject: [PATCH 06/31] ssi: Convert legacy SSI_BUS -> BUS casts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove two legacy ->qbus style casts from TYPE_SSI_BUS to TYPE_BUS in ssi.c. Signed-off-by: Peter Crosthwaite [AF: Convert one missing ->qbus and rename parent field] Signed-off-by: Andreas Färber --- hw/ssi/ssi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c index 3cac37c676..017f0221fb 100644 --- a/hw/ssi/ssi.c +++ b/hw/ssi/ssi.c @@ -15,7 +15,7 @@ #include "hw/ssi.h" struct SSIBus { - BusState qbus; + BusState parent_obj; }; #define TYPE_SSI_BUS "SSI" @@ -88,7 +88,7 @@ static const TypeInfo ssi_slave_info = { DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name) { - return qdev_create(&bus->qbus, name); + return qdev_create(BUS(bus), name); } DeviceState *ssi_create_slave(SSIBus *bus, const char *name) @@ -108,11 +108,12 @@ SSIBus *ssi_create_bus(DeviceState *parent, const char *name) uint32_t ssi_transfer(SSIBus *bus, uint32_t val) { + BusState *b = BUS(bus); BusChild *kid; SSISlaveClass *ssc; uint32_t r = 0; - QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { + QTAILQ_FOREACH(kid, &b->children, sibling) { SSISlave *slave = SSI_SLAVE(kid->child); ssc = SSI_SLAVE_GET_CLASS(slave); r |= ssc->transfer_raw(slave, val); @@ -156,7 +157,7 @@ static int ssi_auto_connect_slave(Object *child, void *opaque) } cs_line = qdev_get_gpio_in(DEVICE(dev), 0); - qdev_set_parent_bus(DEVICE(dev), &arg->bus->qbus); + qdev_set_parent_bus(DEVICE(dev), BUS(arg->bus)); **arg->cs_linep = cs_line; (*arg->cs_linep)++; return 0; From 5ef4a1c304ef60224c29aa9f6d9c2ac0591d020a Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 11 Feb 2014 16:29:00 -0800 Subject: [PATCH 07/31] misc/max111x: Create abstract max111x type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create an abstract class that encompasses both max111x variants. This is needed for QOM cast macro creation (and is the right thing to do anyway). Macroify type-names in the process. Signed-off-by: Peter Crosthwaite Signed-off-by: Andreas Färber --- hw/misc/max111x.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c index 28dfa0bd06..1b5da699b9 100644 --- a/hw/misc/max111x.c +++ b/hw/misc/max111x.c @@ -22,6 +22,11 @@ typedef struct { int inputs, com; } MAX111xState; +#define TYPE_MAX_111X "max111x" + +#define TYPE_MAX_1110 "max1110" +#define TYPE_MAX_1111 "max1111" + /* Control-byte bitfields */ #define CB_PD0 (1 << 0) #define CB_PD1 (1 << 1) @@ -155,18 +160,31 @@ void max111x_set_input(DeviceState *dev, int line, uint8_t value) s->input[line] = value; } +static void max111x_class_init(ObjectClass *klass, void *data) +{ + SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + + k->transfer = max111x_transfer; +} + +static const TypeInfo max111x_info = { + .name = TYPE_MAX_111X, + .parent = TYPE_SSI_SLAVE, + .instance_size = sizeof(MAX111xState), + .class_init = max111x_class_init, + .abstract = true, +}; + static void max1110_class_init(ObjectClass *klass, void *data) { SSISlaveClass *k = SSI_SLAVE_CLASS(klass); k->init = max1110_init; - k->transfer = max111x_transfer; } static const TypeInfo max1110_info = { - .name = "max1110", - .parent = TYPE_SSI_SLAVE, - .instance_size = sizeof(MAX111xState), + .name = TYPE_MAX_1110, + .parent = TYPE_MAX_111X, .class_init = max1110_class_init, }; @@ -175,18 +193,17 @@ static void max1111_class_init(ObjectClass *klass, void *data) SSISlaveClass *k = SSI_SLAVE_CLASS(klass); k->init = max1111_init; - k->transfer = max111x_transfer; } static const TypeInfo max1111_info = { - .name = "max1111", - .parent = TYPE_SSI_SLAVE, - .instance_size = sizeof(MAX111xState), + .name = TYPE_MAX_1111, + .parent = TYPE_MAX_111X, .class_init = max1111_class_init, }; static void max111x_register_types(void) { + type_register_static(&max111x_info); type_register_static(&max1110_info); type_register_static(&max1111_info); } From 7c77b654c5371e970bc3190afe8dc85bc4f2c8ff Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 11 Feb 2014 16:29:35 -0800 Subject: [PATCH 08/31] misc/max111x: QOM casting sweep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define and use QOM cast macro. Removes some usages of legacy casting systems. Signed-off-by: Peter Crosthwaite [AF: Rename parent field] Signed-off-by: Andreas Färber --- hw/misc/max111x.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c index 1b5da699b9..bba87c2ec5 100644 --- a/hw/misc/max111x.c +++ b/hw/misc/max111x.c @@ -13,7 +13,8 @@ #include "hw/ssi.h" typedef struct { - SSISlave ssidev; + SSISlave parent_obj; + qemu_irq interrupt; uint8_t tb1, rb2, rb3; int cycle; @@ -24,6 +25,9 @@ typedef struct { #define TYPE_MAX_111X "max111x" +#define MAX_111X(obj) \ + OBJECT_CHECK(MAX111xState, (obj), TYPE_MAX_111X) + #define TYPE_MAX_1110 "max1110" #define TYPE_MAX_1111 "max1111" @@ -97,7 +101,7 @@ static void max111x_write(MAX111xState *s, uint32_t value) static uint32_t max111x_transfer(SSISlave *dev, uint32_t value) { - MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev); + MAX111xState *s = MAX_111X(dev); max111x_write(s, value); return max111x_read(s); } @@ -108,7 +112,7 @@ static const VMStateDescription vmstate_max111x = { .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, MAX111xState), + VMSTATE_SSI_SLAVE(parent_obj, MAX111xState), VMSTATE_UINT8(tb1, MAX111xState), VMSTATE_UINT8(rb2, MAX111xState), VMSTATE_UINT8(rb3, MAX111xState), @@ -123,7 +127,7 @@ static const VMStateDescription vmstate_max111x = { static int max111x_init(SSISlave *d, int inputs) { DeviceState *dev = DEVICE(d); - MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, d); + MAX111xState *s = MAX_111X(dev); qdev_init_gpio_out(dev, &s->interrupt, 1); @@ -155,7 +159,7 @@ static int max1111_init(SSISlave *dev) void max111x_set_input(DeviceState *dev, int line, uint8_t value) { - MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, SSI_SLAVE_FROM_QDEV(dev)); + MAX111xState *s = MAX_111X(dev); assert(line >= 0 && line < s->inputs); s->input[line] = value; } From 1f760d5f2bbe89685f2fe4b12a898c26196d3a1e Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 11 Feb 2014 16:30:10 -0800 Subject: [PATCH 09/31] ssi: Remove SSI_SLAVE_FROM_QDEV() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no usages left of this legacy cast. Delete. Signed-off-by: Peter Crosthwaite [AF: Rename SSISlave parent field] Signed-off-by: Andreas Färber ssi: Rename parent field --- include/hw/ssi.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/hw/ssi.h b/include/hw/ssi.h index fdae317295..6c13fb2e44 100644 --- a/include/hw/ssi.h +++ b/include/hw/ssi.h @@ -56,13 +56,12 @@ typedef struct SSISlaveClass { } SSISlaveClass; struct SSISlave { - DeviceState qdev; + DeviceState parent_obj; /* Chip select state */ bool cs; }; -#define SSI_SLAVE_FROM_QDEV(dev) DO_UPCAST(SSISlave, qdev, dev) #define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev) extern const VMStateDescription vmstate_ssi_slave; From cdccf7d7e7f16046cdb192423323a42ad7f43bec Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 11 Feb 2014 16:30:45 -0800 Subject: [PATCH 10/31] block/m25p80: Remove FROM_SSI_SLAVE() usages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Crosthwaite [AF: Rename parent field] Signed-off-by: Andreas Färber --- hw/block/m25p80.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 02a15441fa..e29a738d23 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -241,7 +241,8 @@ typedef enum { } CMDState; typedef struct Flash { - SSISlave ssidev; + SSISlave parent_obj; + uint32_t r; BlockDriverState *bdrv; @@ -545,7 +546,7 @@ static void decode_new_cmd(Flash *s, uint32_t value) static int m25p80_cs(SSISlave *ss, bool select) { - Flash *s = FROM_SSI_SLAVE(Flash, ss); + Flash *s = M25P80(ss); if (select) { s->len = 0; @@ -561,7 +562,7 @@ static int m25p80_cs(SSISlave *ss, bool select) static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) { - Flash *s = FROM_SSI_SLAVE(Flash, ss); + Flash *s = M25P80(ss); uint32_t r = 0; switch (s->state) { @@ -610,7 +611,7 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) static int m25p80_init(SSISlave *ss) { DriveInfo *dinfo; - Flash *s = FROM_SSI_SLAVE(Flash, ss); + Flash *s = M25P80(ss); M25P80Class *mc = M25P80_GET_CLASS(s); s->pi = mc->pi; From 1b8601b0ea0b91467561e0bbddd52a833e4b2b1a Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Thu, 6 Mar 2014 14:11:00 +1100 Subject: [PATCH 11/31] spapr-pci: Change the default PCI bus naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously libvirt required the first/default PCI bus to have name "pci". Since QEMU can support multiple buses now, libvirt wants "pci.0" now. This removes custom bus name and lets QEMU make up default names. Signed-off-by: Alexey Kardashevskiy Signed-off-by: Andreas Färber --- hw/ppc/spapr_pci.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index cea9469872..3063109e21 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -510,7 +510,6 @@ static int spapr_phb_init(SysBusDevice *s) DeviceState *dev = DEVICE(s); sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s); PCIHostState *phb = PCI_HOST_BRIDGE(s); - const char *busname; char *namebuf; int i; PCIBus *bus; @@ -594,26 +593,8 @@ static int spapr_phb_init(SysBusDevice *s) get_system_io(), 0, SPAPR_PCI_IO_WIN_SIZE); memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, &sphb->iowindow); - /* - * Selecting a busname is more complex than you'd think, due to - * interacting constraints. If the user has specified an id - * explicitly for the phb , then we want to use the qdev default - * of naming the bus based on the bridge device (so the user can - * then assign devices to it in the way they expect). For the - * first / default PCI bus (index=0) we want to use just "pci" - * because libvirt expects there to be a bus called, simply, - * "pci". Otherwise, we use the same name as in the device tree, - * since it's unique by construction, and makes the guest visible - * BUID clear. - */ - if (dev->id) { - busname = NULL; - } else if (sphb->index == 0) { - busname = "pci"; - } else { - busname = sphb->dtbusname; - } - bus = pci_register_bus(dev, busname, + + bus = pci_register_bus(dev, NULL, pci_spapr_set_irq, pci_spapr_map_irq, sphb, &sphb->memspace, &sphb->iospace, PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS); From a3d7cbc1397bf01249b5c39dd1e285bd6aa818dc Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 6 Mar 2014 10:12:52 +0100 Subject: [PATCH 12/31] qdev-monitor-test: Simplify using g_assert_cmpstr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use g_assert_cmpstr() instead of combining g_assert() and strcmp(3). This simplifies the code since we no longer have to play games to distinguish NULL from "" using "(null)". gcc extension haters will also be happy that ?: was dropped. Suggested-by: Markus Armbruster Signed-off-by: Stefan Hajnoczi Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi Signed-off-by: Andreas Färber --- tests/qdev-monitor-test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/qdev-monitor-test.c b/tests/qdev-monitor-test.c index ba7f9cc238..eefaab823a 100644 --- a/tests/qdev-monitor-test.c +++ b/tests/qdev-monitor-test.c @@ -32,8 +32,9 @@ static void test_device_add(void) "}}"); g_assert(response); error = qdict_get_qdict(response, "error"); - g_assert(!strcmp(qdict_get_try_str(error, "desc") ?: "", - "Device needs media, but drive is empty")); + g_assert_cmpstr(qdict_get_try_str(error, "desc"), + ==, + "Device needs media, but drive is empty"); QDECREF(response); /* Delete the drive */ @@ -42,7 +43,7 @@ static void test_device_add(void) " \"command-line\": \"drive_del drive0\"" "}}"); g_assert(response); - g_assert(!strcmp(qdict_get_try_str(response, "return") ?: "(null)", "")); + g_assert_cmpstr(qdict_get_try_str(response, "return"), ==, ""); QDECREF(response); /* Try to re-add the drive. This fails with duplicate IDs if a leaked @@ -53,8 +54,7 @@ static void test_device_add(void) " \"command-line\": \"drive_add pci-addr=auto if=none,id=drive0\"" "}}"); g_assert(response); - g_assert(!strcmp(qdict_get_try_str(response, "return") ?: "", - "OK\r\n")); + g_assert_cmpstr(qdict_get_try_str(response, "return"), ==, "OK\r\n"); QDECREF(response); qtest_end(); From 49649f23db977137c031a21eee2f0521404f6710 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 6 Mar 2014 10:12:53 +0100 Subject: [PATCH 13/31] qdev-monitor-test: Don't test human-readable error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test the error class instead. Expecting a specific message is fragile. In fact, it broke once already, in commit 75884af. Restore the test of error member "class" dropped there, and drop the test of error member "desc". There are no other tests of "desc" as far as I can tell. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi Signed-off-by: Andreas Färber --- tests/qdev-monitor-test.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/qdev-monitor-test.c b/tests/qdev-monitor-test.c index eefaab823a..e20ffd67a7 100644 --- a/tests/qdev-monitor-test.c +++ b/tests/qdev-monitor-test.c @@ -32,9 +32,7 @@ static void test_device_add(void) "}}"); g_assert(response); error = qdict_get_qdict(response, "error"); - g_assert_cmpstr(qdict_get_try_str(error, "desc"), - ==, - "Device needs media, but drive is empty"); + g_assert_cmpstr(qdict_get_try_str(error, "class"), ==, "GenericError"); QDECREF(response); /* Delete the drive */ From 36d20cb2b39311869b061e1669cb55ccbf0af759 Mon Sep 17 00:00:00 2001 From: Marcel Apfelbaum Date: Wed, 5 Mar 2014 19:30:45 +0200 Subject: [PATCH 14/31] hw/core: Introduce QEMU machine as QOM object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The main functional change is to convert QEMUMachine into MachineClass and QEMUMachineInitArgs into MachineState, instance of MachineClass. As a first step, in order to make possible an incremental development, both QEMUMachine and QEMUMachineInitArgs are being embedded into the new types. Reviewed-by: Michael S. Tsirkin Signed-off-by: Marcel Apfelbaum Signed-off-by: Andreas Färber --- hw/core/Makefile.objs | 2 +- hw/core/machine.c | 28 ++++++++++++++++++++++++ include/hw/boards.h | 50 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 hw/core/machine.c diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index 9e324befd6..981593c7e6 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -8,7 +8,7 @@ common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o common-obj-$(CONFIG_XILINX_AXI) += stream.o common-obj-$(CONFIG_PTIMER) += ptimer.o common-obj-$(CONFIG_SOFTMMU) += sysbus.o +common-obj-$(CONFIG_SOFTMMU) += machine.o common-obj-$(CONFIG_SOFTMMU) += null-machine.o common-obj-$(CONFIG_SOFTMMU) += loader.o common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o - diff --git a/hw/core/machine.c b/hw/core/machine.c new file mode 100644 index 0000000000..d3ffef7e07 --- /dev/null +++ b/hw/core/machine.c @@ -0,0 +1,28 @@ +/* + * QEMU Machine + * + * Copyright (C) 2014 Red Hat Inc + * + * Authors: + * Marcel Apfelbaum + * + * 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 "hw/boards.h" + +static const TypeInfo machine_info = { + .name = TYPE_MACHINE, + .parent = TYPE_OBJECT, + .abstract = true, + .class_size = sizeof(MachineClass), + .instance_size = sizeof(MachineState), +}; + +static void machine_register_types(void) +{ + type_register_static(&machine_info); +} + +type_init(machine_register_types) diff --git a/include/hw/boards.h b/include/hw/boards.h index c2096e6ba2..1259010517 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -6,6 +6,7 @@ #include "sysemu/blockdev.h" #include "sysemu/qemumachine.h" #include "hw/qdev.h" +#include "qom/object.h" typedef struct QEMUMachineInitArgs { const QEMUMachine *machine; @@ -55,4 +56,53 @@ QEMUMachine *find_default_machine(void); extern QEMUMachine *current_machine; +#define TYPE_MACHINE "machine" +#define MACHINE(obj) \ + OBJECT_CHECK(MachineState, (obj), TYPE_MACHINE) +#define MACHINE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(MachineClass, (obj), TYPE_MACHINE) +#define MACHINE_CLASS(klass) \ + OBJECT_CLASS_CHECK(MachineClass, (klass), TYPE_MACHINE) + +typedef struct MachineState MachineState; +typedef struct MachineClass MachineClass; + +/** + * MachineClass: + * @qemu_machine: #QEMUMachine + */ +struct MachineClass { + /*< private >*/ + ObjectClass parent_class; + /*< public >*/ + + QEMUMachine *qemu_machine; +}; + +/** + * MachineState: + */ +struct MachineState { + /*< private >*/ + Object parent_obj; + /*< public >*/ + + char *accel; + bool kernel_irqchip; + int kvm_shadow_mem; + char *kernel; + char *initrd; + char *append; + char *dtb; + char *dumpdtb; + int phandle_start; + char *dt_compatible; + bool dump_guest_core; + bool mem_merge; + bool usb; + char *firmware; + + QEMUMachineInitArgs init_args; +}; + #endif From 261747f176f6f2d88f8268aaebfdd1a1afe887e2 Mon Sep 17 00:00:00 2001 From: Marcel Apfelbaum Date: Wed, 5 Mar 2014 19:30:46 +0200 Subject: [PATCH 15/31] vl: Use MachineClass instead of global QEMUMachine list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The machine registration flow is refactored to use the QOM functionality. Instead of linking the machines into a list, each machine has a type and the types can be traversed in the QOM way. Reviewed-by: Michael S. Tsirkin Signed-off-by: Marcel Apfelbaum Signed-off-by: Andreas Färber --- include/hw/boards.h | 1 + vl.c | 75 ++++++++++++++++++++++++++++++++------------- 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/include/hw/boards.h b/include/hw/boards.h index 1259010517..f9c035f33f 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -51,6 +51,7 @@ struct QEMUMachine { const char *hw_version; }; +#define TYPE_MACHINE_SUFFIX "-machine" int qemu_register_machine(QEMUMachine *m); QEMUMachine *find_default_machine(void); diff --git a/vl.c b/vl.c index bca5c95908..9e86be41bd 100644 --- a/vl.c +++ b/vl.c @@ -1571,54 +1571,81 @@ void pcmcia_info(Monitor *mon, const QDict *qdict) /***********************************************************/ /* machine registration */ -static QEMUMachine *first_machine = NULL; QEMUMachine *current_machine = NULL; +static void machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->qemu_machine = data; +} + int qemu_register_machine(QEMUMachine *m) { - QEMUMachine **pm; - pm = &first_machine; - while (*pm != NULL) - pm = &(*pm)->next; - m->next = NULL; - *pm = m; + TypeInfo ti = { + .name = g_strconcat(m->name, TYPE_MACHINE_SUFFIX, NULL), + .parent = TYPE_MACHINE, + .class_init = machine_class_init, + .class_data = (void *)m, + }; + + type_register(&ti); + return 0; } static QEMUMachine *find_machine(const char *name) { - QEMUMachine *m; + GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); + QEMUMachine *m = NULL; - for(m = first_machine; m != NULL; m = m->next) { - if (!strcmp(m->name, name)) - return m; - if (m->alias && !strcmp(m->alias, name)) - return m; + for (el = machines; el; el = el->next) { + MachineClass *mc = el->data; + + if (!strcmp(mc->qemu_machine->name, name)) { + m = mc->qemu_machine; + break; + } + if (mc->qemu_machine->alias && !strcmp(mc->qemu_machine->alias, name)) { + m = mc->qemu_machine; + break; + } } - return NULL; + + g_slist_free(machines); + return m; } QEMUMachine *find_default_machine(void) { - QEMUMachine *m; + GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); + QEMUMachine *m = NULL; - for(m = first_machine; m != NULL; m = m->next) { - if (m->is_default) { - return m; + for (el = machines; el; el = el->next) { + MachineClass *mc = el->data; + + if (mc->qemu_machine->is_default) { + m = mc->qemu_machine; + break; } } - return NULL; + + g_slist_free(machines); + return m; } MachineInfoList *qmp_query_machines(Error **errp) { + GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); MachineInfoList *mach_list = NULL; QEMUMachine *m; - for (m = first_machine; m; m = m->next) { + for (el = machines; el; el = el->next) { + MachineClass *mc = el->data; MachineInfoList *entry; MachineInfo *info; + m = mc->qemu_machine; info = g_malloc0(sizeof(*info)); if (m->is_default) { info->has_is_default = true; @@ -1639,6 +1666,7 @@ MachineInfoList *qmp_query_machines(Error **errp) mach_list = entry; } + g_slist_free(machines); return mach_list; } @@ -2608,6 +2636,7 @@ static int debugcon_parse(const char *devname) static QEMUMachine *machine_parse(const char *name) { QEMUMachine *m, *machine = NULL; + GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); if (name) { machine = find_machine(name); @@ -2616,13 +2645,17 @@ static QEMUMachine *machine_parse(const char *name) return machine; } printf("Supported machines are:\n"); - for (m = first_machine; m != NULL; m = m->next) { + for (el = machines; el; el = el->next) { + MachineClass *mc = el->data; + m = mc->qemu_machine; if (m->alias) { printf("%-20s %s (alias of %s)\n", m->alias, m->desc, m->name); } printf("%-20s %s%s\n", m->name, m->desc, m->is_default ? " (default)" : ""); } + + g_slist_free(machines); exit(!name || !is_help_option(name)); } From 0056ae24bc36798fdd96d0b31e217e9f73896736 Mon Sep 17 00:00:00 2001 From: Marcel Apfelbaum Date: Wed, 5 Mar 2014 19:30:47 +0200 Subject: [PATCH 16/31] hw/boards: Convert current_machine to MachineState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to allow attaching machine options to a machine instance, current_machine is converted into MachineState. As a first step of deprecating QEMUMachine, some of the functions were modified to return MachineClass. Signed-off-by: Marcel Apfelbaum Signed-off-by: Andreas Färber --- device-hotplug.c | 4 ++- include/hw/boards.h | 6 ++-- qmp.c | 7 +++-- vl.c | 72 ++++++++++++++++++++++++++------------------- 4 files changed, 53 insertions(+), 36 deletions(-) diff --git a/device-hotplug.c b/device-hotplug.c index 103d34ac45..ebfa6b1016 100644 --- a/device-hotplug.c +++ b/device-hotplug.c @@ -33,12 +33,14 @@ DriveInfo *add_init_drive(const char *optstr) { DriveInfo *dinfo; QemuOpts *opts; + MachineClass *mc; opts = drive_def(optstr); if (!opts) return NULL; - dinfo = drive_init(opts, current_machine->block_default_type); + mc = MACHINE_GET_CLASS(current_machine); + dinfo = drive_init(opts, mc->qemu_machine->block_default_type); if (!dinfo) { qemu_opts_del(opts); return NULL; diff --git a/include/hw/boards.h b/include/hw/boards.h index f9c035f33f..6b17397e8d 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -53,9 +53,6 @@ struct QEMUMachine { #define TYPE_MACHINE_SUFFIX "-machine" int qemu_register_machine(QEMUMachine *m); -QEMUMachine *find_default_machine(void); - -extern QEMUMachine *current_machine; #define TYPE_MACHINE "machine" #define MACHINE(obj) \ @@ -68,6 +65,9 @@ extern QEMUMachine *current_machine; typedef struct MachineState MachineState; typedef struct MachineClass MachineClass; +MachineClass *find_default_machine(void); +extern MachineState *current_machine; + /** * MachineClass: * @qemu_machine: #QEMUMachine diff --git a/qmp.c b/qmp.c index f556a04d19..87a28f797d 100644 --- a/qmp.c +++ b/qmp.c @@ -114,8 +114,11 @@ void qmp_cpu(int64_t index, Error **errp) void qmp_cpu_add(int64_t id, Error **errp) { - if (current_machine->hot_add_cpu) { - current_machine->hot_add_cpu(id, errp); + MachineClass *mc; + + mc = MACHINE_GET_CLASS(current_machine); + if (mc->qemu_machine->hot_add_cpu) { + mc->qemu_machine->hot_add_cpu(id, errp); } else { error_setg(errp, "Not supported"); } diff --git a/vl.c b/vl.c index 9e86be41bd..862cf20f3c 100644 --- a/vl.c +++ b/vl.c @@ -1571,7 +1571,7 @@ void pcmcia_info(Monitor *mon, const QDict *qdict) /***********************************************************/ /* machine registration */ -QEMUMachine *current_machine = NULL; +MachineState *current_machine; static void machine_class_init(ObjectClass *oc, void *data) { @@ -1594,44 +1594,45 @@ int qemu_register_machine(QEMUMachine *m) return 0; } -static QEMUMachine *find_machine(const char *name) +static MachineClass *find_machine(const char *name) { GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); - QEMUMachine *m = NULL; + MachineClass *mc = NULL; for (el = machines; el; el = el->next) { - MachineClass *mc = el->data; + MachineClass *temp = el->data; - if (!strcmp(mc->qemu_machine->name, name)) { - m = mc->qemu_machine; + if (!strcmp(temp->qemu_machine->name, name)) { + mc = temp; break; } - if (mc->qemu_machine->alias && !strcmp(mc->qemu_machine->alias, name)) { - m = mc->qemu_machine; + if (temp->qemu_machine->alias && + !strcmp(temp->qemu_machine->alias, name)) { + mc = temp; break; } } g_slist_free(machines); - return m; + return mc; } -QEMUMachine *find_default_machine(void) +MachineClass *find_default_machine(void) { GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); - QEMUMachine *m = NULL; + MachineClass *mc = NULL; for (el = machines; el; el = el->next) { - MachineClass *mc = el->data; + MachineClass *temp = el->data; - if (mc->qemu_machine->is_default) { - m = mc->qemu_machine; + if (temp->qemu_machine->is_default) { + mc = temp; break; } } g_slist_free(machines); - return m; + return mc; } MachineInfoList *qmp_query_machines(Error **errp) @@ -1860,8 +1861,12 @@ void qemu_devices_reset(void) void qemu_system_reset(bool report) { - if (current_machine && current_machine->reset) { - current_machine->reset(); + MachineClass *mc; + + mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL; + + if (mc && mc->qemu_machine->reset) { + mc->qemu_machine->reset(); } else { qemu_devices_reset(); } @@ -2633,21 +2638,21 @@ static int debugcon_parse(const char *devname) return 0; } -static QEMUMachine *machine_parse(const char *name) +static MachineClass *machine_parse(const char *name) { - QEMUMachine *m, *machine = NULL; + MachineClass *mc = NULL; GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); if (name) { - machine = find_machine(name); + mc = find_machine(name); } - if (machine) { - return machine; + if (mc) { + return mc; } printf("Supported machines are:\n"); for (el = machines; el; el = el->next) { MachineClass *mc = el->data; - m = mc->qemu_machine; + QEMUMachine *m = mc->qemu_machine; if (m->alias) { printf("%-20s %s (alias of %s)\n", m->alias, m->desc, m->name); } @@ -2904,6 +2909,7 @@ int main(int argc, char **argv, char **envp) int optind; const char *optarg; const char *loadvm = NULL; + MachineClass *machine_class; QEMUMachine *machine; const char *cpu_model; const char *vga_model = "none"; @@ -2978,7 +2984,7 @@ int main(int argc, char **argv, char **envp) os_setup_early_signal_handling(); module_call_init(MODULE_INIT_MACHINE); - machine = find_default_machine(); + machine_class = find_default_machine(); cpu_model = NULL; ram_size = 0; snapshot = 0; @@ -3044,7 +3050,7 @@ int main(int argc, char **argv, char **envp) } switch(popt->index) { case QEMU_OPTION_M: - machine = machine_parse(optarg); + machine_class = machine_parse(optarg); break; case QEMU_OPTION_no_kvm_irqchip: { olist = qemu_find_opts("machine"); @@ -3600,7 +3606,7 @@ int main(int argc, char **argv, char **envp) } optarg = qemu_opt_get(opts, "type"); if (optarg) { - machine = machine_parse(optarg); + machine_class = machine_parse(optarg); } break; case QEMU_OPTION_no_kvm: @@ -3906,11 +3912,17 @@ int main(int argc, char **argv, char **envp) } #endif - if (machine == NULL) { + if (machine_class == NULL) { fprintf(stderr, "No machine found.\n"); exit(1); } + current_machine = MACHINE(object_new(object_class_get_name( + OBJECT_CLASS(machine_class)))); + object_property_add_child(object_get_root(), "machine", + OBJECT(current_machine), &error_abort); + + machine = machine_class->qemu_machine; if (machine->hw_version) { qemu_set_version(machine->hw_version); } @@ -4339,7 +4351,9 @@ int main(int argc, char **argv, char **envp) .kernel_cmdline = kernel_cmdline, .initrd_filename = initrd_filename, .cpu_model = cpu_model }; - machine->init(&args); + + current_machine->init_args = args; + machine->init(¤t_machine->init_args); audio_init(); @@ -4347,8 +4361,6 @@ int main(int argc, char **argv, char **envp) set_numa_modes(); - current_machine = machine; - /* init USB devices */ if (usb_enabled(false)) { if (foreach_device_config(DEV_USB, usb_parse) < 0) From dc06cbd28611c366096fd1c9b8bba7b459a96877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 7 Feb 2014 15:36:16 +0100 Subject: [PATCH 17/31] qom-test: Test QOM properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recursively walk all properties under /machine and try to retrieve their value. This is a regression test for link<> properties and the DeviceState::hotpluggable property. Cf. be2f78b6b062eec5170e2612299fb8953046993f and 1a37eca107cece3ed454bae29eef0bd1fac4a244 Signed-off-by: Andreas Färber --- tests/qom-test.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/qom-test.c b/tests/qom-test.c index b6671fbec3..6d9a00b448 100644 --- a/tests/qom-test.c +++ b/tests/qom-test.c @@ -10,6 +10,7 @@ #include #include +#include "qemu-common.h" #include "libqtest.h" #include "qemu/osdep.h" #include "qapi/qmp/types.h" @@ -43,6 +44,40 @@ static bool is_blacklisted(const char *arch, const char *mach) return false; } +static void test_properties(const char *path) +{ + char *child_path; + QDict *response, *tuple; + QList *list; + QListEntry *entry; + + g_test_message("Obtaining properties of %s", path); + response = qmp("{ 'execute': 'qom-list'," + " 'arguments': { 'path': '%s' } }", path); + g_assert(response); + + g_assert(qdict_haskey(response, "return")); + list = qobject_to_qlist(qdict_get(response, "return")); + QLIST_FOREACH_ENTRY(list, entry) { + tuple = qobject_to_qdict(qlist_entry_obj(entry)); + if (strstart(qdict_get_str(tuple, "type"), "child<", NULL)) { + child_path = g_strdup_printf("%s/%s", + path, qdict_get_str(tuple, "name")); + test_properties(child_path); + g_free(child_path); + } else { + const char *prop = qdict_get_str(tuple, "name"); + g_test_message("Testing property %s.%s", path, prop); + response = qmp("{ 'execute': 'qom-get'," + " 'arguments': { 'path': '%s'," + " 'property': '%s' } }", + path, prop); + /* qom-get may fail but should not, e.g., segfault. */ + g_assert(response); + } + } +} + static void test_machine(gconstpointer data) { const char *machine = data; @@ -51,8 +86,12 @@ static void test_machine(gconstpointer data) args = g_strdup_printf("-machine %s", machine); qtest_start(args); + + test_properties("/machine"); + response = qmp("{ 'execute': 'quit' }"); g_assert(qdict_haskey(response, "return")); + qtest_end(); g_free(args); } From 83bb0b2ffd589346c8b8f4fee9296d0a8a309cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 21 Feb 2014 16:29:17 +0100 Subject: [PATCH 18/31] tests: Clean up IndustryPack TPCI200 gcov paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- tests/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index e146f81d44..1dc24c86a0 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -87,9 +87,9 @@ gcov-files-pci-y += hw/net/ne2000.c check-qtest-pci-y += $(check-qtest-virtio-y) gcov-files-pci-y += $(gcov-files-virtio-y) hw/virtio/virtio-pci.c check-qtest-pci-y += tests/tpci200-test$(EXESUF) -gcov-files-pci-y += hw/char/tpci200.c +gcov-files-pci-y += hw/ipack/tpci200.c check-qtest-pci-y += $(check-qtest-ipack-y) -gcov-files-pci-y += $(gcov-files-ipack-y) hw/ipack/tpci200.c +gcov-files-pci-y += $(gcov-files-ipack-y) check-qtest-i386-y = tests/endianness-test$(EXESUF) check-qtest-i386-y += tests/fdc-test$(EXESUF) From c7a59bed62184d2d5ef5c6ed87c7ee6c23c57802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 9 Feb 2014 04:32:55 +0100 Subject: [PATCH 19/31] tests: Add virtio-blk qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Kevin Wolf Reviewed-by: Stefan Hajnoczi Signed-off-by: Andreas Färber --- tests/Makefile | 3 +++ tests/virtio-blk-test.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 tests/virtio-blk-test.c diff --git a/tests/Makefile b/tests/Makefile index 1dc24c86a0..d5a3f10d4d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -72,6 +72,8 @@ gcov-files-ipack-y += hw/char/ipoctal232.c gcov-files-virtio-y += i386-softmmu/hw/virtio/virtio.c check-qtest-virtio-y += tests/virtio-net-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/net/virtio-net.c +check-qtest-virtio-y += tests/virtio-blk-test$(EXESUF) +gcov-files-virtio-y += i386-softmmu/hw/block/virtio-blk.c check-qtest-pci-y += tests/e1000-test$(EXESUF) gcov-files-pci-y += hw/net/e1000.c @@ -239,6 +241,7 @@ tests/pcnet-test$(EXESUF): tests/pcnet-test.o tests/eepro100-test$(EXESUF): tests/eepro100-test.o tests/vmxnet3-test$(EXESUF): tests/vmxnet3-test.o tests/ne2000-test$(EXESUF): tests/ne2000-test.o +tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o tests/tpci200-test$(EXESUF): tests/tpci200-test.o tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c new file mode 100644 index 0000000000..d53f875b89 --- /dev/null +++ b/tests/virtio-blk-test.c @@ -0,0 +1,34 @@ +/* + * QTest testcase for VirtIO Block Device + * + * Copyright (c) 2014 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 +#include +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void pci_nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/virtio/blk/pci/nop", pci_nop); + + qtest_start("-drive id=drv0,if=none,file=/dev/null " + "-device virtio-blk-pci,drive=drv0"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} From 02063aaa653c35291f06d58400a3349305000dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 9 Feb 2014 04:39:47 +0100 Subject: [PATCH 20/31] tests: Add virtio-balloon qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Signed-off-by: Andreas Färber --- tests/Makefile | 3 +++ tests/virtio-balloon-test.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/virtio-balloon-test.c diff --git a/tests/Makefile b/tests/Makefile index d5a3f10d4d..d4f23dfc17 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -72,6 +72,8 @@ gcov-files-ipack-y += hw/char/ipoctal232.c gcov-files-virtio-y += i386-softmmu/hw/virtio/virtio.c check-qtest-virtio-y += tests/virtio-net-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/net/virtio-net.c +check-qtest-virtio-y += tests/virtio-balloon-test$(EXESUF) +gcov-files-virtio-y += i386-softmmu/hw/virtio/virtio-balloon.c check-qtest-virtio-y += tests/virtio-blk-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/block/virtio-blk.c @@ -241,6 +243,7 @@ tests/pcnet-test$(EXESUF): tests/pcnet-test.o tests/eepro100-test$(EXESUF): tests/eepro100-test.o tests/vmxnet3-test$(EXESUF): tests/vmxnet3-test.o tests/ne2000-test$(EXESUF): tests/ne2000-test.o +tests/virtio-balloon-test$(EXESUF): tests/virtio-balloon-test.o tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o tests/tpci200-test$(EXESUF): tests/tpci200-test.o diff --git a/tests/virtio-balloon-test.c b/tests/virtio-balloon-test.c new file mode 100644 index 0000000000..becebb51a7 --- /dev/null +++ b/tests/virtio-balloon-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for VirtIO Balloon + * + * Copyright (c) 2014 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 +#include +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void pci_nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/virtio/balloon/pci/nop", pci_nop); + + qtest_start("-device virtio-balloon-pci"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} From b6f46f02f4756d0cd6c45515c1728a899fbb1dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 9 Feb 2014 04:43:10 +0100 Subject: [PATCH 21/31] tests: Add virtio-rng qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Signed-off-by: Andreas Färber --- tests/Makefile | 3 +++ tests/virtio-rng-test.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/virtio-rng-test.c diff --git a/tests/Makefile b/tests/Makefile index d4f23dfc17..308a5a2248 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -76,6 +76,8 @@ check-qtest-virtio-y += tests/virtio-balloon-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/virtio/virtio-balloon.c check-qtest-virtio-y += tests/virtio-blk-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/block/virtio-blk.c +check-qtest-virtio-y += tests/virtio-rng-test$(EXESUF) +gcov-files-virtio-y += hw/virtio/virtio-rng.c check-qtest-pci-y += tests/e1000-test$(EXESUF) gcov-files-pci-y += hw/net/e1000.c @@ -246,6 +248,7 @@ tests/ne2000-test$(EXESUF): tests/ne2000-test.o tests/virtio-balloon-test$(EXESUF): tests/virtio-balloon-test.o tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o +tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o tests/tpci200-test$(EXESUF): tests/tpci200-test.o tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o tests/qom-test$(EXESUF): tests/qom-test.o diff --git a/tests/virtio-rng-test.c b/tests/virtio-rng-test.c new file mode 100644 index 0000000000..402c2060da --- /dev/null +++ b/tests/virtio-rng-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for VirtIO RNG + * + * Copyright (c) 2014 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 +#include +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void pci_nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/virtio/rng/pci/nop", pci_nop); + + qtest_start("-device virtio-rng-pci"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} From 26c9a015ef8ad158a62690f72ee04d10545db80d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 21 Feb 2014 16:42:15 +0100 Subject: [PATCH 22/31] tests: Add virtio-scsi qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Paolo Bonzini Signed-off-by: Andreas Färber --- tests/Makefile | 3 +++ tests/virtio-scsi-test.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 tests/virtio-scsi-test.c diff --git a/tests/Makefile b/tests/Makefile index 308a5a2248..75b46599f6 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -78,6 +78,8 @@ check-qtest-virtio-y += tests/virtio-blk-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/block/virtio-blk.c check-qtest-virtio-y += tests/virtio-rng-test$(EXESUF) gcov-files-virtio-y += hw/virtio/virtio-rng.c +check-qtest-virtio-y += tests/virtio-scsi-test$(EXESUF) +gcov-files-virtio-y += i386-softmmu/hw/scsi/virtio-scsi.c check-qtest-pci-y += tests/e1000-test$(EXESUF) gcov-files-pci-y += hw/net/e1000.c @@ -249,6 +251,7 @@ tests/virtio-balloon-test$(EXESUF): tests/virtio-balloon-test.o tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o +tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o tests/tpci200-test$(EXESUF): tests/tpci200-test.o tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o tests/qom-test$(EXESUF): tests/qom-test.o diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c new file mode 100644 index 0000000000..3230908b98 --- /dev/null +++ b/tests/virtio-scsi-test.c @@ -0,0 +1,35 @@ +/* + * QTest testcase for VirtIO SCSI + * + * Copyright (c) 2014 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 +#include +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void pci_nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/virtio/scsi/pci/nop", pci_nop); + + qtest_start("-drive id=drv0,if=none,file=/dev/null " + "-device virtio-scsi-pci,id=vscsi0 " + "-device scsi-hd,bus=vscsi0.0,drive=drv0"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} From aa97405e3289059ab614e906ce4f1141971dfd9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 21 Feb 2014 17:36:57 +0100 Subject: [PATCH 23/31] tests: Add virtio-serial qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- tests/Makefile | 3 +++ tests/virtio-serial-test.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/virtio-serial-test.c diff --git a/tests/Makefile b/tests/Makefile index 75b46599f6..179667f31b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -80,6 +80,8 @@ check-qtest-virtio-y += tests/virtio-rng-test$(EXESUF) gcov-files-virtio-y += hw/virtio/virtio-rng.c check-qtest-virtio-y += tests/virtio-scsi-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/scsi/virtio-scsi.c +check-qtest-virtio-y += tests/virtio-serial-test$(EXESUF) +gcov-files-virtio-y += i386-softmmu/hw/char/virtio-serial-bus.c check-qtest-pci-y += tests/e1000-test$(EXESUF) gcov-files-pci-y += hw/net/e1000.c @@ -252,6 +254,7 @@ tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o +tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o tests/tpci200-test$(EXESUF): tests/tpci200-test.o tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o tests/qom-test$(EXESUF): tests/qom-test.o diff --git a/tests/virtio-serial-test.c b/tests/virtio-serial-test.c new file mode 100644 index 0000000000..e7438751ea --- /dev/null +++ b/tests/virtio-serial-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for VirtIO Serial + * + * Copyright (c) 2014 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 +#include +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void pci_nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/virtio/serial/pci/nop", pci_nop); + + qtest_start("-device virtio-serial-pci"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} From 6e8114a0650e78b6476e312de59361ef11c62b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 21 Feb 2014 17:49:12 +0100 Subject: [PATCH 24/31] tests: Add virtio-console qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- tests/Makefile | 6 ++++++ tests/virtio-console-test.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/virtio-console-test.c diff --git a/tests/Makefile b/tests/Makefile index 179667f31b..76a2468cfa 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -69,6 +69,9 @@ gcov-files-ipack-y += hw/ipack/ipack.c check-qtest-ipack-y += tests/ipoctal232-test$(EXESUF) gcov-files-ipack-y += hw/char/ipoctal232.c +check-qtest-virtioserial-y += tests/virtio-console-test$(EXESUF) +gcov-files-virtioserial-y += hw/char/virtio-console.c + gcov-files-virtio-y += i386-softmmu/hw/virtio/virtio.c check-qtest-virtio-y += tests/virtio-net-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/net/virtio-net.c @@ -82,6 +85,8 @@ check-qtest-virtio-y += tests/virtio-scsi-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/scsi/virtio-scsi.c check-qtest-virtio-y += tests/virtio-serial-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/char/virtio-serial-bus.c +check-qtest-virtio-y += $(check-qtest-virtioserial-y) +gcov-files-virtio-y += $(gcov-files-virtioserial-y) check-qtest-pci-y += tests/e1000-test$(EXESUF) gcov-files-pci-y += hw/net/e1000.c @@ -255,6 +260,7 @@ tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o +tests/virtio-console-test$(EXESUF): tests/virtio-console-test.o tests/tpci200-test$(EXESUF): tests/tpci200-test.o tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o tests/qom-test$(EXESUF): tests/qom-test.o diff --git a/tests/virtio-console-test.c b/tests/virtio-console-test.c new file mode 100644 index 0000000000..f98f5af252 --- /dev/null +++ b/tests/virtio-console-test.c @@ -0,0 +1,34 @@ +/* + * QTest testcase for VirtIO Console + * + * Copyright (c) 2014 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 +#include +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void pci_nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/virtio/console/pci/nop", pci_nop); + + qtest_start("-device virtio-serial-pci,id=vser0 " + "-device virtconsole,bus=vser0.0"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} From 0399a3819b27083ba69b88a9baa9025facab85bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 7 Jun 2013 19:10:02 +0200 Subject: [PATCH 25/31] virtio-console: QOM cast cleanup for VirtConsole MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce type constant, cast macro and rename parent field. Signed-off-by: Andreas Färber --- hw/char/virtio-console.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 2e00ad2a7c..73e18f2219 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -15,8 +15,13 @@ #include "trace.h" #include "hw/virtio/virtio-serial.h" +#define TYPE_VIRTIO_CONSOLE "virtconsole" +#define VIRTIO_CONSOLE(obj) \ + OBJECT_CHECK(VirtConsole, (obj), TYPE_VIRTIO_CONSOLE) + typedef struct VirtConsole { - VirtIOSerialPort port; + VirtIOSerialPort parent_obj; + CharDriverState *chr; guint watch; } VirtConsole; @@ -31,7 +36,7 @@ static gboolean chr_write_unblocked(GIOChannel *chan, GIOCondition cond, VirtConsole *vcon = opaque; vcon->watch = 0; - virtio_serial_throttle_port(&vcon->port, false); + virtio_serial_throttle_port(VIRTIO_SERIAL_PORT(vcon), false); return FALSE; } @@ -39,7 +44,7 @@ static gboolean chr_write_unblocked(GIOChannel *chan, GIOCondition cond, static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, ssize_t len) { - VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); + VirtConsole *vcon = VIRTIO_CONSOLE(port); ssize_t ret; if (!vcon->chr) { @@ -75,7 +80,7 @@ static ssize_t flush_buf(VirtIOSerialPort *port, /* Callback function that's called when the guest opens/closes the port */ static void set_guest_connected(VirtIOSerialPort *port, int guest_connected) { - VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); + VirtConsole *vcon = VIRTIO_CONSOLE(port); if (!vcon->chr) { return; @@ -88,40 +93,42 @@ static int chr_can_read(void *opaque) { VirtConsole *vcon = opaque; - return virtio_serial_guest_ready(&vcon->port); + return virtio_serial_guest_ready(VIRTIO_SERIAL_PORT(vcon)); } /* Send data from a char device over to the guest */ static void chr_read(void *opaque, const uint8_t *buf, int size) { VirtConsole *vcon = opaque; + VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon); - trace_virtio_console_chr_read(vcon->port.id, size); - virtio_serial_write(&vcon->port, buf, size); + trace_virtio_console_chr_read(port->id, size); + virtio_serial_write(port, buf, size); } static void chr_event(void *opaque, int event) { VirtConsole *vcon = opaque; + VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon); - trace_virtio_console_chr_event(vcon->port.id, event); + trace_virtio_console_chr_event(port->id, event); switch (event) { case CHR_EVENT_OPENED: - virtio_serial_open(&vcon->port); + virtio_serial_open(port); break; case CHR_EVENT_CLOSED: if (vcon->watch) { g_source_remove(vcon->watch); vcon->watch = 0; } - virtio_serial_close(&vcon->port); + virtio_serial_close(port); break; } } static int virtconsole_initfn(VirtIOSerialPort *port) { - VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); + VirtConsole *vcon = VIRTIO_CONSOLE(port); VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port); if (port->id == 0 && !k->is_console) { @@ -140,7 +147,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port) static int virtconsole_exitfn(VirtIOSerialPort *port) { - VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); + VirtConsole *vcon = VIRTIO_CONSOLE(port); if (vcon->watch) { g_source_remove(vcon->watch); @@ -168,7 +175,7 @@ static void virtconsole_class_init(ObjectClass *klass, void *data) } static const TypeInfo virtconsole_info = { - .name = "virtconsole", + .name = TYPE_VIRTIO_CONSOLE, .parent = TYPE_VIRTIO_SERIAL_PORT, .instance_size = sizeof(VirtConsole), .class_init = virtconsole_class_init, From 2ef66625f3a8978dcbbad773e6813f747971381e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 7 Jun 2013 19:02:12 +0200 Subject: [PATCH 26/31] virtio-serial-port: Convert to QOM realize/unrealize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- hw/char/virtio-console.c | 28 ++++++++--------- hw/char/virtio-serial-bus.c | 51 ++++++++++++++++--------------- include/hw/virtio/virtio-serial.h | 8 ++--- 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 73e18f2219..ffd29a80bc 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -126,14 +126,16 @@ static void chr_event(void *opaque, int event) } } -static int virtconsole_initfn(VirtIOSerialPort *port) +static void virtconsole_realize(DeviceState *dev, Error **errp) { - VirtConsole *vcon = VIRTIO_CONSOLE(port); - VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port); + VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); + VirtConsole *vcon = VIRTIO_CONSOLE(dev); + VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev); if (port->id == 0 && !k->is_console) { - error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility."); - return -1; + error_setg(errp, "Port number 0 on virtio-serial devices reserved " + "for virtconsole devices for backward compatibility."); + return; } if (vcon->chr) { @@ -141,19 +143,15 @@ static int virtconsole_initfn(VirtIOSerialPort *port) qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, vcon); } - - return 0; } -static int virtconsole_exitfn(VirtIOSerialPort *port) +static void virtconsole_unrealize(DeviceState *dev, Error **errp) { - VirtConsole *vcon = VIRTIO_CONSOLE(port); + VirtConsole *vcon = VIRTIO_CONSOLE(dev); if (vcon->watch) { g_source_remove(vcon->watch); } - - return 0; } static Property virtconsole_properties[] = { @@ -167,8 +165,8 @@ static void virtconsole_class_init(ObjectClass *klass, void *data) VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass); k->is_console = true; - k->init = virtconsole_initfn; - k->exit = virtconsole_exitfn; + k->realize = virtconsole_realize; + k->unrealize = virtconsole_unrealize; k->have_data = flush_buf; k->set_guest_connected = set_guest_connected; dc->props = virtconsole_properties; @@ -191,8 +189,8 @@ static void virtserialport_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass); - k->init = virtconsole_initfn; - k->exit = virtconsole_exitfn; + k->realize = virtconsole_realize; + k->unrealize = virtconsole_unrealize; k->have_data = flush_buf; k->set_guest_connected = set_guest_connected; dc->props = virtserialport_properties; diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 226e9f9a3c..2b647b68d5 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -808,13 +808,14 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id) send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1); } -static int virtser_port_qdev_init(DeviceState *qdev) +static void virtser_port_device_realize(DeviceState *dev, Error **errp) { - VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev); + VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); - VirtIOSerialBus *bus = DO_UPCAST(VirtIOSerialBus, qbus, qdev->parent_bus); - int ret, max_nr_ports; + VirtIOSerialBus *bus = VIRTIO_SERIAL_BUS(qdev_get_parent_bus(dev)); + int max_nr_ports; bool plugging_port0; + Error *err = NULL; port->vser = bus->vser; port->bh = qemu_bh_new(flush_queued_data_bh, port); @@ -829,9 +830,9 @@ static int virtser_port_qdev_init(DeviceState *qdev) plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0); if (find_port_by_id(port->vser, port->id)) { - error_report("virtio-serial-bus: A port already exists at id %u", - port->id); - return -1; + error_setg(errp, "virtio-serial-bus: A port already exists at id %u", + port->id); + return; } if (port->id == VIRTIO_CONSOLE_BAD_ID) { @@ -840,22 +841,24 @@ static int virtser_port_qdev_init(DeviceState *qdev) } else { port->id = find_free_port_id(port->vser); if (port->id == VIRTIO_CONSOLE_BAD_ID) { - error_report("virtio-serial-bus: Maximum port limit for this device reached"); - return -1; + error_setg(errp, "virtio-serial-bus: Maximum port limit for " + "this device reached"); + return; } } } max_nr_ports = tswap32(port->vser->config.max_nr_ports); if (port->id >= max_nr_ports) { - error_report("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u", - max_nr_ports - 1); - return -1; + error_setg(errp, "virtio-serial-bus: Out-of-range port id specified, " + "max. allowed: %u", max_nr_ports - 1); + return; } - ret = vsc->init(port); - if (ret) { - return ret; + vsc->realize(dev, &err); + if (err != NULL) { + error_propagate(errp, err); + return; } port->elem.out_num = 0; @@ -868,14 +871,12 @@ static int virtser_port_qdev_init(DeviceState *qdev) /* Send an update to the guest about this new port added */ virtio_notify_config(VIRTIO_DEVICE(port->vser)); - - return ret; } -static int virtser_port_qdev_exit(DeviceState *qdev) +static void virtser_port_device_unrealize(DeviceState *dev, Error **errp) { - VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev); - VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); + VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); + VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(dev); VirtIOSerial *vser = port->vser; qemu_bh_delete(port->bh); @@ -883,10 +884,9 @@ static int virtser_port_qdev_exit(DeviceState *qdev) QTAILQ_REMOVE(&vser->ports, port, next); - if (vsc->exit) { - vsc->exit(port); + if (vsc->unrealize) { + vsc->unrealize(dev, errp); } - return 0; } static void virtio_serial_device_realize(DeviceState *dev, Error **errp) @@ -971,10 +971,11 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) static void virtio_serial_port_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); - k->init = virtser_port_qdev_init; + set_bit(DEVICE_CATEGORY_INPUT, k->categories); k->bus_type = TYPE_VIRTIO_SERIAL_BUS; - k->exit = virtser_port_qdev_exit; + k->realize = virtser_port_device_realize; + k->unrealize = virtser_port_device_unrealize; k->unplug = qdev_simple_unplug_cb; k->props = virtser_props; } diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h index 1d2040b245..4746312a83 100644 --- a/include/hw/virtio/virtio-serial.h +++ b/include/hw/virtio/virtio-serial.h @@ -81,15 +81,15 @@ typedef struct VirtIOSerialPortClass { bool is_console; /* - * The per-port (or per-app) init function that's called when a + * The per-port (or per-app) realize function that's called when a * new device is found on the bus. */ - int (*init)(VirtIOSerialPort *port); + DeviceRealize realize; /* - * Per-port exit function that's called when a port gets + * Per-port unrealize function that's called when a port gets * hot-unplugged or removed. */ - int (*exit)(VirtIOSerialPort *port); + DeviceUnrealize unrealize; /* Callbacks for guest events */ /* Guest opened/closed device. */ From 04e9a20b495f37f3132f4ada80fd925b4794b253 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Mon, 10 Feb 2014 14:52:56 +1100 Subject: [PATCH 27/31] tests: Add spapr-pci-host-bridge qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a test whether sPAPR PHB can be added via the command line. Signed-off-by: Alexey Kardashevskiy Signed-off-by: Andreas Färber --- tests/Makefile | 3 +++ tests/spapr-phb-test.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 tests/spapr-phb-test.c diff --git a/tests/Makefile b/tests/Makefile index 76a2468cfa..7bc3999ecc 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -144,6 +144,8 @@ check-qtest-arm-y = tests/tmp105-test$(EXESUF) gcov-files-arm-y += hw/misc/tmp105.c check-qtest-ppc-y += tests/boot-order-test$(EXESUF) check-qtest-ppc64-y += tests/boot-order-test$(EXESUF) +check-qtest-ppc64-y += tests/spapr-phb-test$(EXESUF) +gcov-files-ppc64-y += ppc64-softmmu/hw/ppc/spapr_pci.c check-qtest-microblazeel-y = $(check-qtest-microblaze-y) check-qtest-xtensaeb-y = $(check-qtest-xtensa-y) @@ -240,6 +242,7 @@ libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o tests/rtc-test$(EXESUF): tests/rtc-test.o tests/m48t59-test$(EXESUF): tests/m48t59-test.o tests/endianness-test$(EXESUF): tests/endianness-test.o +tests/spapr-phb-test$(EXESUF): tests/spapr-phb-test.o $(libqos-obj-y) tests/fdc-test$(EXESUF): tests/fdc-test.o tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y) tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o diff --git a/tests/spapr-phb-test.c b/tests/spapr-phb-test.c new file mode 100644 index 0000000000..b629de475a --- /dev/null +++ b/tests/spapr-phb-test.c @@ -0,0 +1,35 @@ +/* + * QTest testcase for SPAPR PHB + * + * Authors: + * Alexey Kardashevskiy + * + * 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 + +#include "libqtest.h" + +#define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void test_phb_device(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/spapr-phb/device", test_phb_device); + + qtest_start("-device " TYPE_SPAPR_PCI_HOST_BRIDGE ",index=100"); + + ret = g_test_run(); + + qtest_end(); + + return ret; +} From 02e7f85dac3c639b70460ce557cb6c29963db97a Mon Sep 17 00:00:00 2001 From: Bandan Das Date: Mon, 25 Nov 2013 17:48:40 -0500 Subject: [PATCH 28/31] qdev: Prepare realize/unrealize hooks for BusState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a "realized" property calling realize/unrealize hooks as for devices. Signed-off-by: Bandan Das Signed-off-by: Andreas Färber --- hw/core/qdev.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/hw/qdev-core.h | 6 ++++++ 2 files changed, 47 insertions(+) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 71b70454eb..7e58259911 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -501,6 +501,45 @@ static void bus_unparent(Object *obj) } } +static bool bus_get_realized(Object *obj, Error **err) +{ + BusState *bus = BUS(obj); + + return bus->realized; +} + +static void bus_set_realized(Object *obj, bool value, Error **err) +{ + BusState *bus = BUS(obj); + BusClass *bc = BUS_GET_CLASS(bus); + Error *local_err = NULL; + + if (value && !bus->realized) { + if (bc->realize) { + bc->realize(bus, &local_err); + + if (local_err != NULL) { + goto error; + } + + } + } else if (!value && bus->realized) { + if (bc->unrealize) { + bc->unrealize(bus, &local_err); + + if (local_err != NULL) { + goto error; + } + } + } + + bus->realized = value; + return; + +error: + error_propagate(err, local_err); +} + void qbus_create_inplace(void *bus, size_t size, const char *typename, DeviceState *parent, const char *name) { @@ -889,6 +928,8 @@ static void qbus_initfn(Object *obj) object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY, TYPE_HOTPLUG_HANDLER, (Object **)&bus->hotplug_handler, NULL); + object_property_add_bool(obj, "realized", + bus_get_realized, bus_set_realized, NULL); } static char *default_bus_get_fw_dev_path(DeviceState *dev) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 1ed0691716..dbe473c344 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -36,6 +36,8 @@ typedef int (*qdev_event)(DeviceState *dev); typedef void (*qdev_resetfn)(DeviceState *dev); typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp); +typedef void (*BusRealize)(BusState *bus, Error **errp); +typedef void (*BusUnrealize)(BusState *bus, Error **errp); struct VMStateDescription; @@ -174,6 +176,9 @@ struct BusClass { */ char *(*get_fw_dev_path)(DeviceState *dev); void (*reset)(BusState *bus); + BusRealize realize; + BusUnrealize unrealize; + /* maximum devices allowed on the bus, 0: no limit. */ int max_dev; /* number of automatically allocated bus ids (e.g. ide.0) */ @@ -199,6 +204,7 @@ struct BusState { int allow_hotplug; HotplugHandler *hotplug_handler; int max_index; + bool realized; QTAILQ_HEAD(ChildrenHead, BusChild) children; QLIST_ENTRY(BusState) sibling; }; From 5c21ce77d7e5643089ceec556c0408445d017f32 Mon Sep 17 00:00:00 2001 From: Bandan Das Date: Wed, 12 Mar 2014 21:02:12 +0100 Subject: [PATCH 29/31] qdev: Realize buses on device realization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Integrate (un)realization of child buses with realization/unrealization of the device hosting them. Code in device_unparent() is reordered for unrealization of buses to work as part of device unrealization. That way no changes need to be made to bus instantiation. Signed-off-by: Bandan Das Signed-off-by: Andreas Färber --- hw/core/qdev.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 7e58259911..9f0a522ee8 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -716,6 +716,7 @@ static void device_set_realized(Object *obj, bool value, Error **err) { DeviceState *dev = DEVICE(obj); DeviceClass *dc = DEVICE_GET_CLASS(dev); + BusState *bus; Error *local_err = NULL; if (dev->hotplugged && !dc->hotpluggable) { @@ -749,14 +750,30 @@ static void device_set_realized(Object *obj, bool value, Error **err) dev->instance_id_alias, dev->alias_required_for_version); } + if (local_err == NULL) { + QLIST_FOREACH(bus, &dev->child_bus, sibling) { + object_property_set_bool(OBJECT(bus), true, "realized", + &local_err); + if (local_err != NULL) { + break; + } + } + } if (dev->hotplugged && local_err == NULL) { device_reset(dev); } } else if (!value && dev->realized) { - if (qdev_get_vmsd(dev)) { + QLIST_FOREACH(bus, &dev->child_bus, sibling) { + object_property_set_bool(OBJECT(bus), false, "realized", + &local_err); + if (local_err != NULL) { + break; + } + } + if (qdev_get_vmsd(dev) && local_err == NULL) { vmstate_unregister(dev, qdev_get_vmsd(dev), dev); } - if (dc->unrealize) { + if (dc->unrealize && local_err == NULL) { dc->unrealize(dev, &local_err); } } @@ -841,13 +858,13 @@ static void device_unparent(Object *obj) QObject *event_data; bool have_realized = dev->realized; + if (dev->realized) { + object_property_set_bool(obj, false, "realized", NULL); + } while (dev->num_child_bus) { bus = QLIST_FIRST(&dev->child_bus); object_unparent(OBJECT(bus)); } - if (dev->realized) { - object_property_set_bool(obj, false, "realized", NULL); - } if (dev->parent_bus) { bus_remove_child(dev->parent_bus, dev); object_unref(OBJECT(dev->parent_bus)); From d2f69df746f06d785ffbf6cc9711f7df9d014e35 Mon Sep 17 00:00:00 2001 From: Bandan Das Date: Mon, 25 Nov 2013 17:48:42 -0500 Subject: [PATCH 30/31] pci: Move VMState registration/unregistration to QOM realize/unrealize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the realize and unrealize hooks to register and unregister vmstate_pcibus respectively. Relocate some stuff to avoid forward declarations. Signed-off-by: Bandan Das Acked-by: Michael S. Tsirkin [AF: Keep using PCI_BUS() cast macro] Signed-off-by: Andreas Färber --- hw/pci/pci.c | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 4e0701df38..8f722dd961 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -48,7 +48,6 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent); static char *pcibus_get_dev_path(DeviceState *dev); static char *pcibus_get_fw_dev_path(DeviceState *dev); static void pcibus_reset(BusState *qbus); -static void pci_bus_finalize(Object *obj); static Property pci_props[] = { DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), @@ -61,6 +60,34 @@ static Property pci_props[] = { DEFINE_PROP_END_OF_LIST() }; +static const VMStateDescription vmstate_pcibus = { + .name = "PCIBUS", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_INT32_EQUAL(nirq, PCIBus), + VMSTATE_VARRAY_INT32(irq_count, PCIBus, + nirq, 0, vmstate_info_int32, + int32_t), + VMSTATE_END_OF_LIST() + } +}; + +static void pci_bus_realize(BusState *qbus, Error **errp) +{ + PCIBus *bus = PCI_BUS(qbus); + + vmstate_register(NULL, -1, &vmstate_pcibus, bus); +} + +static void pci_bus_unrealize(BusState *qbus, Error **errp) +{ + PCIBus *bus = PCI_BUS(qbus); + + vmstate_unregister(NULL, &vmstate_pcibus, bus); +} + static void pci_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); @@ -68,6 +95,8 @@ static void pci_bus_class_init(ObjectClass *klass, void *data) k->print_dev = pcibus_dev_print; k->get_dev_path = pcibus_get_dev_path; k->get_fw_dev_path = pcibus_get_fw_dev_path; + k->realize = pci_bus_realize; + k->unrealize = pci_bus_unrealize; k->reset = pcibus_reset; } @@ -75,7 +104,6 @@ static const TypeInfo pci_bus_info = { .name = TYPE_PCI_BUS, .parent = TYPE_BUS, .instance_size = sizeof(PCIBus), - .instance_finalize = pci_bus_finalize, .class_init = pci_bus_class_init, }; @@ -95,17 +123,6 @@ static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU; static QLIST_HEAD(, PCIHostState) pci_host_bridges; -static const VMStateDescription vmstate_pcibus = { - .name = "PCIBUS", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { - VMSTATE_INT32_EQUAL(nirq, PCIBus), - VMSTATE_VARRAY_INT32(irq_count, PCIBus, nirq, 0, vmstate_info_int32, int32_t), - VMSTATE_END_OF_LIST() - } -}; static int pci_bar(PCIDevice *d, int reg) { uint8_t type; @@ -299,8 +316,6 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent, QLIST_INIT(&bus->child); pci_host_bus_register(bus, parent); - - vmstate_register(NULL, -1, &vmstate_pcibus, bus); } bool pci_bus_is_express(PCIBus *bus) @@ -369,12 +384,6 @@ int pci_bus_num(PCIBus *s) return s->parent_dev->config[PCI_SECONDARY_BUS]; } -static void pci_bus_finalize(Object *obj) -{ - PCIBus *bus = PCI_BUS(obj); - vmstate_unregister(NULL, &vmstate_pcibus, bus); -} - static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) { PCIDevice *s = container_of(pv, PCIDevice, config); From f8762027a33e2f5d0915c56a904962b1481f75c1 Mon Sep 17 00:00:00 2001 From: Marcel Apfelbaum Date: Tue, 11 Mar 2014 15:00:34 +0200 Subject: [PATCH 31/31] libqtest: Fix possible deadlock in qtest initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'socket_accept' waits for QEMU to init its unix socket. If QEMU encounters an error during command line parsing, it can exit before initializing the communication channel. Using a timeout for sockets fixes the issue. Reviewed-by: Eric Blake Signed-off-by: Marcel Apfelbaum Reviewed-by: Stefan Hajnoczi Signed-off-by: Andreas Färber --- tests/libqtest.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index f587d36176..c9e78aa741 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -34,6 +34,7 @@ #include "qapi/qmp/json-parser.h" #define MAX_IRQ 256 +#define SOCKET_TIMEOUT 5 QTestState *global_qtest; @@ -78,12 +79,16 @@ static int socket_accept(int sock) struct sockaddr_un addr; socklen_t addrlen; int ret; + struct timeval timeout = { .tv_sec = SOCKET_TIMEOUT, + .tv_usec = 0 }; + + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, + sizeof(timeout)); addrlen = sizeof(addr); do { ret = accept(sock, (struct sockaddr *)&addr, &addrlen); } while (ret == -1 && errno == EINTR); - g_assert_no_errno(ret); close(sock); return ret; @@ -147,12 +152,16 @@ QTestState *qtest_init(const char *extra_args) } s->fd = socket_accept(sock); - s->qmp_fd = socket_accept(qmpsock); + if (s->fd >= 0) { + s->qmp_fd = socket_accept(qmpsock); + } unlink(socket_path); unlink(qmp_socket_path); g_free(socket_path); g_free(qmp_socket_path); + g_assert(s->fd >= 0 && s->qmp_fd >= 0); + s->rx = g_string_new(""); for (i = 0; i < MAX_IRQ; i++) { s->irq_level[i] = false;