diff options
-rwxr-xr-x | QMP/qmp-shell | 7 | ||||
-rw-r--r-- | hmp-commands.hx | 2 | ||||
-rw-r--r-- | hmp.c | 16 | ||||
-rw-r--r-- | hmp.h | 1 | ||||
-rw-r--r-- | hw/qdev-addr.c | 2 | ||||
-rw-r--r-- | hw/qdev-properties-system.c | 4 | ||||
-rw-r--r-- | hw/qdev-properties.c | 40 | ||||
-rw-r--r-- | hw/qdev-properties.h | 12 | ||||
-rw-r--r-- | hw/qdev.c | 12 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-bus.c | 26 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-bus.h | 11 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-ccw.c | 3 | ||||
-rw-r--r-- | hw/s390x/virtio-ccw.c | 28 | ||||
-rw-r--r-- | hw/s390x/virtio-ccw.h | 12 | ||||
-rw-r--r-- | hw/virtio-pci.c | 115 | ||||
-rw-r--r-- | hw/virtio-pci.h | 15 | ||||
-rw-r--r-- | hw/virtio-scsi.c | 122 | ||||
-rw-r--r-- | hw/virtio-scsi.h | 30 | ||||
-rw-r--r-- | include/char/char.h | 15 | ||||
-rw-r--r-- | monitor.c | 7 | ||||
-rw-r--r-- | qapi-schema.json | 23 | ||||
-rw-r--r-- | qemu-char.c | 27 | ||||
-rw-r--r-- | qemu-options.hx | 3 | ||||
-rw-r--r-- | qmp-commands.hx | 80 | ||||
-rw-r--r-- | qom/object.c | 13 | ||||
-rw-r--r-- | qtest.c | 2 | ||||
-rw-r--r-- | tpm/tpm.c | 9 | ||||
-rw-r--r-- | vl.c | 5 |
28 files changed, 468 insertions, 174 deletions
diff --git a/QMP/qmp-shell b/QMP/qmp-shell index 24b665c8c0..d126e63ad1 100755 --- a/QMP/qmp-shell +++ b/QMP/qmp-shell @@ -101,7 +101,12 @@ class QMPShell(qmp.QEMUMonitorProtocol): try: value = int(opt[1]) except ValueError: - value = opt[1] + if opt[1] == 'true': + value = True + elif opt[1] == 'false': + value = False + else: + value = opt[1] qmpcmd['arguments'][opt[0]] = value return qmpcmd diff --git a/hmp-commands.hx b/hmp-commands.hx index df44906ef9..3d98604f77 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1643,6 +1643,8 @@ show qdev device model list show roms @item info tpm show the TPM device +@item info cpu_max +show the number of CPUs supported by the machine being emulated. @end table ETEXI @@ -633,11 +633,11 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict) c, TpmModel_lookup[ti->model]); monitor_printf(mon, " \\ %s: type=%s", - ti->id, TpmType_lookup[ti->type]); + ti->id, TpmTypeOptionsKind_lookup[ti->options->kind]); - switch (ti->tpm_options->kind) { - case TPM_TYPE_OPTIONS_KIND_TPM_PASSTHROUGH_OPTIONS: - tpo = ti->tpm_options->tpm_passthrough_options; + switch (ti->options->kind) { + case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH: + tpo = ti->options->passthrough; monitor_printf(mon, "%s%s%s%s", tpo->has_path ? ",path=" : "", tpo->has_path ? tpo->path : "", @@ -750,6 +750,14 @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict) g_free(data); } +void hmp_query_cpu_max(Monitor *mon, const QDict *qdict) +{ + int cpu_max; + + cpu_max = qmp_query_cpu_max(NULL); + monitor_printf(mon, "Maximum number of CPUs is %d\n", cpu_max); +} + static void hmp_cont_cb(void *opaque, int err) { if (!err) { @@ -42,6 +42,7 @@ void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); void hmp_system_powerdown(Monitor *mon, const QDict *qdict); void hmp_cpu(Monitor *mon, const QDict *qdict); +void hmp_query_cpu_max(Monitor *mon, const QDict *qdict); void hmp_memsave(Monitor *mon, const QDict *qdict); void hmp_pmemsave(Monitor *mon, const QDict *qdict); void hmp_ringbuf_write(Monitor *mon, const QDict *qdict); diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c index 2398b4a37f..80a38bb017 100644 --- a/hw/qdev-addr.c +++ b/hw/qdev-addr.c @@ -42,7 +42,7 @@ static void set_taddr(Object *obj, Visitor *v, void *opaque, int64_t value; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c index 87951444a1..28813d3978 100644 --- a/hw/qdev-properties-system.c +++ b/hw/qdev-properties-system.c @@ -43,7 +43,7 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop, int ret; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -287,7 +287,7 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque, NetClientState *hubport; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 247ca6c5b4..168c4663e9 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -7,6 +7,20 @@ #include "qapi/visitor.h" #include "char/char.h" +void qdev_prop_set_after_realize(DeviceState *dev, const char *name, + Error **errp) +{ + if (dev->id) { + error_setg(errp, "Attempt to set property '%s' on device '%s' " + "(type '%s') after it was realized", name, dev->id, + object_get_typename(OBJECT(dev))); + } else { + error_setg(errp, "Attempt to set property '%s' on anonymous device " + "(type '%s') after it was realized", name, + object_get_typename(OBJECT(dev))); + } +} + void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) { void *ptr = dev; @@ -33,7 +47,7 @@ static void set_enum(Object *obj, Visitor *v, void *opaque, int *ptr = qdev_get_prop_ptr(dev, prop); if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -86,7 +100,7 @@ static void set_bit(Object *obj, Visitor *v, void *opaque, bool value; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -126,7 +140,7 @@ static void set_uint8(Object *obj, Visitor *v, void *opaque, uint8_t *ptr = qdev_get_prop_ptr(dev, prop); if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -193,7 +207,7 @@ static void set_uint16(Object *obj, Visitor *v, void *opaque, uint16_t *ptr = qdev_get_prop_ptr(dev, prop); if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -226,7 +240,7 @@ static void set_uint32(Object *obj, Visitor *v, void *opaque, uint32_t *ptr = qdev_get_prop_ptr(dev, prop); if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -251,7 +265,7 @@ static void set_int32(Object *obj, Visitor *v, void *opaque, int32_t *ptr = qdev_get_prop_ptr(dev, prop); if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -324,7 +338,7 @@ static void set_uint64(Object *obj, Visitor *v, void *opaque, uint64_t *ptr = qdev_get_prop_ptr(dev, prop); if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -414,7 +428,7 @@ static void set_string(Object *obj, Visitor *v, void *opaque, char *str; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -478,7 +492,7 @@ static void set_mac(Object *obj, Visitor *v, void *opaque, char *str, *p; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -570,7 +584,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque, char *str; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -641,7 +655,7 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque, const int64_t max = 32768; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -709,7 +723,7 @@ static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque, unsigned int slot = 0, func = 0; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -824,7 +838,7 @@ static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque, int i; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } if (*alenptr) { diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h index c9bb246841..a37933998a 100644 --- a/hw/qdev-properties.h +++ b/hw/qdev-properties.h @@ -167,4 +167,16 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, */ void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp); +/** + * @qdev_prop_set_after_realize: + * @dev: device + * @name: name of property + * @errp: indirect pointer to Error to be set + * Set the Error object to report that an attempt was made to set a property + * on a device after it has already been realized. This is a utility function + * which allows property-setter functions to easily report the error in + * a friendly format identifying both the device and the property. + */ +void qdev_prop_set_after_realize(DeviceState *dev, const char *name, + Error **errp); #endif @@ -562,7 +562,7 @@ static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque, int ret; if (dev->realized) { - error_set(errp, QERR_PERMISSION_DENIED); + qdev_prop_set_after_realize(dev, name, errp); return; } @@ -710,6 +710,7 @@ static void device_initfn(Object *obj) DeviceState *dev = DEVICE(obj); ObjectClass *class; Property *prop; + Error *err = NULL; if (qdev_hotplug) { dev->hotplugged = 1; @@ -725,15 +726,18 @@ static void device_initfn(Object *obj) class = object_get_class(OBJECT(dev)); do { for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) { - qdev_property_add_legacy(dev, prop, NULL); - qdev_property_add_static(dev, prop, NULL); + qdev_property_add_legacy(dev, prop, &err); + assert_no_error(err); + qdev_property_add_static(dev, prop, &err); + assert_no_error(err); } class = object_class_get_parent(class); } while (class != object_class_by_name(TYPE_DEVICE)); qdev_prop_set_globals(dev); object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS, - (Object **)&dev->parent_bus, NULL); + (Object **)&dev->parent_bus, &err); + assert_no_error(err); } /* Unlink device from bus and free the structure. */ diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index c5d5456fa1..8c529c14d0 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -202,16 +202,24 @@ static int s390_virtio_serial_init(VirtIOS390Device *dev) return r; } -static int s390_virtio_scsi_init(VirtIOS390Device *dev) +static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev) { - VirtIODevice *vdev; + VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(s390_dev); + DeviceState *vdev = DEVICE(&dev->vdev); - vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi); - if (!vdev) { + qdev_set_parent_bus(vdev, BUS(&s390_dev->bus)); + if (qdev_init(vdev) < 0) { return -1; } - return s390_virtio_device_init(dev, vdev); + return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev)); +} + +static void s390_virtio_scsi_instance_init(Object *obj) +{ + VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(obj); + object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI); + object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } static int s390_virtio_rng_init(VirtIOS390Device *dev) @@ -538,7 +546,8 @@ static const TypeInfo virtio_s390_device_info = { }; static Property s390_virtio_scsi_properties[] = { - DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, host_features, scsi), + DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIS390, vdev.conf), + DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features), DEFINE_PROP_END_OF_LIST(), }; @@ -552,9 +561,10 @@ static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data) } static const TypeInfo s390_virtio_scsi = { - .name = "virtio-scsi-s390", + .name = TYPE_VIRTIO_SCSI_S390, .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIOS390Device), + .instance_size = sizeof(VirtIOSCSIS390), + .instance_init = s390_virtio_scsi_instance_init, .class_init = s390_virtio_scsi_class_init, }; diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h index 1a634118d1..ebe8794204 100644 --- a/hw/s390x/s390-virtio-bus.h +++ b/hw/s390x/s390-virtio-bus.h @@ -93,7 +93,6 @@ struct VirtIOS390Device { uint32_t host_features; virtio_serial_conf serial; virtio_net_conf net; - VirtIOSCSIConf scsi; VirtIORNGConf rng; VirtioBusState bus; }; @@ -131,5 +130,15 @@ typedef struct VirtIOBlkS390 { VirtIOBlkConf blk; } VirtIOBlkS390; +/* virtio-scsi-s390 */ + +#define TYPE_VIRTIO_SCSI_S390 "virtio-scsi-s390" +#define VIRTIO_SCSI_S390(obj) \ + OBJECT_CHECK(VirtIOSCSIS390, (obj), TYPE_VIRTIO_SCSI_S390) + +typedef struct VirtIOSCSIS390 { + VirtIOS390Device parent_obj; + VirtIOSCSI vdev; +} VirtIOSCSIS390; #endif diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index d4364143ea..76b63e2ca6 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -31,6 +31,9 @@ static int virtio_ccw_hcall_notify(const uint64_t *args) if (!sch || !css_subch_visible(sch)) { return -EINVAL; } + if (queue >= VIRTIO_PCI_QUEUE_MAX) { + return -EINVAL; + } virtio_queue_notify(virtio_ccw_get_vdev(sch), queue); return 0; diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 4c44b7e856..7e79c5795a 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -626,22 +626,24 @@ static int virtio_ccw_balloon_exit(VirtioCcwDevice *dev) return virtio_ccw_exit(dev); } -static int virtio_ccw_scsi_init(VirtioCcwDevice *dev) +static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev) { - VirtIODevice *vdev; + VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(ccw_dev); + DeviceState *vdev = DEVICE(&dev->vdev); - vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi); - if (!vdev) { + qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); + if (qdev_init(vdev) < 0) { return -1; } - return virtio_ccw_device_init(dev, vdev); + return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev)); } -static int virtio_ccw_scsi_exit(VirtioCcwDevice *dev) +static void virtio_ccw_scsi_instance_init(Object *obj) { - virtio_scsi_exit(dev->vdev); - return virtio_ccw_exit(dev); + VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(obj); + object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI); + object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } static int virtio_ccw_rng_init(VirtioCcwDevice *dev) @@ -832,7 +834,8 @@ static const TypeInfo virtio_ccw_balloon = { static Property virtio_ccw_scsi_properties[] = { DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), - DEFINE_VIRTIO_SCSI_PROPERTIES(VirtioCcwDevice, host_features[0], scsi), + DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.conf), + DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]), DEFINE_PROP_END_OF_LIST(), }; @@ -842,15 +845,16 @@ static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data) VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass); k->init = virtio_ccw_scsi_init; - k->exit = virtio_ccw_scsi_exit; + k->exit = virtio_ccw_exit; dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_scsi_properties; } static const TypeInfo virtio_ccw_scsi = { - .name = "virtio-scsi-ccw", + .name = TYPE_VIRTIO_SCSI_CCW, .parent = TYPE_VIRTIO_CCW_DEVICE, - .instance_size = sizeof(VirtioCcwDevice), + .instance_size = sizeof(VirtIOSCSICcw), + .instance_init = virtio_ccw_scsi_instance_init, .class_init = virtio_ccw_scsi_class_init, }; diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index 3993bc53b0..d9f73997df 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -76,7 +76,6 @@ struct VirtioCcwDevice { uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE]; virtio_serial_conf serial; virtio_net_conf net; - VirtIOSCSIConf scsi; VirtIORNGConf rng; VirtioBusState bus; /* Guest provided values: */ @@ -93,6 +92,17 @@ typedef struct VirtualCssBus { #define VIRTUAL_CSS_BUS(obj) \ OBJECT_CHECK(VirtualCssBus, (obj), TYPE_VIRTUAL_CSS_BUS) +/* virtio-scsi-ccw */ + +#define TYPE_VIRTIO_SCSI_CCW "virtio-scsi-ccw" +#define VIRTIO_SCSI_CCW(obj) \ + OBJECT_CHECK(VirtIOSCSICcw, (obj), TYPE_VIRTIO_SCSI_CCW) + +typedef struct VirtIOSCSICcw { + VirtioCcwDevice parent_obj; + VirtIOSCSI vdev; +} VirtIOSCSICcw; + /* virtio-blk-ccw */ #define TYPE_VIRTIO_BLK_CCW "virtio-blk-ccw" diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index f3ece78954..668060d991 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -1190,63 +1190,6 @@ static const TypeInfo virtio_rng_info = { .class_init = virtio_rng_class_init, }; -static int virtio_scsi_init_pci(PCIDevice *pci_dev) -{ - VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); - VirtIODevice *vdev; - - vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi); - if (!vdev) { - return -EINVAL; - } - - vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED - ? proxy->scsi.num_queues + 3 - : proxy->nvectors; - virtio_init_pci(proxy, vdev); - - /* make the actual value visible */ - proxy->nvectors = vdev->nvectors; - return 0; -} - -static void virtio_scsi_exit_pci(PCIDevice *pci_dev) -{ - VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); - - virtio_scsi_exit(proxy->vdev); - virtio_exit_pci(pci_dev); -} - -static Property virtio_scsi_properties[] = { - DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED), - DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi), - DEFINE_PROP_END_OF_LIST(), -}; - -static void virtio_scsi_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = virtio_scsi_init_pci; - k->exit = virtio_scsi_exit_pci; - k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; - k->revision = 0x00; - k->class_id = PCI_CLASS_STORAGE_SCSI; - dc->reset = virtio_pci_reset; - dc->props = virtio_scsi_properties; -} - -static const TypeInfo virtio_scsi_info = { - .name = "virtio-scsi-pci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(VirtIOPCIProxy), - .class_init = virtio_scsi_class_init, -}; - #ifdef CONFIG_VIRTFS static int virtio_9p_init_pci(PCIDevice *pci_dev) { @@ -1453,6 +1396,62 @@ static const TypeInfo virtio_blk_pci_info = { .class_init = virtio_blk_pci_class_init, }; +/* virtio-scsi-pci */ + +static Property virtio_scsi_pci_properties[] = { + DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), + DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, + DEV_NVECTORS_UNSPECIFIED), + DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features), + DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIPCI, vdev.conf), + DEFINE_PROP_END_OF_LIST(), +}; + +static int virtio_scsi_pci_init_pci(VirtIOPCIProxy *vpci_dev) +{ + VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + + if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { + vpci_dev->nvectors = dev->vdev.conf.num_queues + 3; + } + + qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); + if (qdev_init(vdev) < 0) { + return -1; + } + return 0; +} + +static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + k->init = virtio_scsi_pci_init_pci; + dc->props = virtio_scsi_pci_properties; + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; + pcidev_k->revision = 0x00; + pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; +} + +static void virtio_scsi_pci_instance_init(Object *obj) +{ + VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj); + object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI); + object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); +} + +static const TypeInfo virtio_scsi_pci_info = { + .name = TYPE_VIRTIO_SCSI_PCI, + .parent = TYPE_VIRTIO_PCI, + .instance_size = sizeof(VirtIOSCSIPCI), + .instance_init = virtio_scsi_pci_instance_init, + .class_init = virtio_scsi_pci_class_init, +}; + /* virtio-pci-bus */ void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev) @@ -1494,7 +1493,6 @@ static void virtio_pci_register_types(void) type_register_static(&virtio_net_info); type_register_static(&virtio_serial_info); type_register_static(&virtio_balloon_info); - type_register_static(&virtio_scsi_info); type_register_static(&virtio_rng_info); type_register_static(&virtio_pci_bus_info); type_register_static(&virtio_pci_info); @@ -1502,6 +1500,7 @@ static void virtio_pci_register_types(void) type_register_static(&virtio_9p_info); #endif type_register_static(&virtio_blk_pci_info); + type_register_static(&virtio_scsi_pci_info); } type_init(virtio_pci_register_types) diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h index a9dbffffea..bfe7a8e1ca 100644 --- a/hw/virtio-pci.h +++ b/hw/virtio-pci.h @@ -26,6 +26,7 @@ typedef struct VirtIOPCIProxy VirtIOPCIProxy; typedef struct VirtIOBlkPCI VirtIOBlkPCI; +typedef struct VirtIOSCSIPCI VirtIOSCSIPCI; /* virtio-pci-bus */ @@ -81,7 +82,6 @@ struct VirtIOPCIProxy { #endif virtio_serial_conf serial; virtio_net_conf net; - VirtIOSCSIConf scsi; VirtIORNGConf rng; bool ioeventfd_disabled; bool ioeventfd_started; @@ -90,6 +90,19 @@ struct VirtIOPCIProxy { VirtioBusState bus; }; + +/* + * virtio-scsi-pci: This extends VirtioPCIProxy. + */ +#define TYPE_VIRTIO_SCSI_PCI "virtio-scsi-pci" +#define VIRTIO_SCSI_PCI(obj) \ + OBJECT_CHECK(VirtIOSCSIPCI, (obj), TYPE_VIRTIO_SCSI_PCI) + +struct VirtIOSCSIPCI { + VirtIOPCIProxy parent_obj; + VirtIOSCSI vdev; +}; + /* * virtio-blk-pci: This extends VirtioPCIProxy. */ diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index 86207124a2..06a58a6a63 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -17,6 +17,7 @@ #include "qemu/error-report.h" #include <hw/scsi.h> #include <hw/scsi-defs.h> +#include "hw/virtio-bus.h" #define VIRTIO_SCSI_VQ_SIZE 128 #define VIRTIO_SCSI_CDB_SIZE 32 @@ -171,6 +172,7 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req) { VirtIOSCSI *s = req->dev; VirtQueue *vq = req->vq; + VirtIODevice *vdev = VIRTIO_DEVICE(s); virtqueue_push(vq, &req->elem, req->qsgl.size + req->elem.in_sg[0].iov_len); qemu_sglist_destroy(&req->qsgl); if (req->sreq) { @@ -178,7 +180,7 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req) scsi_req_unref(req->sreq); } g_free(req); - virtio_notify(&s->vdev, vq); + virtio_notify(vdev, vq); } static void virtio_scsi_bad_req(void) @@ -237,7 +239,7 @@ static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq) VirtIOSCSIReq *req = sreq->hba_private; uint32_t n = virtio_queue_get_id(req->vq) - 2; - assert(n < req->dev->conf->num_queues); + assert(n < req->dev->conf.num_queues); qemu_put_be32s(f, &n); qemu_put_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem)); } @@ -251,7 +253,7 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq) req = g_malloc(sizeof(*req)); qemu_get_be32s(f, &n); - assert(n < s->conf->num_queues); + assert(n < s->conf.num_queues); qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem)); virtio_scsi_parse_req(s, s->cmd_vqs[n], req); @@ -513,10 +515,10 @@ static void virtio_scsi_get_config(VirtIODevice *vdev, VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config; VirtIOSCSI *s = (VirtIOSCSI *)vdev; - stl_raw(&scsiconf->num_queues, s->conf->num_queues); + stl_raw(&scsiconf->num_queues, s->conf.num_queues); stl_raw(&scsiconf->seg_max, 128 - 2); - stl_raw(&scsiconf->max_sectors, s->conf->max_sectors); - stl_raw(&scsiconf->cmd_per_lun, s->conf->cmd_per_lun); + stl_raw(&scsiconf->max_sectors, s->conf.max_sectors); + stl_raw(&scsiconf->cmd_per_lun, s->conf.cmd_per_lun); stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent)); stl_raw(&scsiconf->sense_size, s->sense_size); stl_raw(&scsiconf->cdb_size, s->cdb_size); @@ -565,16 +567,16 @@ static void virtio_scsi_reset(VirtIODevice *vdev) */ static void virtio_scsi_save(QEMUFile *f, void *opaque) { - VirtIOSCSI *s = opaque; - virtio_save(&s->vdev, f); + VirtIODevice *vdev = VIRTIO_DEVICE(opaque); + virtio_save(vdev, f); } static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id) { - VirtIOSCSI *s = opaque; + VirtIODevice *vdev = VIRTIO_DEVICE(opaque); int ret; - ret = virtio_load(&s->vdev, f); + ret = virtio_load(vdev, f); if (ret) { return ret; } @@ -586,9 +588,10 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev, { VirtIOSCSIReq *req = virtio_scsi_pop_req(s, s->event_vq); VirtIOSCSIEvent *evt; + VirtIODevice *vdev = VIRTIO_DEVICE(s); int in_size; - if (!(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) { + if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { return; } @@ -632,7 +635,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev, static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq) { - VirtIOSCSI *s = (VirtIOSCSI *)vdev; + VirtIOSCSI *s = VIRTIO_SCSI(vdev); if (s->events_dropped) { virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0); @@ -642,8 +645,9 @@ static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq) static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) { VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); + VirtIODevice *vdev = VIRTIO_DEVICE(s); - if (((s->vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) && + if (((vdev->guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) && dev->type != TYPE_ROM) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE, sense.asc | (sense.ascq << 8)); @@ -653,8 +657,9 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev) { VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); + VirtIODevice *vdev = VIRTIO_DEVICE(s); - if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { + if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); } @@ -663,8 +668,9 @@ static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev) static void virtio_scsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev) { VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); + VirtIODevice *vdev = VIRTIO_DEVICE(s); - if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { + if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED); } @@ -686,49 +692,83 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = { .load_request = virtio_scsi_load_request, }; -VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf) +static int virtio_scsi_device_init(VirtIODevice *vdev) { - VirtIOSCSI *s; + DeviceState *qdev = DEVICE(vdev); + VirtIOSCSI *s = VIRTIO_SCSI(vdev); static int virtio_scsi_id; - size_t sz; int i; - sz = sizeof(VirtIOSCSI) + proxyconf->num_queues * sizeof(VirtQueue *); - s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI, - sizeof(VirtIOSCSIConfig), sz); + virtio_init(VIRTIO_DEVICE(s), "virtio-scsi", VIRTIO_ID_SCSI, + sizeof(VirtIOSCSIConfig)); - s->qdev = dev; - s->conf = proxyconf; + s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *)); /* TODO set up vdev function pointers */ - s->vdev.get_config = virtio_scsi_get_config; - s->vdev.set_config = virtio_scsi_set_config; - s->vdev.get_features = virtio_scsi_get_features; - s->vdev.reset = virtio_scsi_reset; - - s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE, - virtio_scsi_handle_ctrl); - s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE, + vdev->get_config = virtio_scsi_get_config; + vdev->set_config = virtio_scsi_set_config; + vdev->get_features = virtio_scsi_get_features; + vdev->reset = virtio_scsi_reset; + + s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, + virtio_scsi_handle_ctrl); + s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, virtio_scsi_handle_event); - for (i = 0; i < s->conf->num_queues; i++) { - s->cmd_vqs[i] = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE, + for (i = 0; i < s->conf.num_queues; i++) { + s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, virtio_scsi_handle_cmd); } - scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info); - if (!dev->hotplugged) { + scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info); + if (!qdev->hotplugged) { scsi_bus_legacy_handle_cmdline(&s->bus); } - register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1, + register_savevm(qdev, "virtio-scsi", virtio_scsi_id++, 1, virtio_scsi_save, virtio_scsi_load, s); - return &s->vdev; + return 0; } -void virtio_scsi_exit(VirtIODevice *vdev) +static int virtio_scsi_device_exit(DeviceState *qdev) { - VirtIOSCSI *s = (VirtIOSCSI *)vdev; - unregister_savevm(s->qdev, "virtio-scsi", s); - virtio_cleanup(vdev); + VirtIOSCSI *s = VIRTIO_SCSI(qdev); + VirtIODevice *vdev = VIRTIO_DEVICE(qdev); + + unregister_savevm(qdev, "virtio-scsi", s); + g_free(s->cmd_vqs); + virtio_common_cleanup(vdev); + return 0; +} + +static Property virtio_scsi_properties[] = { + DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI, conf), + DEFINE_PROP_END_OF_LIST(), +}; + +static void virtio_scsi_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->exit = virtio_scsi_device_exit; + dc->props = virtio_scsi_properties; + vdc->init = virtio_scsi_device_init; + vdc->get_config = virtio_scsi_get_config; + vdc->set_config = virtio_scsi_set_config; + vdc->get_features = virtio_scsi_get_features; + vdc->reset = virtio_scsi_reset; +} + +static const TypeInfo virtio_scsi_info = { + .name = TYPE_VIRTIO_SCSI, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VirtIOSCSI), + .class_init = virtio_scsi_class_init, +}; + +static void virtio_register_types(void) +{ + type_register_static(&virtio_scsi_info); } + +type_init(virtio_register_types) diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h index ccf1e4207c..31e97bbe38 100644 --- a/hw/virtio-scsi.h +++ b/hw/virtio-scsi.h @@ -18,6 +18,11 @@ #include "hw/pci/pci.h" #include "hw/scsi.h" +#define TYPE_VIRTIO_SCSI "virtio-scsi" +#define VIRTIO_SCSI(obj) \ + OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI) + + /* The ID for virtio_scsi */ #define VIRTIO_ID_SCSI 8 @@ -33,9 +38,8 @@ struct VirtIOSCSIConf { }; typedef struct VirtIOSCSI { - VirtIODevice vdev; - DeviceState *qdev; - VirtIOSCSIConf *conf; + VirtIODevice parent_obj; + VirtIOSCSIConf conf; SCSIBus bus; uint32_t sense_size; @@ -44,15 +48,19 @@ typedef struct VirtIOSCSI { bool events_dropped; VirtQueue *ctrl_vq; VirtQueue *event_vq; - VirtQueue *cmd_vqs[0]; + VirtQueue **cmd_vqs; } VirtIOSCSI; -#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \ - DEFINE_VIRTIO_COMMON_FEATURES(_state, _features_field), \ - DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \ - DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \ - DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128), \ - DEFINE_PROP_BIT("hotplug", _state, _features_field, VIRTIO_SCSI_F_HOTPLUG, true), \ - DEFINE_PROP_BIT("param_change", _state, _features_field, VIRTIO_SCSI_F_CHANGE, true) +#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _conf_field) \ + DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \ + DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF),\ + DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128) + +#define DEFINE_VIRTIO_SCSI_FEATURES(_state, _feature_field) \ + DEFINE_VIRTIO_COMMON_FEATURES(_state, _feature_field), \ + DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG, \ + true), \ + DEFINE_PROP_BIT("param_change", _state, _feature_field, \ + VIRTIO_SCSI_F_CHANGE, true) #endif /* _QEMU_VIRTIO_SCSI_H */ diff --git a/include/char/char.h b/include/char/char.h index 0326b2a47b..5c3a7a5756 100644 --- a/include/char/char.h +++ b/include/char/char.h @@ -170,6 +170,21 @@ int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond, int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len); /** + * @qemu_chr_fe_write_all: + * + * Write data to a character backend from the front end. This function will + * send data from the front end to the back end. Unlike @qemu_chr_fe_write, + * this function will block if the back end cannot consume all of the data + * attempted to be written. + * + * @buf the data + * @len the number of bytes to send + * + * Returns: the number of bytes consumed + */ +int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len); + +/** * @qemu_chr_fe_ioctl: * * Issue a device specific ioctl to a backend. @@ -2746,6 +2746,13 @@ static mon_cmd_t info_cmds[] = { .mhandler.cmd = hmp_info_tpm, }, { + .name = "cpu_max", + .args_type = "", + .params = "", + .help = "Get maximum number of VCPUs supported by machine", + .mhandler.cmd = hmp_query_cpu_max, + }, + { .name = NULL, }, }; diff --git a/qapi-schema.json b/qapi-schema.json index 6c4966be43..6494787714 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1834,6 +1834,17 @@ { 'command': 'query-migrate-cache-size', 'returns': 'int' } ## +## @query-cpu-max +## +## query maximum number of CPUs supported by machine +## +## Returns: number of CPUs +## +## Since: 1.5 +### +{ 'command': 'query-cpu-max', 'returns': 'int' } + +## # @ObjectPropertyInfo: # # @name: the name of the property @@ -3405,13 +3416,12 @@ # # A union referencing different TPM backend types' configuration options # -# @tpm-passthough-options: TPMPassthroughOptions describing the TPM -# passthrough configuration options +# @passthrough: The configuration options for the TPM passthrough type # # Since: 1.5 ## { 'union': 'TpmTypeOptions', - 'data': { 'tpm-passthrough-options' : 'TPMPassthroughOptions' } } + 'data': { 'passthrough' : 'TPMPassthroughOptions' } } ## # @TpmInfo: @@ -3422,17 +3432,14 @@ # # @model: The TPM frontend model # -# @type: The TPM (backend) type being used -# -# @tpm-options: The TPM (backend) type configuration options +# @options: The TPM (backend) type configuration options # # Since: 1.5 ## { 'type': 'TPMInfo', 'data': {'id': 'str', 'model': 'TpmModel', - 'type': 'TpmType', - 'tpm-options': 'TpmTypeOptions' } } + 'options': 'TpmTypeOptions' } } ## # @query-tpm: diff --git a/qemu-char.c b/qemu-char.c index 4e011df3ec..936150fa73 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -140,6 +140,33 @@ int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len) return s->chr_write(s, buf, len); } +int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len) +{ + int offset = 0; + int res; + + while (offset < len) { + do { + res = s->chr_write(s, buf + offset, len - offset); + if (res == -1 && errno == EAGAIN) { + g_usleep(100); + } + } while (res == -1 && errno == EAGAIN); + + if (res == 0) { + break; + } + + if (res < 0) { + return res; + } + + offset += res; + } + + return offset; +} + int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg) { if (!s->chr_ioctl) diff --git a/qemu-options.hx b/qemu-options.hx index d7afeab8b0..c40ba554f9 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2241,7 +2241,8 @@ Backend type must be: @option{passthrough}. The specific backend type will determine the applicable options. -The @code{-tpmdev} option requires a @code{-device} option. +The @code{-tpmdev} option creates the TPM backend and requires a +@code{-device} option that specifies the TPM frontend interface model. Options to each backend are described below. diff --git a/qmp-commands.hx b/qmp-commands.hx index fdc40486f6..1e0e11ee32 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -385,6 +385,28 @@ Note: CPUs' indexes are obtained with the 'query-cpus' command. EQMP { + .name = "query-cpu-max", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_cpu_max, + }, + +SQMP +query-cpu-max +------------- + +Get the maximum CPUs supported by the machine being currently +emulated. + +Returns json-int. + +Example: + +-> { "execute": "query-cpu-max" } +<- { "return": 255 } + +EQMP + + { .name = "memsave", .args_type = "val:l,size:i,filename:s,cpu:i?", .mhandler.cmd_new = qmp_marshal_input_memsave, @@ -2732,18 +2754,76 @@ EQMP .mhandler.cmd_new = qmp_marshal_input_query_tpm, }, +SQMP +query-tpm +--------- + +Return information about the TPM device. + +Arguments: None + +Example: + +-> { "execute": "query-tpm" } +<- { "return": + [ + { "model": "tpm-tis", + "options": + { "type": "passthrough", + "data": + { "cancel-path": "/sys/class/misc/tpm0/device/cancel", + "path": "/dev/tpm0" + } + }, + "id": "tpm0" + } + ] + } + +EQMP + { .name = "query-tpm-models", .args_type = "", .mhandler.cmd_new = qmp_marshal_input_query_tpm_models, }, +SQMP +query-tpm-models +---------------- + +Return a list of supported TPM models. + +Arguments: None + +Example: + +-> { "execute": "query-tpm-models" } +<- { "return": [ "tpm-tis" ] } + +EQMP + { .name = "query-tpm-types", .args_type = "", .mhandler.cmd_new = qmp_marshal_input_query_tpm_types, }, +SQMP +query-tpm-types +--------------- + +Return a list of supported TPM types. + +Arguments: None + +Example: + +-> { "execute": "query-tpm-types" } +<- { "return": [ "passthrough" ] } + +EQMP + { .name = "chardev-add", .args_type = "id:s,backend:q", diff --git a/qom/object.c b/qom/object.c index 3d638ff273..3f77968560 100644 --- a/qom/object.c +++ b/qom/object.c @@ -629,7 +629,18 @@ void object_property_add(Object *obj, const char *name, const char *type, ObjectPropertyRelease *release, void *opaque, Error **errp) { - ObjectProperty *prop = g_malloc0(sizeof(*prop)); + ObjectProperty *prop; + + QTAILQ_FOREACH(prop, &obj->properties, node) { + if (strcmp(prop->name, name) == 0) { + error_setg(errp, "attempt to add duplicate property '%s'" + " to object (type '%s')", name, + object_get_typename(obj)); + return; + } + } + + prop = g_malloc0(sizeof(*prop)); prop->name = g_strdup(name); prop->type = g_strdup(type); @@ -191,7 +191,7 @@ static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr, len = vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); - qemu_chr_fe_write(chr, (uint8_t *)buffer, len); + qemu_chr_fe_write_all(chr, (uint8_t *)buffer, len); if (qtest_log_fp && qtest_opened) { fprintf(qtest_log_fp, "%s", buffer); } @@ -257,14 +257,13 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv) res->id = g_strdup(drv->id); res->model = drv->fe_model; - res->type = drv->ops->type; - res->tpm_options = g_new0(TpmTypeOptions, 1); + res->options = g_new0(TpmTypeOptions, 1); - switch (res->type) { + switch (drv->ops->type) { case TPM_TYPE_PASSTHROUGH: - res->tpm_options->kind = TPM_TYPE_OPTIONS_KIND_TPM_PASSTHROUGH_OPTIONS; + res->options->kind = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH; tpo = g_new0(TPMPassthroughOptions, 1); - res->tpm_options->tpm_passthrough_options = tpo; + res->options->passthrough = tpo; if (drv->path) { tpo->path = g_strdup(drv->path); tpo->has_path = true; @@ -662,6 +662,11 @@ StatusInfo *qmp_query_status(Error **errp) return info; } +int64_t qmp_query_cpu_max(Error **errp) +{ + return current_machine->max_cpus; +} + /***********************************************************/ /* real time host monotonic timer */ |