Currently we allow devices to define "link properties" with
DEFINE_PROP_LINK(): these are a way to give a device a pointer to
another QOM object. (Under the hood this is done by handing it the
canonical QOM path for the object.)
We also allow devices to define "array properties" with
DEFINE_PROP_ARRAY(): these are a way to give a device a
variable-length array of properties.
However, there is no way to define an array of link properties. If
you try to do it by passing qdev_prop_link as the arrayprop argument
to DEFINE_PROP_ARRAY() you will get a crash because qdev_prop_link
does not provide the .set and .get methods in its PropertyInfo
struct.
This patch implements a new DEFINE_PROP_LINK_ARRAY(). In
a device you can use it like this:
struct MyDevice {
...
uint32_t num_cpus;
ARMCPU **cpus;
}
and in your Property array:
DEFINE_PROP_LINK_ARRAY("cpus", MyDevice, num_cpus, cpus,
TYPE_ARM_CPU, ARMCPU *),
The array property code will fill in s->num_cpus, allocate memory in
s->cpus, and populate it with pointers.
On the device-creation side you set the property in the same way as
the existing array properties, using the new qlist_append_link()
function to append to the QList:
QList *cpulist = qlist_new();
for (int i = 0; i < cpus; i++) {
qlist_append_link(cpulist, OBJECT(cpu[i]));
}
qdev_prop_set_array(mydev, "cpus", cpulist);
The implementation is mostly in the provision of the .set and
.get methods to the qdev_prop_link PropertyInfo struct. The
code of these methods parallels the code in
object_set_link_property() and object_get_link_property(). We can't
completely share the code with those functions because of differences
in where we get the information like the target QOM type, but I have
pulled out a new function object_resolve_and_typecheck() for the
shared "given a QOM path and a type, give me the object or an error"
code.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-id: 20260327111700.795099-3-peter.maydell@linaro.org
325 lines
14 KiB
C
325 lines
14 KiB
C
#ifndef QEMU_QDEV_PROPERTIES_H
|
|
#define QEMU_QDEV_PROPERTIES_H
|
|
|
|
#include "qom/compat-properties.h"
|
|
#include "hw/core/qdev.h"
|
|
|
|
/**
|
|
* Property:
|
|
* @set_default: true if the default value should be set from @defval,
|
|
* in which case @info->set_default_value must not be NULL
|
|
* (if false then no default value is set by the property system
|
|
* and the field retains whatever value it was given by instance_init).
|
|
* @defval: default value for the property. This is used only if @set_default
|
|
* is true.
|
|
*/
|
|
struct Property {
|
|
const char *name;
|
|
const PropertyInfo *info;
|
|
ptrdiff_t offset;
|
|
const char *link_type;
|
|
uint64_t bitmask;
|
|
union {
|
|
int64_t i;
|
|
uint64_t u;
|
|
} defval;
|
|
const PropertyInfo *arrayinfo;
|
|
int arrayoffset;
|
|
int arrayfieldsize;
|
|
uint8_t bitnr;
|
|
bool set_default;
|
|
};
|
|
|
|
struct PropertyInfo {
|
|
const char *type;
|
|
const char *description;
|
|
const QEnumLookup *enum_table;
|
|
bool realized_set_allowed; /* allow setting property on realized device */
|
|
char *(*print)(Object *obj, const Property *prop);
|
|
void (*set_default_value)(ObjectProperty *op, const Property *prop);
|
|
ObjectProperty *(*create)(ObjectClass *oc, const char *name,
|
|
const Property *prop);
|
|
ObjectPropertyAccessor *get;
|
|
ObjectPropertyAccessor *set;
|
|
ObjectPropertyRelease *release;
|
|
};
|
|
|
|
/**
|
|
* struct OnOffAutoBit64 - OnOffAuto storage with 64 elements.
|
|
* @on_bits: Bitmap of elements with "on".
|
|
* @auto_bits: Bitmap of elements with "auto".
|
|
*/
|
|
typedef struct OnOffAutoBit64 {
|
|
uint64_t on_bits;
|
|
uint64_t auto_bits;
|
|
} OnOffAutoBit64;
|
|
|
|
|
|
/*** qdev-properties.c ***/
|
|
|
|
extern const PropertyInfo qdev_prop_bit;
|
|
extern const PropertyInfo qdev_prop_bit64;
|
|
extern const PropertyInfo qdev_prop_on_off_auto_bit64;
|
|
extern const PropertyInfo qdev_prop_bool;
|
|
extern const PropertyInfo qdev_prop_uint8;
|
|
extern const PropertyInfo qdev_prop_uint16;
|
|
extern const PropertyInfo qdev_prop_uint32;
|
|
extern const PropertyInfo qdev_prop_usize;
|
|
extern const PropertyInfo qdev_prop_int32;
|
|
extern const PropertyInfo qdev_prop_uint64;
|
|
extern const PropertyInfo qdev_prop_uint64_checkmask;
|
|
extern const PropertyInfo qdev_prop_int64;
|
|
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_array;
|
|
extern const PropertyInfo qdev_prop_link;
|
|
|
|
#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) { \
|
|
.name = (_name), \
|
|
.info = &(_prop), \
|
|
.offset = offsetof(_state, _field) \
|
|
+ type_check(_type, typeof_field(_state, _field)), \
|
|
__VA_ARGS__ \
|
|
}
|
|
|
|
#define DEFINE_PROP_SIGNED(_name, _state, _field, _defval, _prop, _type) \
|
|
DEFINE_PROP(_name, _state, _field, _prop, _type, \
|
|
.set_default = true, \
|
|
.defval.i = (_type)_defval)
|
|
|
|
#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \
|
|
DEFINE_PROP(_name, _state, _field, _prop, _type)
|
|
|
|
#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) \
|
|
DEFINE_PROP(_name, _state, _field, qdev_prop_bit, uint32_t, \
|
|
.bitnr = (_bit), \
|
|
.set_default = true, \
|
|
.defval.u = (bool)_defval)
|
|
|
|
#define DEFINE_PROP_UNSIGNED(_name, _state, _field, _defval, _prop, _type) \
|
|
DEFINE_PROP(_name, _state, _field, _prop, _type, \
|
|
.set_default = true, \
|
|
.defval.u = (_type)_defval)
|
|
|
|
#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \
|
|
DEFINE_PROP(_name, _state, _field, _prop, _type)
|
|
|
|
#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) \
|
|
DEFINE_PROP(_name, _state, _field, qdev_prop_bit64, uint64_t, \
|
|
.bitnr = (_bit), \
|
|
.set_default = true, \
|
|
.defval.u = (bool)_defval)
|
|
|
|
#define DEFINE_PROP_ON_OFF_AUTO_BIT64(_name, _state, _field, _bit, _defval) \
|
|
DEFINE_PROP(_name, _state, _field, qdev_prop_on_off_auto_bit64, \
|
|
OnOffAutoBit64, \
|
|
.bitnr = (_bit), \
|
|
.set_default = true, \
|
|
.defval.i = (OnOffAuto)_defval)
|
|
|
|
#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) \
|
|
DEFINE_PROP(_name, _state, _field, qdev_prop_bool, bool, \
|
|
.set_default = true, \
|
|
.defval.u = (bool)_defval)
|
|
|
|
/**
|
|
* The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value
|
|
* against corresponding bitmask, rejects the value if it violates.
|
|
* The default value is set in instance_init().
|
|
*/
|
|
#define DEFINE_PROP_UINT64_CHECKMASK(_name, _state, _field, _bitmask) \
|
|
DEFINE_PROP(_name, _state, _field, qdev_prop_uint64_checkmask, uint64_t, \
|
|
.bitmask = (_bitmask), \
|
|
.set_default = false)
|
|
|
|
/**
|
|
* DEFINE_PROP_ARRAY:
|
|
* @_name: name of the array
|
|
* @_state: name of the device state structure type
|
|
* @_field: uint32_t field in @_state to hold the array length
|
|
* @_arrayfield: field in @_state (of type '@_arraytype *') which
|
|
* will point to the array
|
|
* @_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. The array is
|
|
* represented as a list in the visitor interface.
|
|
*
|
|
* @_arraytype is required to be movable with memcpy().
|
|
*
|
|
* 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 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(_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) \
|
|
DEFINE_PROP(_name, _state, _field, qdev_prop_link, _ptr_type, \
|
|
.link_type = _type)
|
|
|
|
/**
|
|
* DEFINE_PROP_LINK_ARRAY:
|
|
* @_name: name of the array
|
|
* @_state: name of the device state structure type
|
|
* @_field: uint32_t field in @_state to hold the array length
|
|
* @_arrayfield: field in @_state (of type '@_arraytype *') which
|
|
* will point to the array
|
|
* @_linktype: QOM type name of the link type
|
|
* @_arraytype: C type of the array elements
|
|
*
|
|
* Define device properties for a variable-length array _name of links
|
|
* (i.e. this is the array version of DEFINE_PROP_LINK).
|
|
*
|
|
* The array is represented as a list of QStrings in the visitor interface,
|
|
* where each string is the QOM path of the object to be linked.
|
|
*/
|
|
#define DEFINE_PROP_LINK_ARRAY(_name, _state, _field, _arrayfield, \
|
|
_linktype, _arraytype) \
|
|
DEFINE_PROP(_name, _state, _field, qdev_prop_array, uint32_t, \
|
|
.set_default = true, \
|
|
.defval.u = 0, \
|
|
.arrayinfo = &qdev_prop_link, \
|
|
.arrayfieldsize = sizeof(_arraytype), \
|
|
.arrayoffset = offsetof(_state, _arrayfield), \
|
|
.link_type = _linktype)
|
|
|
|
#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \
|
|
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
|
|
#define DEFINE_PROP_UINT16(_n, _s, _f, _d) \
|
|
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
|
|
#define DEFINE_PROP_UINT32(_n, _s, _f, _d) \
|
|
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
|
|
#define DEFINE_PROP_INT32(_n, _s, _f, _d) \
|
|
DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_int32, int32_t)
|
|
#define DEFINE_PROP_UINT64(_n, _s, _f, _d) \
|
|
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
|
|
#define DEFINE_PROP_INT64(_n, _s, _f, _d) \
|
|
DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_int64, int64_t)
|
|
#define DEFINE_PROP_SIZE(_n, _s, _f, _d) \
|
|
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_size, uint64_t)
|
|
#define DEFINE_PROP_STRING(_n, _s, _f) \
|
|
DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
|
|
#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
|
|
DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto)
|
|
#define DEFINE_PROP_SIZE32(_n, _s, _f, _d) \
|
|
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_size32, uint32_t)
|
|
|
|
/*
|
|
* Set properties between creation and realization.
|
|
*
|
|
* Returns: %true on success, %false on error.
|
|
*/
|
|
bool qdev_prop_set_drive_err(DeviceState *dev, const char *name,
|
|
BlockBackend *value, Error **errp);
|
|
|
|
/*
|
|
* Set properties between creation and realization.
|
|
* @value must be valid. Each property may be set at most once.
|
|
*/
|
|
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
|
|
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
|
|
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
|
|
void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
|
|
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
|
|
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
|
|
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
|
|
void qdev_prop_set_chr(DeviceState *dev, const char *name, Chardev *value);
|
|
void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
|
|
void qdev_prop_set_drive(DeviceState *dev, const char *name,
|
|
BlockBackend *value);
|
|
void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
|
|
const uint8_t *value);
|
|
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
|
|
|
|
/* Takes ownership of @values */
|
|
void qdev_prop_set_array(DeviceState *dev, const char *name, QList *values);
|
|
|
|
/**
|
|
* qlist_append_link: Add a QOM object to a QList of link properties
|
|
* @qlist: list to append to
|
|
* @obj: object to append
|
|
*
|
|
* This is a helper function for constructing a QList to pass to
|
|
* qdev_prop_set_array() when the qdev property array is an array of
|
|
* link properties (i.e. one defined with DEFINE_PROP_LINK_ARRAY).
|
|
*
|
|
* The object is encoded into the list as a QString which is the
|
|
* canonical path of the object; this is the same encoding that
|
|
* object_set_link_property() and object_get_link_property() use.
|
|
*/
|
|
void qlist_append_link(QList *qlist, Object *obj);
|
|
|
|
void *object_field_prop_ptr(Object *obj, const Property *prop);
|
|
|
|
void qdev_prop_register_global(GlobalProperty *prop);
|
|
const GlobalProperty *qdev_find_global_prop(Object *obj,
|
|
const char *name);
|
|
int qdev_prop_check_globals(void);
|
|
void qdev_prop_set_globals(DeviceState *dev);
|
|
void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj,
|
|
const char *name, const char *value);
|
|
|
|
/**
|
|
* qdev_property_add_static:
|
|
* @dev: Device to add the property to.
|
|
* @prop: The qdev property definition.
|
|
*
|
|
* Add a static QOM property to @dev for qdev property @prop.
|
|
* On error, store error in @errp. Static properties access data in a struct.
|
|
* The type of the QOM property is derived from prop->info.
|
|
*/
|
|
void qdev_property_add_static(DeviceState *dev, const Property *prop);
|
|
|
|
/**
|
|
* qdev_alias_all_properties: Create aliases on source for all target properties
|
|
* @target: Device which has properties to be aliased
|
|
* @source: Object to add alias properties to
|
|
*
|
|
* Add alias properties to the @source object for all properties on the @target
|
|
* DeviceState.
|
|
*
|
|
* This is useful when @target is an internal implementation object
|
|
* owned by @source, and you want to expose all the properties of that
|
|
* implementation object as properties on the @source object so that users
|
|
* of @source can set them.
|
|
*/
|
|
void qdev_alias_all_properties(DeviceState *target, Object *source);
|
|
|
|
/**
|
|
* @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);
|
|
|
|
/**
|
|
* qdev_prop_allow_set_link_before_realize:
|
|
*
|
|
* Set the #Error object if an attempt is made to set the link after realize.
|
|
* This function should be used as the check() argument to
|
|
* object_property_add_link().
|
|
*/
|
|
void qdev_prop_allow_set_link_before_realize(const Object *obj,
|
|
const char *name,
|
|
Object *val, Error **errp);
|
|
|
|
#endif
|