Like Xu <like...@linux.intel.com> writes: > The new generic DEFINE_PROP_BITMASK_UINT64 could be used to ensure > that a user-provided property value complies with its bitmask rule > and the default value is recommended to be set in instance_init(). > > Signed-off-by: Like Xu <like...@linux.intel.com> > --- > hw/core/qdev-properties.c | 19 +++++++++++++++++++ > include/hw/qdev-properties.h | 12 ++++++++++++ > include/qapi/qmp/qerror.h | 3 +++ > 3 files changed, 34 insertions(+) > > diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c > index 50f40949f5..3784d3b30d 100644 > --- a/hw/core/qdev-properties.c > +++ b/hw/core/qdev-properties.c > @@ -428,6 +428,25 @@ const PropertyInfo qdev_prop_int64 = { > .set_default_value = qdev_propinfo_set_default_value_int, > }; > > +static void set_bitmask_uint64(Object *obj, Visitor *v, const char *name, > + void *opaque, Error **errp) > +{ > + Property *prop = opaque; > + uint64_t *ptr = object_field_prop_ptr(obj, prop); > + > + visit_type_uint64(v, name, ptr, errp); > + > + if (*ptr & ~prop->bitmask) { > + error_setg(errp, QERR_INVALID_BITMASK_VALUE, name, prop->bitmask); > + } > +} > + > +const PropertyInfo qdev_prop_bitmask_uint64 = { > + .name = "int64", > + .get = get_uint64, > + .set = set_bitmask_uint64, > +}; > + > /* --- string --- */ > > static void release_string(Object *obj, const char *name, void *opaque) > diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h > index 0ef97d60ce..42f0112e14 100644 > --- a/include/hw/qdev-properties.h > +++ b/include/hw/qdev-properties.h > @@ -17,6 +17,7 @@ struct Property { > const PropertyInfo *info; > ptrdiff_t offset; > uint8_t bitnr; > + uint64_t bitmask;
The new member is used just for BITMASK properties. Similar to how .bitnr is used just for BIT properties, .link_type is just for LINK properties, and the .arrayFOO are just for ARRAY properties. I don't like that, to be frank, but I'm not the maintainer. > bool set_default; > union { > int64_t i; > @@ -53,6 +54,7 @@ extern const PropertyInfo qdev_prop_uint16; > extern const PropertyInfo qdev_prop_uint32; > extern const PropertyInfo qdev_prop_int32; > extern const PropertyInfo qdev_prop_uint64; > +extern const PropertyInfo qdev_prop_bitmask_uint64; > extern const PropertyInfo qdev_prop_int64; > extern const PropertyInfo qdev_prop_size; > extern const PropertyInfo qdev_prop_string; > @@ -102,6 +104,16 @@ extern const PropertyInfo qdev_prop_link; > .set_default = true, \ > .defval.u = (bool)_defval) > > +/** > + * The DEFINE_PROP_BITMASK_UINT64 could be used to ensure that > + * a user-provided value complies with certain bitmask rule and > + * the default value is recommended to be set in instance_init(). > + */ > +#define DEFINE_PROP_BITMASK_UINT64(_name, _state, _field, _bitmask) \ > + DEFINE_PROP(_name, _state, _field, qdev_prop_bitmask_uint64, uint64_t, \ > + .bitmask = (_bitmask), \ > + .set_default = false) > + > #define PROP_ARRAY_LEN_PREFIX "len-" > > /** > diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h > index 596fce0c54..aab7902760 100644 > --- a/include/qapi/qmp/qerror.h > +++ b/include/qapi/qmp/qerror.h > @@ -68,4 +68,7 @@ > #define QERR_UNSUPPORTED \ > "this feature or command is not currently supported" > > +#define QERR_INVALID_BITMASK_VALUE \ > + "the requested value for '%s' violates its bitmask '0x%lx'" > + > #endif /* QERROR_H */ Note the comment further up: /* * These macros will go away, please don't use in new code, and do not * add new ones! */ Please put the error message string into set_bitmask_uint64()'s error_setg() call instead.