* [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties @ 2011-12-18 16:05 Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 1/8] qapi: protect against NULL QObject in qmp_input_get_object Paolo Bonzini ` (8 more replies) 0 siblings, 9 replies; 15+ messages in thread From: Paolo Bonzini @ 2011-12-18 16:05 UTC (permalink / raw) To: qemu-devel QOM right now does not have a way to communicate values for qdev properties except as strings. This is bad. This patch improves the Property implementation so that properties export a visitor-based interface in addition to the string-based interface. The new interface can then be registered as a "static" property. It's called static because it uses a struct field for storage and, as such, should be present in all objects of a given class. Patches 1-2 are bugfixes and patches 3-4 are cleanups. Example using qmp-shell: x86_64-softmmu/qemu-system-x86_64 \ -hda ~/test.img -snapshot -S \ -qmp unix:/tmp/server.sock,server,nowait \ -netdev type=user,id=net -device virtio-net-pci,netdev=net,id=net \ -net user,vlan=1 -device virtio-net-pci,id=net2,vlan=1 \ -chardev id=stdio,backend=stdio -device isa-serial,chardev=stdio,id=serial Boolean properties: (QEMU) qom-get path=/i440fx/piix3 property=command_serr_enable {u'return': True} (QEMU) qom-get path=/i440fx/piix3 property=legacy<command_serr_enable> {u'return': u'on'} PCI address properties (perhaps will disappear later, but not yet): (QEMU) qom-get path=/i440fx/piix3 property=addr {u'return': u'01.0'} (QEMU) qom-get path=/i440fx/piix3 property=legacy-addr {u'return': u'01.0'} String properties (NULL mapped to empty string): (QEMU) qom-get path=/vga property=romfile {u'return': u'vgabios-cirrus.bin'} (QEMU) qom-get path=/vga property=legacy-romfile {u'return': u'"vgabios-cirrus.bin"'} (QEMU) qom-get path=/i440fx/piix3 property=romfile {u'return': u''} (QEMU) qom-get path=/i440fx/piix3 property=legacy-romfile {u'return': u'<null>'} MAC properties: (QEMU) qom-get path=/peripheral/net property=mac {u'return': u'52:54:00:12:34:56'} (QEMU) qom-get path=/peripheral/net property=legacy-mac {u'return': u'52:54:00:12:34:56'} (QEMU) qom-set path=/peripheral/net property=mac value=52-54-00-12-34-57 {u'error': {u'data': {}, u'class': u'PermissionDenied', u'desc': u'Insufficient permission to perform this operation'}} Network properties: (QEMU) qom-get path=/peripheral/net property=netdev {u'return': u'net'} (QEMU) qom-get path=/peripheral/net property=legacy-netdev {u'return': u'net'} VLAN properties: (QEMU) qom-get path=/peripheral/net property=vlan {u'return': -1} (QEMU) qom-get path=/peripheral/net property=legacy-vlan {u'return': u'<null>'} (QEMU) qom-get path=/peripheral/net2 property=vlan {u'return': 1} (QEMU) qom-get path=/peripheral/net2 property=legacy-vlan {u'return': u'1'} Chardev properties: (QEMU) qom-get path=/peripheral/serial property=chardev {u'return': u'stdio'} (QEMU) qom-get path=/peripheral/serial property=legacy-chardev {u'return': u'stdio'} Legacy hex32 properties: (QEMU) qom-get path=/peripheral/serial property=iobase {u'return': 1016} (QEMU) qom-get path=/peripheral/serial property=legacy-iobase {u'return': u'0x3f8'} Examples of setting properties (after disabling the DEV_STATE_CREATED check for testing only): (QEMU) qom-set path=/peripheral/net2 property=vlan value=-1 {u'return': {}} (QEMU) qom-get path=/peripheral/net2 property=vlan {u'return': -1} (QEMU) qom-get path=/peripheral/net2 property=legacy-vlan {u'return': u'<null>'} (QEMU) qom-set path=/peripheral/serial property=iobase value=760 {u'return': {}} (QEMU) qom-get path=/peripheral/serial property=iobase {u'return': 760} (QEMU) qom-get path=/peripheral/serial property=legacy-iobase {u'return': u'0x2f8'} v2->v3: Tweaks to patch 4. v1->v2: New "qom: interpret the return value when setting legacy properties". Always pass a value to the visitor when there is no error. Handle empty strings as NULL. Did not change QERR_PROPERTY_VALUE_OUT_OF_RANGE because it is consistent with other QERR_PROPERTY_* errors, now used by QOM too. Paolo Bonzini (8): qapi: protect against NULL QObject in qmp_input_get_object qom: fix swapped parameters qom: push permission checks up into qdev_property_add_legacy qom: interpret the return value when setting legacy properties qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE qom: introduce get/set methods for Property qom: distinguish "legacy" property type name from QOM type name qom: register qdev properties also as non-legacy properties hw/qdev-addr.c | 41 +++++ hw/qdev-properties.c | 407 +++++++++++++++++++++++++++++++++++++++++++-- hw/qdev.c | 84 ++++++---- hw/qdev.h | 14 +- qapi/qmp-input-visitor.c | 10 +- qerror.c | 5 + qerror.h | 3 + 7 files changed, 502 insertions(+), 62 deletions(-) -- 1.7.7.1 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 1/8] qapi: protect against NULL QObject in qmp_input_get_object 2011-12-18 16:05 [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Paolo Bonzini @ 2011-12-18 16:05 ` Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 2/8] qom: fix swapped parameters Paolo Bonzini ` (7 subsequent siblings) 8 siblings, 0 replies; 15+ messages in thread From: Paolo Bonzini @ 2011-12-18 16:05 UTC (permalink / raw) To: qemu-devel A NULL qobj can occur when a parameter is fetched via qdict_get, but the parameter is not in the command. By returning NULL, the caller can choose whether to raise a missing parameter error, an invalid parameter type error, or use a default value. For example, qom-set could can use this to reset a property to its default value, though at this time it will fail with "Invalid parameter type". In any case, anything is better than crashing! Reviewed-by: Anthony Liguori <anthony@codemonkey.ws> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- qapi/qmp-input-visitor.c | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-) diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index 8cbc0ab..c78022b 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -49,10 +49,12 @@ static const QObject *qmp_input_get_object(QmpInputVisitor *qiv, qobj = qiv->stack[qiv->nb_stack - 1].obj; } - if (name && qobject_type(qobj) == QTYPE_QDICT) { - return qdict_get(qobject_to_qdict(qobj), name); - } else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) { - return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry); + if (qobj) { + if (name && qobject_type(qobj) == QTYPE_QDICT) { + return qdict_get(qobject_to_qdict(qobj), name); + } else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) { + return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry); + } } return qobj; -- 1.7.7.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 2/8] qom: fix swapped parameters 2011-12-18 16:05 [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 1/8] qapi: protect against NULL QObject in qmp_input_get_object Paolo Bonzini @ 2011-12-18 16:05 ` Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 3/8] qom: push permission checks up into qdev_property_add_legacy Paolo Bonzini ` (6 subsequent siblings) 8 siblings, 0 replies; 15+ messages in thread From: Paolo Bonzini @ 2011-12-18 16:05 UTC (permalink / raw) To: qemu-devel Reviewed-by: Anthony Liguori <anthony@codemonkey.ws> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- hw/qdev.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index 83913c7..bda8d6c 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -1110,7 +1110,7 @@ void qdev_property_set(DeviceState *dev, Visitor *v, const char *name, if (!prop->set) { error_set(errp, QERR_PERMISSION_DENIED); } else { - prop->set(dev, prop->opaque, v, name, errp); + prop->set(dev, v, prop->opaque, name, errp); } } -- 1.7.7.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 3/8] qom: push permission checks up into qdev_property_add_legacy 2011-12-18 16:05 [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 1/8] qapi: protect against NULL QObject in qmp_input_get_object Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 2/8] qom: fix swapped parameters Paolo Bonzini @ 2011-12-18 16:05 ` Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 4/8] qom: interpret the return value when setting legacy properties Paolo Bonzini ` (5 subsequent siblings) 8 siblings, 0 replies; 15+ messages in thread From: Paolo Bonzini @ 2011-12-18 16:05 UTC (permalink / raw) To: qemu-devel qdev_property_get and qdev_property_set can generate permission denied errors themselves. Do not duplicate this functionality in qdev_get/set_legacy_property, and clean up excessive indentation. Reviewed-by: Anthony Liguori <anthony@codemonkey.ws> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- hw/qdev.c | 46 +++++++++++++++++++--------------------------- 1 files changed, 19 insertions(+), 27 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index bda8d6c..c020a6f 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -1135,46 +1135,38 @@ static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque, { Property *prop = opaque; - if (prop->info->print) { - char buffer[1024]; - char *ptr = buffer; + char buffer[1024]; + char *ptr = buffer; - prop->info->print(dev, prop, buffer, sizeof(buffer)); - visit_type_str(v, &ptr, name, errp); - } else { - error_set(errp, QERR_PERMISSION_DENIED); - } + prop->info->print(dev, prop, buffer, sizeof(buffer)); + visit_type_str(v, &ptr, name, errp); } static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque, const char *name, Error **errp) { Property *prop = opaque; + Error *local_err = NULL; + char *ptr = NULL; + int ret; if (dev->state != DEV_STATE_CREATED) { error_set(errp, QERR_PERMISSION_DENIED); return; } - if (prop->info->parse) { - Error *local_err = NULL; - char *ptr = NULL; + visit_type_str(v, &ptr, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } - visit_type_str(v, &ptr, name, &local_err); - if (!local_err) { - int ret; - ret = prop->info->parse(dev, prop, ptr); - if (ret != 0) { - error_set(errp, QERR_INVALID_PARAMETER_VALUE, - name, prop->info->name); - } - g_free(ptr); - } else { - error_propagate(errp, local_err); - } - } else { - error_set(errp, QERR_PERMISSION_DENIED); + ret = prop->info->parse(dev, prop, ptr); + if (ret != 0) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, + name, prop->info->name); } + g_free(ptr); } /** @@ -1194,8 +1186,8 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop, type = g_strdup_printf("legacy<%s>", prop->info->name); qdev_property_add(dev, prop->name, type, - qdev_get_legacy_property, - qdev_set_legacy_property, + prop->info->print ? qdev_get_legacy_property : NULL, + prop->info->parse ? qdev_set_legacy_property : NULL, NULL, prop, errp); -- 1.7.7.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 4/8] qom: interpret the return value when setting legacy properties 2011-12-18 16:05 [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Paolo Bonzini ` (2 preceding siblings ...) 2011-12-18 16:05 ` [Qemu-devel] [PATCH 3/8] qom: push permission checks up into qdev_property_add_legacy Paolo Bonzini @ 2011-12-18 16:05 ` Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE Paolo Bonzini ` (4 subsequent siblings) 8 siblings, 0 replies; 15+ messages in thread From: Paolo Bonzini @ 2011-12-18 16:05 UTC (permalink / raw) To: qemu-devel Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- hw/qdev-properties.c | 41 ++++++++++++++++++++++++++--------------- hw/qdev.c | 5 +---- hw/qdev.h | 2 ++ 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index f0b811c..de618f2 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -614,6 +614,28 @@ int qdev_prop_exists(DeviceState *dev, const char *name) return qdev_prop_find(dev, name) ? true : false; } +void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, + Property *prop, const char *value) +{ + switch (ret) { + case -EEXIST: + error_set(errp, QERR_PROPERTY_VALUE_IN_USE, + dev->info->name, prop->name, value); + break; + default: + case -EINVAL: + error_set(errp, QERR_PROPERTY_VALUE_BAD, + dev->info->name, prop->name, value); + break; + case -ENOENT: + error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND, + dev->info->name, prop->name, value); + break; + case 0: + break; + } +} + int qdev_prop_parse(DeviceState *dev, const char *name, const char *value) { Property *prop; @@ -632,21 +654,10 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value) } ret = prop->info->parse(dev, prop, value); if (ret < 0) { - switch (ret) { - case -EEXIST: - qerror_report(QERR_PROPERTY_VALUE_IN_USE, - dev->info->name, name, value); - break; - default: - case -EINVAL: - qerror_report(QERR_PROPERTY_VALUE_BAD, - dev->info->name, name, value); - break; - case -ENOENT: - qerror_report(QERR_PROPERTY_VALUE_NOT_FOUND, - dev->info->name, name, value); - break; - } + Error *err; + error_set_from_qdev_prop_error(&err, ret, dev, prop, value); + qerror_report_err(err); + error_free(err); return -1; } return 0; diff --git a/hw/qdev.c b/hw/qdev.c index c020a6f..2a146f7 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -1162,10 +1162,7 @@ static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque, } ret = prop->info->parse(dev, prop, ptr); - if (ret != 0) { - error_set(errp, QERR_INVALID_PARAMETER_VALUE, - name, prop->info->name); - } + error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr); g_free(ptr); } diff --git a/hw/qdev.h b/hw/qdev.h index 6e18427..94f5ce9 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -370,6 +370,8 @@ void qdev_prop_set_defaults(DeviceState *dev, Property *props); void qdev_prop_register_global_list(GlobalProperty *props); void qdev_prop_set_globals(DeviceState *dev); +void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, + Property *prop, const char *value); static inline const char *qdev_fw_name(DeviceState *dev) { -- 1.7.7.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE 2011-12-18 16:05 [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Paolo Bonzini ` (3 preceding siblings ...) 2011-12-18 16:05 ` [Qemu-devel] [PATCH 4/8] qom: interpret the return value when setting legacy properties Paolo Bonzini @ 2011-12-18 16:05 ` Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 6/8] qom: introduce get/set methods for Property Paolo Bonzini ` (3 subsequent siblings) 8 siblings, 0 replies; 15+ messages in thread From: Paolo Bonzini @ 2011-12-18 16:05 UTC (permalink / raw) To: qemu-devel This will be used when reject invalid values for integer fields that are less than 64-bits wide. Reviewed-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- qerror.c | 5 +++++ qerror.h | 3 +++ 2 files changed, 8 insertions(+), 0 deletions(-) diff --git a/qerror.c b/qerror.c index adde8a5..9a75d06 100644 --- a/qerror.c +++ b/qerror.c @@ -206,6 +206,11 @@ static const QErrorStringTable qerror_table[] = { .desc = "Property '%(device).%(property)' can't find value '%(value)'", }, { + .error_fmt = QERR_PROPERTY_VALUE_OUT_OF_RANGE, + .desc = "Property '%(device).%(property)' doesn't take " + "value %(value) (minimum: %(min), maximum: %(max)'", + }, + { .error_fmt = QERR_QMP_BAD_INPUT_OBJECT, .desc = "Expected '%(expected)' in QMP input", }, diff --git a/qerror.h b/qerror.h index 9190b02..efda232 100644 --- a/qerror.h +++ b/qerror.h @@ -171,6 +171,9 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_PROPERTY_VALUE_NOT_FOUND \ "{ 'class': 'PropertyValueNotFound', 'data': { 'device': %s, 'property': %s, 'value': %s } }" +#define QERR_PROPERTY_VALUE_OUT_OF_RANGE \ + "{ 'class': 'PropertyValueOutOfRange', 'data': { 'device': %s, 'property': %s, 'value': %"PRId64", 'min': %"PRId64", 'max': %"PRId64" } }" + #define QERR_QMP_BAD_INPUT_OBJECT \ "{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }" -- 1.7.7.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 6/8] qom: introduce get/set methods for Property 2011-12-18 16:05 [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Paolo Bonzini ` (4 preceding siblings ...) 2011-12-18 16:05 ` [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE Paolo Bonzini @ 2011-12-18 16:05 ` Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 7/8] qom: distinguish "legacy" property type name from QOM type name Paolo Bonzini ` (2 subsequent siblings) 8 siblings, 0 replies; 15+ messages in thread From: Paolo Bonzini @ 2011-12-18 16:05 UTC (permalink / raw) To: qemu-devel This patch adds a visitor interface to Property. This way, QOM will be able to expose Properties that access a fixed field in a struct without exposing also the everything-is-a-string "feature" of qdev properties. Whenever the printed representation in both QOM and qdev (which is typically the case for device backends), parse/print code can be reused via get_generic/set_generic. Dually, whenever multiple PropertyInfos have the same representation in both the struct and the visitors the code can be reused (for example among all of int32/uint32/hex32). Reviewed-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- hw/qdev-addr.c | 41 ++++++ hw/qdev-properties.c | 354 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/qdev.h | 4 + 3 files changed, 399 insertions(+), 0 deletions(-) diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c index 305c2d3..5ddda2d 100644 --- a/hw/qdev-addr.c +++ b/hw/qdev-addr.c @@ -18,12 +18,53 @@ static int print_taddr(DeviceState *dev, Property *prop, char *dest, size_t len) return snprintf(dest, len, "0x" TARGET_FMT_plx, *ptr); } +static void get_taddr(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop); + int64_t value; + + value = *ptr; + visit_type_int(v, &value, name, errp); +} + +static void set_taddr(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + int64_t value; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_int(v, &value, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if ((uint64_t)value <= (uint64_t) ~(target_phys_addr_t)0) { + *ptr = value; + } else { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, + dev->id?:"", name, value, (uint64_t) 0, + (uint64_t) ~(target_phys_addr_t)0); + } +} + + PropertyInfo qdev_prop_taddr = { .name = "taddr", .type = PROP_TYPE_TADDR, .size = sizeof(target_phys_addr_t), .parse = parse_taddr, .print = print_taddr, + .get = get_taddr, + .set = set_taddr, }; void qdev_prop_set_taddr(DeviceState *dev, const char *name, target_phys_addr_t value) diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index de618f2..41d2165 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -55,12 +55,44 @@ static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len) return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off"); } +static void get_bit(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + uint32_t *p = qdev_get_prop_ptr(dev, prop); + bool value = (*p & qdev_get_prop_mask(prop)) != 0; + + visit_type_bool(v, &value, name, errp); +} + +static void set_bit(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + Error *local_err = NULL; + bool value; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_bool(v, &value, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + bit_prop_set(dev, prop, value); +} + PropertyInfo qdev_prop_bit = { .name = "on/off", .type = PROP_TYPE_BIT, .size = sizeof(uint32_t), .parse = parse_bit, .print = print_bit, + .get = get_bit, + .set = set_bit, }; /* --- 8bit integer --- */ @@ -85,12 +117,54 @@ static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len) return snprintf(dest, len, "%" PRIu8, *ptr); } +static void get_int8(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + int8_t *ptr = qdev_get_prop_ptr(dev, prop); + int64_t value; + + value = *ptr; + visit_type_int(v, &value, name, errp); +} + +static void set_int8(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + int8_t *ptr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + int64_t value; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_int(v, &value, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (value > prop->info->min && value <= prop->info->max) { + *ptr = value; + } else { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, + dev->id?:"", name, value, prop->info->min, + prop->info->max); + } +} + PropertyInfo qdev_prop_uint8 = { .name = "uint8", .type = PROP_TYPE_UINT8, .size = sizeof(uint8_t), .parse = parse_uint8, .print = print_uint8, + .get = get_int8, + .set = set_int8, + .min = 0, + .max = 255, }; /* --- 8bit hex value --- */ @@ -120,6 +194,10 @@ PropertyInfo qdev_prop_hex8 = { .size = sizeof(uint8_t), .parse = parse_hex8, .print = print_hex8, + .get = get_int8, + .set = set_int8, + .min = 0, + .max = 255, }; /* --- 16bit integer --- */ @@ -144,12 +222,54 @@ static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len return snprintf(dest, len, "%" PRIu16, *ptr); } +static void get_int16(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + int16_t *ptr = qdev_get_prop_ptr(dev, prop); + int64_t value; + + value = *ptr; + visit_type_int(v, &value, name, errp); +} + +static void set_int16(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + int16_t *ptr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + int64_t value; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_int(v, &value, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (value > prop->info->min && value <= prop->info->max) { + *ptr = value; + } else { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, + dev->id?:"", name, value, prop->info->min, + prop->info->max); + } +} + PropertyInfo qdev_prop_uint16 = { .name = "uint16", .type = PROP_TYPE_UINT16, .size = sizeof(uint16_t), .parse = parse_uint16, .print = print_uint16, + .get = get_int16, + .set = set_int16, + .min = 0, + .max = 65535, }; /* --- 32bit integer --- */ @@ -174,12 +294,54 @@ static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len return snprintf(dest, len, "%" PRIu32, *ptr); } +static void get_int32(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + int32_t *ptr = qdev_get_prop_ptr(dev, prop); + int64_t value; + + value = *ptr; + visit_type_int(v, &value, name, errp); +} + +static void set_int32(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + int32_t *ptr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + int64_t value; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_int(v, &value, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (value > prop->info->min && value <= prop->info->max) { + *ptr = value; + } else { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, + dev->id?:"", name, value, prop->info->min, + prop->info->max); + } +} + PropertyInfo qdev_prop_uint32 = { .name = "uint32", .type = PROP_TYPE_UINT32, .size = sizeof(uint32_t), .parse = parse_uint32, .print = print_uint32, + .get = get_int32, + .set = set_int32, + .min = 0, + .max = 0xFFFFFFFFULL, }; static int parse_int32(DeviceState *dev, Property *prop, const char *str) @@ -207,6 +369,10 @@ PropertyInfo qdev_prop_int32 = { .size = sizeof(int32_t), .parse = parse_int32, .print = print_int32, + .get = get_int32, + .set = set_int32, + .min = -0x80000000LL, + .max = 0x7FFFFFFFLL, }; /* --- 32bit hex value --- */ @@ -236,6 +402,10 @@ PropertyInfo qdev_prop_hex32 = { .size = sizeof(uint32_t), .parse = parse_hex32, .print = print_hex32, + .get = get_int32, + .set = set_int32, + .min = 0, + .max = 0xFFFFFFFFULL, }; /* --- 64bit integer --- */ @@ -260,12 +430,37 @@ static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len return snprintf(dest, len, "%" PRIu64, *ptr); } +static void get_int64(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + int64_t *ptr = qdev_get_prop_ptr(dev, prop); + + visit_type_int(v, ptr, name, errp); +} + +static void set_int64(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + int64_t *ptr = qdev_get_prop_ptr(dev, prop); + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_int(v, ptr, name, errp); +} + PropertyInfo qdev_prop_uint64 = { .name = "uint64", .type = PROP_TYPE_UINT64, .size = sizeof(uint64_t), .parse = parse_uint64, .print = print_uint64, + .get = get_int64, + .set = set_int64, }; /* --- 64bit hex value --- */ @@ -295,6 +490,8 @@ PropertyInfo qdev_prop_hex64 = { .size = sizeof(uint64_t), .parse = parse_hex64, .print = print_hex64, + .get = get_int64, + .set = set_int64, }; /* --- string --- */ @@ -322,6 +519,48 @@ static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len return snprintf(dest, len, "\"%s\"", *ptr); } +static void get_string(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + char **ptr = qdev_get_prop_ptr(dev, prop); + + if (!*ptr) { + char *str = (char *)""; + visit_type_str(v, &str, name, errp); + } else { + visit_type_str(v, ptr, name, errp); + } +} + +static void set_string(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + char **ptr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + char *str; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_str(v, &str, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (!*str) { + g_free(str); + str = NULL; + } + if (*ptr) { + g_free(*ptr); + } + *ptr = str; +} + PropertyInfo qdev_prop_string = { .name = "string", .type = PROP_TYPE_STRING, @@ -329,6 +568,8 @@ PropertyInfo qdev_prop_string = { .parse = parse_string, .print = print_string, .free = free_string, + .get = get_string, + .set = set_string, }; /* --- drive --- */ @@ -364,12 +605,57 @@ static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len) *ptr ? bdrv_get_device_name(*ptr) : "<null>"); } +static void get_generic(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + void **ptr = qdev_get_prop_ptr(dev, prop); + char buffer[1024]; + char *p = buffer; + + buffer[0] = 0; + if (*ptr) { + prop->info->print(dev, prop, buffer, sizeof(buffer)); + } + visit_type_str(v, &p, name, errp); +} + +static void set_generic(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + Error *local_err = NULL; + char *str; + int ret; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_str(v, &str, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (!*str) { + g_free(str); + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); + return; + } + ret = prop->info->parse(dev, prop, str); + error_set_from_qdev_prop_error(errp, ret, dev, prop, str); + g_free(str); +} + PropertyInfo qdev_prop_drive = { .name = "drive", .type = PROP_TYPE_DRIVE, .size = sizeof(BlockDriverState *), .parse = parse_drive, .print = print_drive, + .get = get_generic, + .set = set_generic, .free = free_drive, }; @@ -407,6 +693,8 @@ PropertyInfo qdev_prop_chr = { .size = sizeof(CharDriverState*), .parse = parse_chr, .print = print_chr, + .get = get_generic, + .set = set_generic, }; /* --- netdev device --- */ @@ -441,6 +729,8 @@ PropertyInfo qdev_prop_netdev = { .size = sizeof(VLANClientState*), .parse = parse_netdev, .print = print_netdev, + .get = get_generic, + .set = set_generic, }; /* --- vlan --- */ @@ -469,12 +759,57 @@ static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) } } +static void get_vlan(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + VLANState **ptr = qdev_get_prop_ptr(dev, prop); + int64_t id; + + id = *ptr ? (*ptr)->id : -1; + visit_type_int(v, &id, name, errp); +} + +static void set_vlan(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + VLANState **ptr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + int64_t id; + VLANState *vlan; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_int(v, &id, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (id == -1) { + *ptr = NULL; + return; + } + vlan = qemu_find_vlan(id, 1); + if (!vlan) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, + name, prop->info->name); + return; + } + *ptr = vlan; +} + PropertyInfo qdev_prop_vlan = { .name = "vlan", .type = PROP_TYPE_VLAN, .size = sizeof(VLANClientState*), .parse = parse_vlan, .print = print_vlan, + .get = get_vlan, + .set = set_vlan, }; /* --- pointer --- */ @@ -531,6 +866,8 @@ PropertyInfo qdev_prop_macaddr = { .size = sizeof(MACAddr), .parse = parse_mac, .print = print_mac, + .get = get_generic, + .set = set_generic, }; /* --- pci address --- */ @@ -570,12 +907,29 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t } } +static void get_pci_devfn(DeviceState *dev, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + Property *prop = opaque; + uint32_t *ptr = qdev_get_prop_ptr(dev, prop); + char buffer[32]; + char *p = buffer; + + buffer[0] = 0; + if (*ptr != -1) { + snprintf(buffer, sizeof(buffer), "%02x.%x", *ptr >> 3, *ptr & 7); + } + visit_type_str(v, &p, name, errp); +} + PropertyInfo qdev_prop_pci_devfn = { .name = "pci-devfn", .type = PROP_TYPE_UINT32, .size = sizeof(uint32_t), .parse = parse_pci_devfn, .print = print_pci_devfn, + .get = get_pci_devfn, + .set = set_generic, }; /* --- public helpers --- */ diff --git a/hw/qdev.h b/hw/qdev.h index 94f5ce9..42495ae 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -158,9 +158,13 @@ struct PropertyInfo { const char *name; size_t size; enum PropertyType type; + int64_t min; + int64_t max; int (*parse)(DeviceState *dev, Property *prop, const char *str); int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); void (*free)(DeviceState *dev, Property *prop); + DevicePropertyAccessor *get; + DevicePropertyAccessor *set; }; typedef struct GlobalProperty { -- 1.7.7.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 7/8] qom: distinguish "legacy" property type name from QOM type name 2011-12-18 16:05 [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Paolo Bonzini ` (5 preceding siblings ...) 2011-12-18 16:05 ` [Qemu-devel] [PATCH 6/8] qom: introduce get/set methods for Property Paolo Bonzini @ 2011-12-18 16:05 ` Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 8/8] qom: register qdev properties also as non-legacy properties Paolo Bonzini 2011-12-19 20:18 ` [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Anthony Liguori 8 siblings, 0 replies; 15+ messages in thread From: Paolo Bonzini @ 2011-12-18 16:05 UTC (permalink / raw) To: qemu-devel Reviewed-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- hw/qdev-properties.c | 12 ++++++++---- hw/qdev.c | 9 ++++++--- hw/qdev.h | 1 + 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 41d2165..663c2a0 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -86,7 +86,8 @@ static void set_bit(DeviceState *dev, Visitor *v, void *opaque, } PropertyInfo qdev_prop_bit = { - .name = "on/off", + .name = "boolean", + .legacy_name = "on/off", .type = PROP_TYPE_BIT, .size = sizeof(uint32_t), .parse = parse_bit, @@ -189,7 +190,8 @@ static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len) } PropertyInfo qdev_prop_hex8 = { - .name = "hex8", + .name = "uint8", + .legacy_name = "hex8", .type = PROP_TYPE_UINT8, .size = sizeof(uint8_t), .parse = parse_hex8, @@ -397,7 +399,8 @@ static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len) } PropertyInfo qdev_prop_hex32 = { - .name = "hex32", + .name = "uint32", + .legacy_name = "hex32", .type = PROP_TYPE_UINT32, .size = sizeof(uint32_t), .parse = parse_hex32, @@ -485,7 +488,8 @@ static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len) } PropertyInfo qdev_prop_hex64 = { - .name = "hex64", + .name = "uint64", + .legacy_name = "hex64", .type = PROP_TYPE_UINT64, .size = sizeof(uint64_t), .parse = parse_hex64, diff --git a/hw/qdev.c b/hw/qdev.c index 2a146f7..c6fcf4c 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -218,13 +218,15 @@ int qdev_device_help(QemuOpts *opts) if (!prop->info->parse) { continue; /* no way to set it, don't show */ } - error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name); + error_printf("%s.%s=%s\n", info->name, prop->name, + prop->info->legacy_name ?: prop->info->name); } for (prop = info->bus_info->props; prop && prop->name; prop++) { if (!prop->info->parse) { continue; /* no way to set it, don't show */ } - error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name); + error_printf("%s.%s=%s\n", info->name, prop->name, + prop->info->legacy_name ?: prop->info->name); } return 1; } @@ -1180,7 +1182,8 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop, { gchar *type; - type = g_strdup_printf("legacy<%s>", prop->info->name); + type = g_strdup_printf("legacy<%s>", + prop->info->legacy_name ?: prop->info->name); qdev_property_add(dev, prop->name, type, prop->info->print ? qdev_get_legacy_property : NULL, diff --git a/hw/qdev.h b/hw/qdev.h index 42495ae..5f23cac 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -156,6 +156,7 @@ enum PropertyType { struct PropertyInfo { const char *name; + const char *legacy_name; size_t size; enum PropertyType type; int64_t min; -- 1.7.7.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 8/8] qom: register qdev properties also as non-legacy properties 2011-12-18 16:05 [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Paolo Bonzini ` (6 preceding siblings ...) 2011-12-18 16:05 ` [Qemu-devel] [PATCH 7/8] qom: distinguish "legacy" property type name from QOM type name Paolo Bonzini @ 2011-12-18 16:05 ` Paolo Bonzini 2011-12-19 20:18 ` [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Anthony Liguori 8 siblings, 0 replies; 15+ messages in thread From: Paolo Bonzini @ 2011-12-18 16:05 UTC (permalink / raw) To: qemu-devel Push legacy properties into a "legacy-..." namespace, and make them available with correct types too. For now, all properties come in both variants. This need not be the case for string properties. We will revisit this after -device is changed to actually use the legacy properties. Reviewed-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- hw/qdev.c | 28 +++++++++++++++++++++++++--- hw/qdev.h | 7 +++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index c6fcf4c..0465632 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -80,6 +80,9 @@ static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name) return NULL; } +static void qdev_property_add_legacy(DeviceState *dev, Property *prop, + Error **errp); + static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info) { DeviceState *dev; @@ -104,10 +107,12 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info) for (prop = dev->info->props; prop && prop->name; prop++) { qdev_property_add_legacy(dev, prop, NULL); + qdev_property_add_static(dev, prop, NULL); } for (prop = dev->info->bus_info->props; prop && prop->name; prop++) { qdev_property_add_legacy(dev, prop, NULL); + qdev_property_add_static(dev, prop, NULL); } qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL); @@ -1172,7 +1177,7 @@ static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque, * @qdev_add_legacy_property - adds a legacy property * * Do not use this is new code! Properties added through this interface will - * be given types in the "legacy<>" type namespace. + * be given names and types in the "legacy" namespace. * * Legacy properties are always processed as strings. The format of the string * depends on the property type. @@ -1180,18 +1185,35 @@ static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque, void qdev_property_add_legacy(DeviceState *dev, Property *prop, Error **errp) { - gchar *type; + gchar *name, *type; + name = g_strdup_printf("legacy-%s", prop->name); type = g_strdup_printf("legacy<%s>", prop->info->legacy_name ?: prop->info->name); - qdev_property_add(dev, prop->name, type, + qdev_property_add(dev, name, type, prop->info->print ? qdev_get_legacy_property : NULL, prop->info->parse ? qdev_set_legacy_property : NULL, NULL, prop, errp); g_free(type); + g_free(name); +} + +/** + * @qdev_property_add_static - add a @Property to a device. + * + * Static properties access data in a struct. The actual type of the + * property and the field depends on the property type. + */ +void qdev_property_add_static(DeviceState *dev, Property *prop, + Error **errp) +{ + qdev_property_add(dev, prop->name, prop->info->name, + prop->info->get, prop->info->set, + NULL, + prop, errp); } DeviceState *qdev_get_root(void) diff --git a/hw/qdev.h b/hw/qdev.h index 5f23cac..d5896be 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -487,11 +487,10 @@ const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp); /** - * @qdev_property_add_legacy - add a legacy @Property to a device - * - * DO NOT USE THIS IN NEW CODE! + * @qdev_property_add_static - add a @Property to a device referencing a + * field in a struct. */ -void qdev_property_add_legacy(DeviceState *dev, Property *prop, Error **errp); +void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp); /** * @qdev_get_root - returns the root device of the composition tree -- 1.7.7.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties 2011-12-18 16:05 [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Paolo Bonzini ` (7 preceding siblings ...) 2011-12-18 16:05 ` [Qemu-devel] [PATCH 8/8] qom: register qdev properties also as non-legacy properties Paolo Bonzini @ 2011-12-19 20:18 ` Anthony Liguori 8 siblings, 0 replies; 15+ messages in thread From: Anthony Liguori @ 2011-12-19 20:18 UTC (permalink / raw) To: Paolo Bonzini; +Cc: qemu-devel On 12/18/2011 10:05 AM, Paolo Bonzini wrote: > QOM right now does not have a way to communicate values for qdev > properties except as strings. This is bad. > > This patch improves the Property implementation so that properties > export a visitor-based interface in addition to the string-based > interface. The new interface can then be registered as a "static" > property. It's called static because it uses a struct field for > storage and, as such, should be present in all objects of a given > class. > > Patches 1-2 are bugfixes and patches 3-4 are cleanups. Applied all. Thanks. Regards, Anthony Liguori > > Example using qmp-shell: > > x86_64-softmmu/qemu-system-x86_64 \ > -hda ~/test.img -snapshot -S \ > -qmp unix:/tmp/server.sock,server,nowait \ > -netdev type=user,id=net -device virtio-net-pci,netdev=net,id=net \ > -net user,vlan=1 -device virtio-net-pci,id=net2,vlan=1 \ > -chardev id=stdio,backend=stdio -device isa-serial,chardev=stdio,id=serial > > Boolean properties: > > (QEMU) qom-get path=/i440fx/piix3 property=command_serr_enable > {u'return': True} > (QEMU) qom-get path=/i440fx/piix3 property=legacy<command_serr_enable> > {u'return': u'on'} > > PCI address properties (perhaps will disappear later, but not yet): > > (QEMU) qom-get path=/i440fx/piix3 property=addr > {u'return': u'01.0'} > (QEMU) qom-get path=/i440fx/piix3 property=legacy-addr > {u'return': u'01.0'} > > String properties (NULL mapped to empty string): > > (QEMU) qom-get path=/vga property=romfile > {u'return': u'vgabios-cirrus.bin'} > (QEMU) qom-get path=/vga property=legacy-romfile > {u'return': u'"vgabios-cirrus.bin"'} > (QEMU) qom-get path=/i440fx/piix3 property=romfile > {u'return': u''} > (QEMU) qom-get path=/i440fx/piix3 property=legacy-romfile > {u'return': u'<null>'} > > MAC properties: > > (QEMU) qom-get path=/peripheral/net property=mac > {u'return': u'52:54:00:12:34:56'} > (QEMU) qom-get path=/peripheral/net property=legacy-mac > {u'return': u'52:54:00:12:34:56'} > (QEMU) qom-set path=/peripheral/net property=mac value=52-54-00-12-34-57 > {u'error': {u'data': {}, u'class': u'PermissionDenied', u'desc': u'Insufficient permission to perform this operation'}} > > Network properties: > > (QEMU) qom-get path=/peripheral/net property=netdev > {u'return': u'net'} > (QEMU) qom-get path=/peripheral/net property=legacy-netdev > {u'return': u'net'} > > VLAN properties: > > (QEMU) qom-get path=/peripheral/net property=vlan > {u'return': -1} > (QEMU) qom-get path=/peripheral/net property=legacy-vlan > {u'return': u'<null>'} > (QEMU) qom-get path=/peripheral/net2 property=vlan > {u'return': 1} > (QEMU) qom-get path=/peripheral/net2 property=legacy-vlan > {u'return': u'1'} > > Chardev properties: > > (QEMU) qom-get path=/peripheral/serial property=chardev > {u'return': u'stdio'} > (QEMU) qom-get path=/peripheral/serial property=legacy-chardev > {u'return': u'stdio'} > > Legacy hex32 properties: > > (QEMU) qom-get path=/peripheral/serial property=iobase > {u'return': 1016} > (QEMU) qom-get path=/peripheral/serial property=legacy-iobase > {u'return': u'0x3f8'} > > Examples of setting properties (after disabling the DEV_STATE_CREATED > check for testing only): > > (QEMU) qom-set path=/peripheral/net2 property=vlan value=-1 > {u'return': {}} > (QEMU) qom-get path=/peripheral/net2 property=vlan > {u'return': -1} > (QEMU) qom-get path=/peripheral/net2 property=legacy-vlan > {u'return': u'<null>'} > > (QEMU) qom-set path=/peripheral/serial property=iobase value=760 > {u'return': {}} > (QEMU) qom-get path=/peripheral/serial property=iobase > {u'return': 760} > (QEMU) qom-get path=/peripheral/serial property=legacy-iobase > {u'return': u'0x2f8'} > > v2->v3: > Tweaks to patch 4. > > v1->v2: > New "qom: interpret the return value when setting legacy > properties". Always pass a value to the visitor when there > is no error. Handle empty strings as NULL. Did not change > QERR_PROPERTY_VALUE_OUT_OF_RANGE because it is consistent > with other QERR_PROPERTY_* errors, now used by QOM too. > > Paolo Bonzini (8): > qapi: protect against NULL QObject in qmp_input_get_object > qom: fix swapped parameters > qom: push permission checks up into qdev_property_add_legacy > qom: interpret the return value when setting legacy properties > qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE > qom: introduce get/set methods for Property > qom: distinguish "legacy" property type name from QOM type name > qom: register qdev properties also as non-legacy properties > > hw/qdev-addr.c | 41 +++++ > hw/qdev-properties.c | 407 +++++++++++++++++++++++++++++++++++++++++++-- > hw/qdev.c | 84 ++++++---- > hw/qdev.h | 14 +- > qapi/qmp-input-visitor.c | 10 +- > qerror.c | 5 + > qerror.h | 3 + > 7 files changed, 502 insertions(+), 62 deletions(-) > ^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 0/8] qom: introduce non-legacy static properties @ 2011-12-16 12:01 Paolo Bonzini 2011-12-16 12:01 ` [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE Paolo Bonzini 0 siblings, 1 reply; 15+ messages in thread From: Paolo Bonzini @ 2011-12-16 12:01 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf QOM right now does not have a way to communicate values for qdev properties except as strings. This is bad. This patch improves the Property implementation so that properties export a visitor-based interface in addition to the string-based interface. The new interface can then be registered as a "static" property. It's called static because it uses a struct field for storage and, as such, should be present in all objects of a given class. Patches 1-3 are bugfixes and patch 4 is a cleanup, so please apply those at least. Example using qmp-shell: x86_64-softmmu/qemu-system-x86_64 \ -hda ~/test.img -snapshot -S \ -qmp unix:/tmp/server.sock,server,nowait \ -netdev type=user,id=net -device virtio-net-pci,netdev=net,id=net \ -net user,vlan=1 -device virtio-net-pci,id=net2,vlan=1 \ -chardev id=stdio,backend=stdio -device isa-serial,chardev=stdio,id=serial Boolean properties: (QEMU) qom-get path=/i440fx/piix3 property=command_serr_enable {u'return': True} (QEMU) qom-get path=/i440fx/piix3 property=legacy<command_serr_enable> {u'return': u'on'} PCI address properties (perhaps will disappear later, but not yet): (QEMU) qom-get path=/i440fx/piix3 property=addr {u'return': u'01.0'} (QEMU) qom-get path=/i440fx/piix3 property=legacy<addr> {u'return': u'01.0'} String properties (QObject does not have NULL): (QEMU) qom-get path=/vga property=romfile {u'return': u'vgabios-cirrus.bin'} (QEMU) qom-get path=/vga property=legacy<romfile> {u'return': u'"vgabios-cirrus.bin"'} (QEMU) qom-get path=/i440fx/piix3 property=romfile {u'return': {}} (QEMU) qom-get path=/i440fx/piix3 property=legacy<romfile> {u'return': u'<null>'} MAC properties: (QEMU) qom-get path=/peripheral/net property=mac {u'return': u'52:54:00:12:34:56'} (QEMU) qom-get path=/peripheral/net property=legacy<mac> {u'return': u'52:54:00:12:34:56'} (QEMU) qom-set path=/peripheral/net property=mac value=52-54-00-12-34-57 {u'error': {u'data': {}, u'class': u'PermissionDenied', u'desc': u'Insufficient permission to perform this operation'}} Network properties: (QEMU) qom-get path=/peripheral/net property=netdev {u'return': u'net'} (QEMU) qom-get path=/peripheral/net property=legacy<netdev> {u'return': u'net'} VLAN properties: (QEMU) qom-get path=/peripheral/net property=vlan {u'return': {}} (QEMU) qom-get path=/peripheral/net property=legacy<vlan> {u'return': u'<null>'} (QEMU) qom-get path=/peripheral/net2 property=vlan {u'return': 1} (QEMU) qom-get path=/peripheral/net2 property=legacy<vlan> {u'return': u'1'} Chardev properties: (QEMU) qom-get path=/peripheral/serial property=chardev {u'return': u'stdio'} (QEMU) qom-get path=/peripheral/serial property=legacy<chardev> {u'return': u'stdio'} Legacy hex32 properties: (QEMU) qom-get path=/peripheral/serial property=iobase {u'return': 1016} (QEMU) qom-get path=/peripheral/serial property=legacy<iobase> {u'return': u'0x3f8'} Examples of setting properties (after disabling the DEV_STATE_CREATED check for testing only): (QEMU) qom-set path=/peripheral/net2 property=vlan value=-1 {u'return': {}} (QEMU) qom-get path=/peripheral/net2 property=vlan {u'return': {}} (QEMU) qom-get path=/peripheral/net2 property=legacy<vlan> {u'return': u'<null>'} (QEMU) qom-set path=/peripheral/serial property=iobase value=760 {u'return': {}} (QEMU) qom-get path=/peripheral/serial property=iobase {u'return': 760} (QEMU) qom-get path=/peripheral/serial property=legacy<iobase> {u'return': u'0x2f8'} Paolo Bonzini (8): qapi: fix NULL pointer dereference qapi: protect against NULL QObject in qmp_input_get_object qom: fix swapped parameters qom: push permission checks up into qdev_property_add_legacy qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE qom: introduce get/set methods for Property qom: distinguish "legacy" property type name from QOM type name qom: register qdev properties also as non-legacy properties hw/qdev-addr.c | 41 +++++ hw/qdev-properties.c | 360 ++++++++++++++++++++++++++++++++++++++++++++- hw/qdev.c | 85 +++++++----- hw/qdev.h | 12 +- qapi/qmp-input-visitor.c | 10 +- qapi/qmp-output-visitor.c | 4 +- qerror.c | 5 + qerror.h | 3 + 8 files changed, 472 insertions(+), 48 deletions(-) -- 1.7.7.1 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE 2011-12-16 12:01 [Qemu-devel] [PATCH " Paolo Bonzini @ 2011-12-16 12:01 ` Paolo Bonzini 2011-12-16 14:00 ` Anthony Liguori 0 siblings, 1 reply; 15+ messages in thread From: Paolo Bonzini @ 2011-12-16 12:01 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf This will be used when reject invalid values for integer fields that are less than 64-bits wide. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- qerror.c | 5 +++++ qerror.h | 3 +++ 2 files changed, 8 insertions(+), 0 deletions(-) diff --git a/qerror.c b/qerror.c index adde8a5..9a75d06 100644 --- a/qerror.c +++ b/qerror.c @@ -206,6 +206,11 @@ static const QErrorStringTable qerror_table[] = { .desc = "Property '%(device).%(property)' can't find value '%(value)'", }, { + .error_fmt = QERR_PROPERTY_VALUE_OUT_OF_RANGE, + .desc = "Property '%(device).%(property)' doesn't take " + "value %(value) (minimum: %(min), maximum: %(max)'", + }, + { .error_fmt = QERR_QMP_BAD_INPUT_OBJECT, .desc = "Expected '%(expected)' in QMP input", }, diff --git a/qerror.h b/qerror.h index 9190b02..efda232 100644 --- a/qerror.h +++ b/qerror.h @@ -171,6 +171,9 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_PROPERTY_VALUE_NOT_FOUND \ "{ 'class': 'PropertyValueNotFound', 'data': { 'device': %s, 'property': %s, 'value': %s } }" +#define QERR_PROPERTY_VALUE_OUT_OF_RANGE \ + "{ 'class': 'PropertyValueOutOfRange', 'data': { 'device': %s, 'property': %s, 'value': %"PRId64", 'min': %"PRId64", 'max': %"PRId64" } }" + #define QERR_QMP_BAD_INPUT_OBJECT \ "{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }" -- 1.7.7.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE 2011-12-16 12:01 ` [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE Paolo Bonzini @ 2011-12-16 14:00 ` Anthony Liguori 2011-12-16 14:01 ` Paolo Bonzini 0 siblings, 1 reply; 15+ messages in thread From: Anthony Liguori @ 2011-12-16 14:00 UTC (permalink / raw) To: Paolo Bonzini; +Cc: kwolf, qemu-devel On 12/16/2011 06:01 AM, Paolo Bonzini wrote: > This will be used when reject invalid values for integer fields that > are less than 64-bits wide. > > Signed-off-by: Paolo Bonzini<pbonzini@redhat.com> I'd rather use generic errors when possible. How about VALUE_OUT_OF_RANGE and we can make the message "'%(item)' doesn't take value..." and pass "%s.%s" % (device, property) for item. Regards, Anthony Liguori > --- > qerror.c | 5 +++++ > qerror.h | 3 +++ > 2 files changed, 8 insertions(+), 0 deletions(-) > > diff --git a/qerror.c b/qerror.c > index adde8a5..9a75d06 100644 > --- a/qerror.c > +++ b/qerror.c > @@ -206,6 +206,11 @@ static const QErrorStringTable qerror_table[] = { > .desc = "Property '%(device).%(property)' can't find value '%(value)'", > }, > { > + .error_fmt = QERR_PROPERTY_VALUE_OUT_OF_RANGE, > + .desc = "Property '%(device).%(property)' doesn't take " > + "value %(value) (minimum: %(min), maximum: %(max)'", > + }, > + { > .error_fmt = QERR_QMP_BAD_INPUT_OBJECT, > .desc = "Expected '%(expected)' in QMP input", > }, > diff --git a/qerror.h b/qerror.h > index 9190b02..efda232 100644 > --- a/qerror.h > +++ b/qerror.h > @@ -171,6 +171,9 @@ QError *qobject_to_qerror(const QObject *obj); > #define QERR_PROPERTY_VALUE_NOT_FOUND \ > "{ 'class': 'PropertyValueNotFound', 'data': { 'device': %s, 'property': %s, 'value': %s } }" > > +#define QERR_PROPERTY_VALUE_OUT_OF_RANGE \ > + "{ 'class': 'PropertyValueOutOfRange', 'data': { 'device': %s, 'property': %s, 'value': %"PRId64", 'min': %"PRId64", 'max': %"PRId64" } }" > + > #define QERR_QMP_BAD_INPUT_OBJECT \ > "{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }" > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE 2011-12-16 14:00 ` Anthony Liguori @ 2011-12-16 14:01 ` Paolo Bonzini 2011-12-16 17:00 ` Paolo Bonzini 0 siblings, 1 reply; 15+ messages in thread From: Paolo Bonzini @ 2011-12-16 14:01 UTC (permalink / raw) To: Anthony Liguori; +Cc: kwolf, qemu-devel On 12/16/2011 03:00 PM, Anthony Liguori wrote: >> This will be used when reject invalid values for integer fields that >> are less than 64-bits wide. >> >> Signed-off-by: Paolo Bonzini<pbonzini@redhat.com> > > I'd rather use generic errors when possible. How about > VALUE_OUT_OF_RANGE and we can make the message "'%(item)' doesn't take > value..." and pass "%s.%s" % (device, property) for item. Ok. Paolo ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE 2011-12-16 14:01 ` Paolo Bonzini @ 2011-12-16 17:00 ` Paolo Bonzini 2011-12-16 17:01 ` Anthony Liguori 0 siblings, 1 reply; 15+ messages in thread From: Paolo Bonzini @ 2011-12-16 17:00 UTC (permalink / raw) Cc: kwolf, qemu-devel On 12/16/2011 03:01 PM, Paolo Bonzini wrote: >> >> I'd rather use generic errors when possible. How about >> VALUE_OUT_OF_RANGE and we can make the message "'%(item)' doesn't take >> value..." and pass "%s.%s" % (device, property) for item. > > Ok. I didn't do this in the end for two reasons. First, that it is inconsistent with other errors from qdev properties. Current master does not raise them when properties are accessed via QOM, but my revised series does. Second, that it is actually provides less structured information. There's no reason why a client should be expected to "know" that %(item) is in that form. Paolo ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE 2011-12-16 17:00 ` Paolo Bonzini @ 2011-12-16 17:01 ` Anthony Liguori 0 siblings, 0 replies; 15+ messages in thread From: Anthony Liguori @ 2011-12-16 17:01 UTC (permalink / raw) To: Paolo Bonzini; +Cc: kwolf, qemu-devel On 12/16/2011 11:00 AM, Paolo Bonzini wrote: > On 12/16/2011 03:01 PM, Paolo Bonzini wrote: >>> >>> I'd rather use generic errors when possible. How about >>> VALUE_OUT_OF_RANGE and we can make the message "'%(item)' doesn't take >>> value..." and pass "%s.%s" % (device, property) for item. >> >> Ok. > > I didn't do this in the end for two reasons. > > First, that it is inconsistent with other errors from qdev properties. Current > master does not raise them when properties are accessed via QOM, but my revised > series does. > > Second, that it is actually provides less structured information. There's no > reason why a client should be expected to "know" that %(item) is in that form. Ok, then Reviewed-by: Anthony Liguori <aliguori@us.ibm.com> Regards, Anthony Liguori > Paolo ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2011-12-19 20:18 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-12-18 16:05 [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 1/8] qapi: protect against NULL QObject in qmp_input_get_object Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 2/8] qom: fix swapped parameters Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 3/8] qom: push permission checks up into qdev_property_add_legacy Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 4/8] qom: interpret the return value when setting legacy properties Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 6/8] qom: introduce get/set methods for Property Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 7/8] qom: distinguish "legacy" property type name from QOM type name Paolo Bonzini 2011-12-18 16:05 ` [Qemu-devel] [PATCH 8/8] qom: register qdev properties also as non-legacy properties Paolo Bonzini 2011-12-19 20:18 ` [Qemu-devel] [PATCH v3 0/8] qom: introduce non-legacy static properties Anthony Liguori -- strict thread matches above, loose matches on Subject: below -- 2011-12-16 12:01 [Qemu-devel] [PATCH " Paolo Bonzini 2011-12-16 12:01 ` [Qemu-devel] [PATCH 5/8] qom: introduce QERR_PROPERTY_VALUE_OUT_OF_RANGE Paolo Bonzini 2011-12-16 14:00 ` Anthony Liguori 2011-12-16 14:01 ` Paolo Bonzini 2011-12-16 17:00 ` Paolo Bonzini 2011-12-16 17:01 ` Anthony Liguori
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).