aboutsummaryrefslogtreecommitdiff
path: root/include/hw/qdev-properties.h
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2023-11-09 18:42:40 +0100
committerKevin Wolf <kwolf@redhat.com>2023-11-10 18:19:19 +0100
commitb06f8b500da2a5a73dfb15de17cd96ad2385fdc7 (patch)
tree7e57b28a47c33f73a7cfa8a8f12f406955480419 /include/hw/qdev-properties.h
parent3257b854d81ca3ebe6f14375e83a0ed2db3c7562 (diff)
qdev: Rework array properties based on list visitor
Until now, array properties are actually implemented with a hack that uses multiple properties on the QOM level: a static "foo-len" property and after it is set, dynamically created "foo[i]" properties. In external interfaces (-device on the command line and device_add in QMP), this interface was broken by commit f3558b1b ('qdev: Base object creation on QDict rather than QemuOpts') because QDicts are unordered and therefore it could happen that QEMU tried to set the indexed properties before setting the length, which fails and effectively makes array properties inaccessible. In particular, this affects the 'ports' property of the 'rocker' device, which used to be configured like this: -device rocker,len-ports=2,ports[0]=dev0,ports[1]=dev1 This patch reworks the external interface so that instead of using a separate top-level property for the length and for each element, we use a single true array property that accepts a list value. In the external interfaces, this is naturally expressed as a JSON list and makes array properties accessible again. The new syntax looks like this: -device '{"driver":"rocker","ports":["dev0","dev1"]}' Creating an array property on the command line without using JSON format is currently not possible. This could be fixed by switching from QemuOpts to a keyval parser, which however requires consideration of the compatibility implications. All internal users of devices with array properties go through qdev_prop_set_array() at this point, so updating it takes care of all of them. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1090 Fixes: f3558b1b763683bb877f7dd5b282469cdadc65c3 Signed-off-by: Kevin Wolf <kwolf@redhat.com> Message-ID: <20231109174240.72376-12-kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'include/hw/qdev-properties.h')
-rw-r--r--include/hw/qdev-properties.h35
1 files changed, 15 insertions, 20 deletions
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 7fa2fdb7c9..25743a29a0 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -61,7 +61,7 @@ extern const PropertyInfo qdev_prop_size;
extern const PropertyInfo qdev_prop_string;
extern const PropertyInfo qdev_prop_on_off_auto;
extern const PropertyInfo qdev_prop_size32;
-extern const PropertyInfo qdev_prop_arraylen;
+extern const PropertyInfo qdev_prop_array;
extern const PropertyInfo qdev_prop_link;
#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) { \
@@ -115,8 +115,6 @@ extern const PropertyInfo qdev_prop_link;
.bitmask = (_bitmask), \
.set_default = false)
-#define PROP_ARRAY_LEN_PREFIX "len-"
-
/**
* DEFINE_PROP_ARRAY:
* @_name: name of the array
@@ -127,28 +125,25 @@ extern const PropertyInfo qdev_prop_link;
* @_arrayprop: PropertyInfo defining what property the array elements have
* @_arraytype: C type of the array elements
*
- * Define device properties for a variable-length array _name. A
- * static property "len-arrayname" is defined. When the device creator
- * sets this property to the desired length of array, further dynamic
- * properties "arrayname[0]", "arrayname[1]", ... are defined so the
- * device creator can set the array element values. Setting the
- * "len-arrayname" property more than once is an error.
+ * Define device properties for a variable-length array _name. The array is
+ * represented as a list in the visitor interface.
+ *
+ * @_arraytype is required to be movable with memcpy().
*
- * When the array length is set, the @_field member of the device
+ * When the array property is set, the @_field member of the device
* struct is set to the array length, and @_arrayfield is set to point
- * to (zero-initialised) memory allocated for the array. For a zero
- * length array, @_field will be set to 0 and @_arrayfield to NULL.
+ * to the memory allocated for the array.
+ *
* It is the responsibility of the device deinit code to free the
* @_arrayfield memory.
*/
-#define DEFINE_PROP_ARRAY(_name, _state, _field, \
- _arrayfield, _arrayprop, _arraytype) \
- DEFINE_PROP((PROP_ARRAY_LEN_PREFIX _name), \
- _state, _field, qdev_prop_arraylen, uint32_t, \
- .set_default = true, \
- .defval.u = 0, \
- .arrayinfo = &(_arrayprop), \
- .arrayfieldsize = sizeof(_arraytype), \
+#define DEFINE_PROP_ARRAY(_name, _state, _field, \
+ _arrayfield, _arrayprop, _arraytype) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_array, uint32_t, \
+ .set_default = true, \
+ .defval.u = 0, \
+ .arrayinfo = &(_arrayprop), \
+ .arrayfieldsize = sizeof(_arraytype), \
.arrayoffset = offsetof(_state, _arrayfield))
#define DEFINE_PROP_LINK(_name, _state, _field, _type, _ptr_type) \