On Wed, Nov 04, 2020 at 05:36:20PM +0100, Paolo Bonzini wrote:
> On 04/11/20 17:00, Eduardo Habkost wrote:
> > Move all property types from qdev-properties.c to
> > qom/property-types.c.
> > 
> > Signed-off-by: Eduardo Habkost <ehabk...@redhat.com>
> > ---
> > Changes v1 -> v2:
> > * Rebased after changes in previous patches in the series
> > ---
> > Cc: Paolo Bonzini <pbonz...@redhat.com>
> > Cc: "Daniel P. Berrangé" <berra...@redhat.com>
> > Cc: Eduardo Habkost <ehabk...@redhat.com>
> > Cc: qemu-devel@nongnu.org
> > ---
> >   include/hw/qdev-properties.h | 179 +-----------
> >   include/qom/property-types.h | 185 ++++++++++++
> >   hw/core/qdev-properties.c    | 537 ----------------------------------
> >   qom/property-types.c         | 545 +++++++++++++++++++++++++++++++++++
> >   qom/meson.build              |   1 +
> >   5 files changed, 732 insertions(+), 715 deletions(-)
> >   create mode 100644 include/qom/property-types.h
> >   create mode 100644 qom/property-types.c
> 
> I would merge property-types.h and field-property.h in a single file.

I like keeping them separate, to force us to define the API used
to create new property types clearly.

What if I create a qom/qom.h header that includes object.h +
field-properties.h + property-types.h to make this easier to use?

> 
> Actually I wouldn't even bother having separate headers, however it's
> certainly valuable to have headers like you have in patch 42:
> 
> Core QOM API Reference
> ----------------------
> 
> ....
> 
> 
> Field Property API Reference
> ----------------------------
> 
> ....
> 
> 
> 
> I'm not sure if it's possible to include rST headers in .h files.

It is possible to include rST headers in doc comments, but the
way the DOC: blocks work in kernel-doc is weird and has subtle
rules and side effects.

> 
> Paolo
> 
> > diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
> > index bee26d0319..939b6dbf4e 100644
> > --- a/include/hw/qdev-properties.h
> > +++ b/include/hw/qdev-properties.h
> > @@ -3,184 +3,7 @@
> >   #include "hw/qdev-core.h"
> >   #include "qom/field-property.h"
> > -
> > -/*** qdev-properties.c ***/
> > -
> > -extern const PropertyInfo prop_info_bit;
> > -extern const PropertyInfo prop_info_bit64;
> > -extern const PropertyInfo prop_info_bool;
> > -extern const PropertyInfo prop_info_enum;
> > -extern const PropertyInfo prop_info_uint8;
> > -extern const PropertyInfo prop_info_uint16;
> > -extern const PropertyInfo prop_info_uint32;
> > -extern const PropertyInfo prop_info_int32;
> > -extern const PropertyInfo prop_info_uint64;
> > -extern const PropertyInfo prop_info_int64;
> > -extern const PropertyInfo prop_info_size;
> > -extern const PropertyInfo prop_info_string;
> > -extern const PropertyInfo prop_info_on_off_auto;
> > -extern const PropertyInfo prop_info_size32;
> > -extern const PropertyInfo prop_info_arraylen;
> > -extern const PropertyInfo prop_info_link;
> > -
> > -#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) {  \
> > -        .qdev_prop_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, prop_info_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, prop_info_bit64, uint64_t, \
> > -                .bitnr    = (_bit),                               \
> > -                .set_default = true,                              \
> > -                .defval.u  = (bool)_defval)
> > -
> > -#define DEFINE_PROP_BOOL(_name, _state, _field, _defval)     \
> > -    DEFINE_PROP(_name, _state, _field, prop_info_bool, bool, \
> > -                .set_default = true,                         \
> > -                .defval.u    = (bool)_defval)
> > -
> > -#define PROP_ARRAY_LEN_PREFIX "len-"
> > -
> > -/**
> > - * 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.  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.
> > - *
> > - * When the array length 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.
> > - * 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, prop_info_arraylen, 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, prop_info_link, _ptr_type,     \
> > -                .link_type  = _type)
> > -
> > -#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint8, uint8_t)
> > -#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint16, uint16_t)
> > -#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint32, uint32_t)
> > -#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
> > -    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int32, int32_t)
> > -#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint64, uint64_t)
> > -#define DEFINE_PROP_INT64(_n, _s, _f, _d)                      \
> > -    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int64, int64_t)
> > -#define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \
> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size, uint64_t)
> > -#define DEFINE_PROP_STRING(_n, _s, _f)             \
> > -    DEFINE_PROP(_n, _s, _f, prop_info_string, char*)
> > -#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
> > -    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_on_off_auto, OnOffAuto)
> > -#define DEFINE_PROP_SIZE32(_n, _s, _f, _d)                       \
> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size32, uint32_t)
> > -
> > -#define DEFINE_PROP_END_OF_LIST()               \
> > -    {}
> > -
> > -/*
> > - * The PROP_* macros can be used as arguments for
> > - * object_class_property_add_field().  They will evaluate to a
> > - * pointer to a static variable.
> > - */
> > -
> > -#define FIELD_PROP(def) \
> > -    ({ static Property _p = def; &p; })
> > -
> > -#define PROP_SIGNED(...) \
> > -    FIELD_PROP(DEFINE_PROP_SIGNED(NULL, __VA_ARGS__))
> > -#define PROP_SIGNED_NODEFAULT(...) \
> > -    FIELD_PROP(DEFINE_PROP_SIGNED_NODEFAULT(NULL, __VA_ARGS__))
> > -#define PROP_BIT(...) \
> > -    FIELD_PROP(DEFINE_PROP_BIT(NULL, __VA_ARGS__))
> > -#define PROP_UNSIGNED(...) \
> > -    FIELD_PROP(DEFINE_PROP_UNSIGNED(NULL, __VA_ARGS__))
> > -#define PROP_UNSIGNED_NODEFAULT(...) \
> > -    FIELD_PROP(DEFINE_PROP_UNSIGNED_NODEFAULT(NULL, __VA_ARGS__))
> > -#define PROP_BIT64(...) \
> > -    FIELD_PROP(DEFINE_PROP_BIT64(NULL, __VA_ARGS__))
> > -#define PROP_BOOL(...) \
> > -    FIELD_PROP(DEFINE_PROP_BOOL(NULL, __VA_ARGS__))
> > -#define PROP_ARRAY(...) \
> > -    FIELD_PROP(DEFINE_PROP_ARRAY(NULL, __VA_ARGS__))
> > -#define PROP_LINK(...) \
> > -    FIELD_PROP(DEFINE_PROP_LINK(NULL, __VA_ARGS__))
> > -#define PROP_UINT8(...) \
> > -    FIELD_PROP(DEFINE_PROP_UINT8(NULL, __VA_ARGS__))
> > -#define PROP_UINT16(...) \
> > -    FIELD_PROP(DEFINE_PROP_UINT16(NULL, __VA_ARGS__))
> > -#define PROP_UINT32(...) \
> > -    FIELD_PROP(DEFINE_PROP_UINT32(NULL, __VA_ARGS__))
> > -#define PROP_INT32(...) \
> > -    FIELD_PROP(DEFINE_PROP_INT32(NULL, __VA_ARGS__))
> > -#define PROP_UINT64(...) \
> > -    FIELD_PROP(DEFINE_PROP_UINT64(NULL, __VA_ARGS__))
> > -#define PROP_INT64(...) \
> > -    FIELD_PROP(DEFINE_PROP_INT64(NULL, __VA_ARGS__))
> > -#define PROP_SIZE(...) \
> > -    FIELD_PROP(DEFINE_PROP_SIZE(NULL, __VA_ARGS__))
> > -#define PROP_STRING(...) \
> > -    FIELD_PROP(DEFINE_PROP_STRING(NULL, __VA_ARGS__))
> > -#define PROP_ON_OFF_AUTO(...) \
> > -    FIELD_PROP(DEFINE_PROP_ON_OFF_AUTO(NULL, __VA_ARGS__))
> > -#define PROP_SIZE32(...) \
> > -    FIELD_PROP(DEFINE_PROP_SIZE32(NULL, __VA_ARGS__))
> > -#define PROP_UUID(...) \
> > -    FIELD_PROP(DEFINE_PROP_UUID(NULL, __VA_ARGS__))
> > -#define PROP_UUID_NODEFAULT(...) \
> > -    FIELD_PROP(DEFINE_PROP_UUID_NODEFAULT(NULL, __VA_ARGS__))
> > -#define PROP_END_OF_LIST(...) \
> > -    FIELD_PROP(DEFINE_PROP_END_OF_LIST(NULL, __VA_ARGS__))
> > +#include "qom/property-types.h"
> >   /*
> >    * Set properties between creation and realization.
> > diff --git a/include/qom/property-types.h b/include/qom/property-types.h
> > new file mode 100644
> > index 0000000000..75f758e835
> > --- /dev/null
> > +++ b/include/qom/property-types.h
> > @@ -0,0 +1,185 @@
> > +/*
> > + * QOM field property types
> > + */
> > +#ifndef QOM_PROPERTY_TYPES_H
> > +#define QOM_PROPERTY_TYPES_H
> > +
> > +#include "qom/field-property.h"
> > +
> > +extern const PropertyInfo prop_info_bit;
> > +extern const PropertyInfo prop_info_bit64;
> > +extern const PropertyInfo prop_info_bool;
> > +extern const PropertyInfo prop_info_enum;
> > +extern const PropertyInfo prop_info_uint8;
> > +extern const PropertyInfo prop_info_uint16;
> > +extern const PropertyInfo prop_info_uint32;
> > +extern const PropertyInfo prop_info_int32;
> > +extern const PropertyInfo prop_info_uint64;
> > +extern const PropertyInfo prop_info_int64;
> > +extern const PropertyInfo prop_info_size;
> > +extern const PropertyInfo prop_info_string;
> > +extern const PropertyInfo prop_info_on_off_auto;
> > +extern const PropertyInfo prop_info_size32;
> > +extern const PropertyInfo prop_info_arraylen;
> > +extern const PropertyInfo prop_info_link;
> > +
> > +#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) {  \
> > +        .qdev_prop_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, prop_info_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, prop_info_bit64, uint64_t, \
> > +                .bitnr    = (_bit),                               \
> > +                .set_default = true,                              \
> > +                .defval.u  = (bool)_defval)
> > +
> > +#define DEFINE_PROP_BOOL(_name, _state, _field, _defval)     \
> > +    DEFINE_PROP(_name, _state, _field, prop_info_bool, bool, \
> > +                .set_default = true,                         \
> > +                .defval.u    = (bool)_defval)
> > +
> > +#define PROP_ARRAY_LEN_PREFIX "len-"
> > +
> > +/**
> > + * 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.  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.
> > + *
> > + * When the array length 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.
> > + * 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, prop_info_arraylen, 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, prop_info_link, _ptr_type,     \
> > +                .link_type  = _type)
> > +
> > +#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint8, uint8_t)
> > +#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint16, uint16_t)
> > +#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint32, uint32_t)
> > +#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
> > +    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int32, int32_t)
> > +#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint64, uint64_t)
> > +#define DEFINE_PROP_INT64(_n, _s, _f, _d)                      \
> > +    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int64, int64_t)
> > +#define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \
> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size, uint64_t)
> > +#define DEFINE_PROP_STRING(_n, _s, _f)             \
> > +    DEFINE_PROP(_n, _s, _f, prop_info_string, char*)
> > +#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
> > +    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_on_off_auto, OnOffAuto)
> > +#define DEFINE_PROP_SIZE32(_n, _s, _f, _d)                       \
> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size32, uint32_t)
> > +
> > +#define DEFINE_PROP_END_OF_LIST()               \
> > +    {}
> > +
> > +/*
> > + * The PROP_* macros can be used as arguments for
> > + * object_class_property_add_field().  They will evaluate to a
> > + * pointer to a static variable.
> > + */
> > +
> > +#define FIELD_PROP(def) \
> > +    ({ static Property _p = def; &p; })
> > +
> > +#define PROP_SIGNED(...) \
> > +    FIELD_PROP(DEFINE_PROP_SIGNED(NULL, __VA_ARGS__))
> > +#define PROP_SIGNED_NODEFAULT(...) \
> > +    FIELD_PROP(DEFINE_PROP_SIGNED_NODEFAULT(NULL, __VA_ARGS__))
> > +#define PROP_BIT(...) \
> > +    FIELD_PROP(DEFINE_PROP_BIT(NULL, __VA_ARGS__))
> > +#define PROP_UNSIGNED(...) \
> > +    FIELD_PROP(DEFINE_PROP_UNSIGNED(NULL, __VA_ARGS__))
> > +#define PROP_UNSIGNED_NODEFAULT(...) \
> > +    FIELD_PROP(DEFINE_PROP_UNSIGNED_NODEFAULT(NULL, __VA_ARGS__))
> > +#define PROP_BIT64(...) \
> > +    FIELD_PROP(DEFINE_PROP_BIT64(NULL, __VA_ARGS__))
> > +#define PROP_BOOL(...) \
> > +    FIELD_PROP(DEFINE_PROP_BOOL(NULL, __VA_ARGS__))
> > +#define PROP_ARRAY(...) \
> > +    FIELD_PROP(DEFINE_PROP_ARRAY(NULL, __VA_ARGS__))
> > +#define PROP_LINK(...) \
> > +    FIELD_PROP(DEFINE_PROP_LINK(NULL, __VA_ARGS__))
> > +#define PROP_UINT8(...) \
> > +    FIELD_PROP(DEFINE_PROP_UINT8(NULL, __VA_ARGS__))
> > +#define PROP_UINT16(...) \
> > +    FIELD_PROP(DEFINE_PROP_UINT16(NULL, __VA_ARGS__))
> > +#define PROP_UINT32(...) \
> > +    FIELD_PROP(DEFINE_PROP_UINT32(NULL, __VA_ARGS__))
> > +#define PROP_INT32(...) \
> > +    FIELD_PROP(DEFINE_PROP_INT32(NULL, __VA_ARGS__))
> > +#define PROP_UINT64(...) \
> > +    FIELD_PROP(DEFINE_PROP_UINT64(NULL, __VA_ARGS__))
> > +#define PROP_INT64(...) \
> > +    FIELD_PROP(DEFINE_PROP_INT64(NULL, __VA_ARGS__))
> > +#define PROP_SIZE(...) \
> > +    FIELD_PROP(DEFINE_PROP_SIZE(NULL, __VA_ARGS__))
> > +#define PROP_STRING(...) \
> > +    FIELD_PROP(DEFINE_PROP_STRING(NULL, __VA_ARGS__))
> > +#define PROP_ON_OFF_AUTO(...) \
> > +    FIELD_PROP(DEFINE_PROP_ON_OFF_AUTO(NULL, __VA_ARGS__))
> > +#define PROP_SIZE32(...) \
> > +    FIELD_PROP(DEFINE_PROP_SIZE32(NULL, __VA_ARGS__))
> > +#define PROP_UUID(...) \
> > +    FIELD_PROP(DEFINE_PROP_UUID(NULL, __VA_ARGS__))
> > +#define PROP_UUID_NODEFAULT(...) \
> > +    FIELD_PROP(DEFINE_PROP_UUID_NODEFAULT(NULL, __VA_ARGS__))
> > +#define PROP_END_OF_LIST(...) \
> > +    FIELD_PROP(DEFINE_PROP_END_OF_LIST(NULL, __VA_ARGS__))
> > +
> > +#endif
> > diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
> > index b75730f15c..5bb4ff5f46 100644
> > --- a/hw/core/qdev-properties.c
> > +++ b/hw/core/qdev-properties.c
> > @@ -50,496 +50,6 @@ void qdev_prop_allow_set_link_before_realize(const 
> > Object *obj,
> >       }
> >   }
> > -void field_prop_get_enum(Object *obj, Visitor *v, const char *name,
> > -                         void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    int *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
> > -}
> > -
> > -void field_prop_set_enum(Object *obj, Visitor *v, const char *name,
> > -                         void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    int *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
> > -}
> > -
> > -void field_prop_set_default_value_enum(ObjectProperty *op,
> > -                                       const Property *prop)
> > -{
> > -    object_property_set_default_str(op,
> > -        qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
> > -}
> > -
> > -const PropertyInfo prop_info_enum = {
> > -    .name  = "enum",
> > -    .get   = field_prop_get_enum,
> > -    .set   = field_prop_set_enum,
> > -    .set_default_value = field_prop_set_default_value_enum,
> > -};
> > -
> > -/* Bit */
> > -
> > -static uint32_t qdev_get_prop_mask(Property *prop)
> > -{
> > -    assert(prop->info == &prop_info_bit);
> > -    return 0x1 << prop->bitnr;
> > -}
> > -
> > -static void bit_prop_set(Object *obj, Property *props, bool val)
> > -{
> > -    uint32_t *p = object_field_prop_ptr(obj, props);
> > -    uint32_t mask = qdev_get_prop_mask(props);
> > -    if (val) {
> > -        *p |= mask;
> > -    } else {
> > -        *p &= ~mask;
> > -    }
> > -}
> > -
> > -static void prop_get_bit(Object *obj, Visitor *v, const char *name,
> > -                         void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    uint32_t *p = object_field_prop_ptr(obj, prop);
> > -    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
> > -
> > -    visit_type_bool(v, name, &value, errp);
> > -}
> > -
> > -static void prop_set_bit(Object *obj, Visitor *v, const char *name,
> > -                         void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    bool value;
> > -
> > -    if (!visit_type_bool(v, name, &value, errp)) {
> > -        return;
> > -    }
> > -    bit_prop_set(obj, prop, value);
> > -}
> > -
> > -static void set_default_value_bool(ObjectProperty *op, const Property 
> > *prop)
> > -{
> > -    object_property_set_default_bool(op, prop->defval.u);
> > -}
> > -
> > -const PropertyInfo prop_info_bit = {
> > -    .name  = "bool",
> > -    .description = "on/off",
> > -    .get   = prop_get_bit,
> > -    .set   = prop_set_bit,
> > -    .set_default_value = set_default_value_bool,
> > -};
> > -
> > -/* Bit64 */
> > -
> > -static uint64_t qdev_get_prop_mask64(Property *prop)
> > -{
> > -    assert(prop->info == &prop_info_bit64);
> > -    return 0x1ull << prop->bitnr;
> > -}
> > -
> > -static void bit64_prop_set(Object *obj, Property *props, bool val)
> > -{
> > -    uint64_t *p = object_field_prop_ptr(obj, props);
> > -    uint64_t mask = qdev_get_prop_mask64(props);
> > -    if (val) {
> > -        *p |= mask;
> > -    } else {
> > -        *p &= ~mask;
> > -    }
> > -}
> > -
> > -static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
> > -                           void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    uint64_t *p = object_field_prop_ptr(obj, prop);
> > -    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
> > -
> > -    visit_type_bool(v, name, &value, errp);
> > -}
> > -
> > -static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
> > -                           void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    bool value;
> > -
> > -    if (!visit_type_bool(v, name, &value, errp)) {
> > -        return;
> > -    }
> > -    bit64_prop_set(obj, prop, value);
> > -}
> > -
> > -const PropertyInfo prop_info_bit64 = {
> > -    .name  = "bool",
> > -    .description = "on/off",
> > -    .get   = prop_get_bit64,
> > -    .set   = prop_set_bit64,
> > -    .set_default_value = set_default_value_bool,
> > -};
> > -
> > -/* --- bool --- */
> > -
> > -static void get_bool(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > -                     Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    bool *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_bool(v, name, ptr, errp);
> > -}
> > -
> > -static void set_bool(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > -                     Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    bool *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_bool(v, name, ptr, errp);
> > -}
> > -
> > -const PropertyInfo prop_info_bool = {
> > -    .name  = "bool",
> > -    .get   = get_bool,
> > -    .set   = set_bool,
> > -    .set_default_value = set_default_value_bool,
> > -};
> > -
> > -/* --- 8bit integer --- */
> > -
> > -static void get_uint8(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > -                      Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    uint8_t *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_uint8(v, name, ptr, errp);
> > -}
> > -
> > -static void set_uint8(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > -                      Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    uint8_t *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_uint8(v, name, ptr, errp);
> > -}
> > -
> > -void field_prop_set_default_value_int(ObjectProperty *op,
> > -                                      const Property *prop)
> > -{
> > -    object_property_set_default_int(op, prop->defval.i);
> > -}
> > -
> > -void field_prop_set_default_value_uint(ObjectProperty *op,
> > -                                       const Property *prop)
> > -{
> > -    object_property_set_default_uint(op, prop->defval.u);
> > -}
> > -
> > -const PropertyInfo prop_info_uint8 = {
> > -    .name  = "uint8",
> > -    .get   = get_uint8,
> > -    .set   = set_uint8,
> > -    .set_default_value = field_prop_set_default_value_uint,
> > -};
> > -
> > -/* --- 16bit integer --- */
> > -
> > -static void get_uint16(Object *obj, Visitor *v, const char *name,
> > -                       void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    uint16_t *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_uint16(v, name, ptr, errp);
> > -}
> > -
> > -static void set_uint16(Object *obj, Visitor *v, const char *name,
> > -                       void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    uint16_t *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_uint16(v, name, ptr, errp);
> > -}
> > -
> > -const PropertyInfo prop_info_uint16 = {
> > -    .name  = "uint16",
> > -    .get   = get_uint16,
> > -    .set   = set_uint16,
> > -    .set_default_value = field_prop_set_default_value_uint,
> > -};
> > -
> > -/* --- 32bit integer --- */
> > -
> > -static void get_uint32(Object *obj, Visitor *v, const char *name,
> > -                       void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    uint32_t *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_uint32(v, name, ptr, errp);
> > -}
> > -
> > -static void set_uint32(Object *obj, Visitor *v, const char *name,
> > -                       void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    uint32_t *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_uint32(v, name, ptr, errp);
> > -}
> > -
> > -void field_prop_get_int32(Object *obj, Visitor *v, const char *name,
> > -                          void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    int32_t *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_int32(v, name, ptr, errp);
> > -}
> > -
> > -static void set_int32(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > -                      Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    int32_t *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_int32(v, name, ptr, errp);
> > -}
> > -
> > -const PropertyInfo prop_info_uint32 = {
> > -    .name  = "uint32",
> > -    .get   = get_uint32,
> > -    .set   = set_uint32,
> > -    .set_default_value = field_prop_set_default_value_uint,
> > -};
> > -
> > -const PropertyInfo prop_info_int32 = {
> > -    .name  = "int32",
> > -    .get   = field_prop_get_int32,
> > -    .set   = set_int32,
> > -    .set_default_value = field_prop_set_default_value_int,
> > -};
> > -
> > -/* --- 64bit integer --- */
> > -
> > -static void get_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);
> > -}
> > -
> > -static void set_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);
> > -}
> > -
> > -static void get_int64(Object *obj, Visitor *v, const char *name,
> > -                      void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    int64_t *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_int64(v, name, ptr, errp);
> > -}
> > -
> > -static void set_int64(Object *obj, Visitor *v, const char *name,
> > -                      void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    int64_t *ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    visit_type_int64(v, name, ptr, errp);
> > -}
> > -
> > -const PropertyInfo prop_info_uint64 = {
> > -    .name  = "uint64",
> > -    .get   = get_uint64,
> > -    .set   = set_uint64,
> > -    .set_default_value = field_prop_set_default_value_uint,
> > -};
> > -
> > -const PropertyInfo prop_info_int64 = {
> > -    .name  = "int64",
> > -    .get   = get_int64,
> > -    .set   = set_int64,
> > -    .set_default_value = field_prop_set_default_value_int,
> > -};
> > -
> > -/* --- string --- */
> > -
> > -static void release_string(Object *obj, const char *name, void *opaque)
> > -{
> > -    Property *prop = opaque;
> > -    g_free(*(char **)object_field_prop_ptr(obj, prop));
> > -}
> > -
> > -static void get_string(Object *obj, Visitor *v, const char *name,
> > -                       void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    char **ptr = object_field_prop_ptr(obj, prop);
> > -
> > -    if (!*ptr) {
> > -        char *str = (char *)"";
> > -        visit_type_str(v, name, &str, errp);
> > -    } else {
> > -        visit_type_str(v, name, ptr, errp);
> > -    }
> > -}
> > -
> > -static void set_string(Object *obj, Visitor *v, const char *name,
> > -                       void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    char **ptr = object_field_prop_ptr(obj, prop);
> > -    char *str;
> > -
> > -    if (!visit_type_str(v, name, &str, errp)) {
> > -        return;
> > -    }
> > -    g_free(*ptr);
> > -    *ptr = str;
> > -}
> > -
> > -const PropertyInfo prop_info_string = {
> > -    .name  = "str",
> > -    .release = release_string,
> > -    .get   = get_string,
> > -    .set   = set_string,
> > -};
> > -
> > -/* --- on/off/auto --- */
> > -
> > -const PropertyInfo prop_info_on_off_auto = {
> > -    .name = "OnOffAuto",
> > -    .description = "on/off/auto",
> > -    .enum_table = &OnOffAuto_lookup,
> > -    .get = field_prop_get_enum,
> > -    .set = field_prop_set_enum,
> > -    .set_default_value = field_prop_set_default_value_enum,
> > -};
> > -
> > -/* --- 32bit unsigned int 'size' type --- */
> > -
> > -void field_prop_get_size32(Object *obj, Visitor *v, const char *name,
> > -                           void *opaque, Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    uint32_t *ptr = object_field_prop_ptr(obj, prop);
> > -    uint64_t value = *ptr;
> > -
> > -    visit_type_size(v, name, &value, errp);
> > -}
> > -
> > -static void set_size32(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > -                       Error **errp)
> > -{
> > -    Property *prop = opaque;
> > -    uint32_t *ptr = object_field_prop_ptr(obj, prop);
> > -    uint64_t value;
> > -
> > -    if (!visit_type_size(v, name, &value, errp)) {
> > -        return;
> > -    }
> > -
> > -    if (value > UINT32_MAX) {
> > -        error_setg(errp,
> > -                   "Property %s.%s doesn't take value %" PRIu64
> > -                   " (maximum: %u)",
> > -                   object_get_typename(obj), name, value, UINT32_MAX);
> > -        return;
> > -    }
> > -
> > -    *ptr = value;
> > -}
> > -
> > -const PropertyInfo prop_info_size32 = {
> > -    .name  = "size",
> > -    .get = field_prop_get_size32,
> > -    .set = set_size32,
> > -    .set_default_value = field_prop_set_default_value_uint,
> > -};
> > -
> > -/* --- support for array properties --- */
> > -
> > -static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
> > -                              void *opaque, Error **errp)
> > -{
> > -    /* Setter for the property which defines the length of a
> > -     * variable-sized property array. As well as actually setting the
> > -     * array-length field in the device struct, we have to create the
> > -     * array itself and dynamically add the corresponding properties.
> > -     */
> > -    Property *prop = opaque;
> > -    ObjectProperty *op = object_property_find_err(obj, name, &error_abort);
> > -    uint32_t *alenptr = object_field_prop_ptr(obj, prop);
> > -    void **arrayptr = (void *)obj + prop->arrayoffset;
> > -    void *eltptr;
> > -    const char *arrayname;
> > -    int i;
> > -
> > -    if (*alenptr) {
> > -        error_setg(errp, "array size property %s may not be set more than 
> > once",
> > -                   name);
> > -        return;
> > -    }
> > -    if (!visit_type_uint32(v, name, alenptr, errp)) {
> > -        return;
> > -    }
> > -    if (!*alenptr) {
> > -        return;
> > -    }
> > -
> > -    /* DEFINE_PROP_ARRAY guarantees that name should start with this 
> > prefix;
> > -     * strip it off so we can get the name of the array itself.
> > -     */
> > -    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
> > -                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
> > -    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
> > -
> > -    /* Note that it is the responsibility of the individual device's deinit
> > -     * to free the array proper.
> > -     */
> > -    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
> > -    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
> > -        g_autofree char *propname = g_strdup_printf("%s[%d]", arrayname, 
> > i);
> > -        Property *arrayprop = g_new0(Property, 1);
> > -        arrayprop->info = prop->arrayinfo;
> > -        /* This ugly piece of pointer arithmetic sets up the offset so
> > -         * that when the underlying get/set hooks call qdev_get_prop_ptr
> > -         * they get the right answer despite the array element not actually
> > -         * being inside the device struct.
> > -         */
> > -        arrayprop->offset = eltptr - (void *)obj;
> > -        assert(object_field_prop_ptr(obj, arrayprop) == eltptr);
> > -        object_property_add_field(obj, propname, arrayprop, op->allow_set);
> > -    }
> > -}
> > -
> > -const PropertyInfo prop_info_arraylen = {
> > -    .name = "uint32",
> > -    .get = get_uint32,
> > -    .set = set_prop_arraylen,
> > -    .set_default_value = field_prop_set_default_value_uint,
> > -};
> > -
> >   /* --- public helpers --- */
> >   static Property *qdev_prop_walk(Property *props, const char *name)
> > @@ -712,53 +222,6 @@ void qdev_prop_set_globals(DeviceState *dev)
> >                                 dev->hotplugged ? NULL : &error_fatal);
> >   }
> > -/* --- 64bit unsigned int 'size' type --- */
> > -
> > -static void get_size(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_size(v, name, ptr, errp);
> > -}
> > -
> > -static void set_size(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_size(v, name, ptr, errp);
> > -}
> > -
> > -const PropertyInfo prop_info_size = {
> > -    .name  = "size",
> > -    .get = get_size,
> > -    .set = set_size,
> > -    .set_default_value = field_prop_set_default_value_uint,
> > -};
> > -
> > -/* --- object link property --- */
> > -
> > -static ObjectProperty *create_link_property(ObjectClass *oc, const char 
> > *name,
> > -                                            Property *prop)
> > -{
> > -    /*
> > -     * NOTE: object_property_allow_set_link is unconditional, but
> > -     *       ObjectProperty.allow_set may be set for the property too.
> > -     */
> > -    return object_class_property_add_link(oc, name, prop->link_type,
> > -                                          prop->offset,
> > -                                          object_property_allow_set_link,
> > -                                          OBJ_PROP_LINK_STRONG);
> > -}
> > -
> > -const PropertyInfo prop_info_link = {
> > -    .name = "link",
> > -    .create = create_link_property,
> > -};
> > -
> >   void qdev_property_add_static(DeviceState *dev, Property *prop)
> >   {
> >       object_property_add_field(OBJECT(dev), prop->qdev_prop_name, prop,
> > diff --git a/qom/property-types.c b/qom/property-types.c
> > new file mode 100644
> > index 0000000000..f566c05ec2
> > --- /dev/null
> > +++ b/qom/property-types.c
> > @@ -0,0 +1,545 @@
> > +#include "qemu/osdep.h"
> > +#include "qom/field-property.h"
> > +#include "qom/property-types.h"
> > +#include "qom/field-property-internal.h"
> > +#include "qapi/qapi-types-common.h"
> > +#include "qapi/visitor.h"
> > +#include "qapi/error.h"
> > +#include "qemu/uuid.h"
> > +
> > +void field_prop_get_enum(Object *obj, Visitor *v, const char *name,
> > +                         void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    int *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
> > +}
> > +
> > +void field_prop_set_enum(Object *obj, Visitor *v, const char *name,
> > +                         void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    int *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
> > +}
> > +
> > +void field_prop_set_default_value_enum(ObjectProperty *op,
> > +                                       const Property *prop)
> > +{
> > +    object_property_set_default_str(op,
> > +        qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
> > +}
> > +
> > +const PropertyInfo prop_info_enum = {
> > +    .name  = "enum",
> > +    .get   = field_prop_get_enum,
> > +    .set   = field_prop_set_enum,
> > +    .set_default_value = field_prop_set_default_value_enum,
> > +};
> > +
> > +/* Bit */
> > +
> > +static uint32_t qdev_get_prop_mask(Property *prop)
> > +{
> > +    assert(prop->info == &prop_info_bit);
> > +    return 0x1 << prop->bitnr;
> > +}
> > +
> > +static void bit_prop_set(Object *obj, Property *props, bool val)
> > +{
> > +    uint32_t *p = object_field_prop_ptr(obj, props);
> > +    uint32_t mask = qdev_get_prop_mask(props);
> > +    if (val) {
> > +        *p |= mask;
> > +    } else {
> > +        *p &= ~mask;
> > +    }
> > +}
> > +
> > +static void prop_get_bit(Object *obj, Visitor *v, const char *name,
> > +                         void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    uint32_t *p = object_field_prop_ptr(obj, prop);
> > +    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
> > +
> > +    visit_type_bool(v, name, &value, errp);
> > +}
> > +
> > +static void prop_set_bit(Object *obj, Visitor *v, const char *name,
> > +                         void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    bool value;
> > +
> > +    if (!visit_type_bool(v, name, &value, errp)) {
> > +        return;
> > +    }
> > +    bit_prop_set(obj, prop, value);
> > +}
> > +
> > +static void set_default_value_bool(ObjectProperty *op, const Property 
> > *prop)
> > +{
> > +    object_property_set_default_bool(op, prop->defval.u);
> > +}
> > +
> > +const PropertyInfo prop_info_bit = {
> > +    .name  = "bool",
> > +    .description = "on/off",
> > +    .get   = prop_get_bit,
> > +    .set   = prop_set_bit,
> > +    .set_default_value = set_default_value_bool,
> > +};
> > +
> > +/* Bit64 */
> > +
> > +static uint64_t qdev_get_prop_mask64(Property *prop)
> > +{
> > +    assert(prop->info == &prop_info_bit64);
> > +    return 0x1ull << prop->bitnr;
> > +}
> > +
> > +static void bit64_prop_set(Object *obj, Property *props, bool val)
> > +{
> > +    uint64_t *p = object_field_prop_ptr(obj, props);
> > +    uint64_t mask = qdev_get_prop_mask64(props);
> > +    if (val) {
> > +        *p |= mask;
> > +    } else {
> > +        *p &= ~mask;
> > +    }
> > +}
> > +
> > +static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
> > +                           void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    uint64_t *p = object_field_prop_ptr(obj, prop);
> > +    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
> > +
> > +    visit_type_bool(v, name, &value, errp);
> > +}
> > +
> > +static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
> > +                           void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    bool value;
> > +
> > +    if (!visit_type_bool(v, name, &value, errp)) {
> > +        return;
> > +    }
> > +    bit64_prop_set(obj, prop, value);
> > +}
> > +
> > +const PropertyInfo prop_info_bit64 = {
> > +    .name  = "bool",
> > +    .description = "on/off",
> > +    .get   = prop_get_bit64,
> > +    .set   = prop_set_bit64,
> > +    .set_default_value = set_default_value_bool,
> > +};
> > +
> > +/* --- bool --- */
> > +
> > +static void get_bool(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > +                     Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    bool *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_bool(v, name, ptr, errp);
> > +}
> > +
> > +static void set_bool(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > +                     Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    bool *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_bool(v, name, ptr, errp);
> > +}
> > +
> > +const PropertyInfo prop_info_bool = {
> > +    .name  = "bool",
> > +    .get   = get_bool,
> > +    .set   = set_bool,
> > +    .set_default_value = set_default_value_bool,
> > +};
> > +
> > +/* --- 8bit integer --- */
> > +
> > +static void get_uint8(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > +                      Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    uint8_t *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_uint8(v, name, ptr, errp);
> > +}
> > +
> > +static void set_uint8(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > +                      Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    uint8_t *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_uint8(v, name, ptr, errp);
> > +}
> > +
> > +void field_prop_set_default_value_int(ObjectProperty *op,
> > +                                      const Property *prop)
> > +{
> > +    object_property_set_default_int(op, prop->defval.i);
> > +}
> > +
> > +void field_prop_set_default_value_uint(ObjectProperty *op,
> > +                                       const Property *prop)
> > +{
> > +    object_property_set_default_uint(op, prop->defval.u);
> > +}
> > +
> > +const PropertyInfo prop_info_uint8 = {
> > +    .name  = "uint8",
> > +    .get   = get_uint8,
> > +    .set   = set_uint8,
> > +    .set_default_value = field_prop_set_default_value_uint,
> > +};
> > +
> > +/* --- 16bit integer --- */
> > +
> > +static void get_uint16(Object *obj, Visitor *v, const char *name,
> > +                       void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    uint16_t *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_uint16(v, name, ptr, errp);
> > +}
> > +
> > +static void set_uint16(Object *obj, Visitor *v, const char *name,
> > +                       void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    uint16_t *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_uint16(v, name, ptr, errp);
> > +}
> > +
> > +const PropertyInfo prop_info_uint16 = {
> > +    .name  = "uint16",
> > +    .get   = get_uint16,
> > +    .set   = set_uint16,
> > +    .set_default_value = field_prop_set_default_value_uint,
> > +};
> > +
> > +/* --- 32bit integer --- */
> > +
> > +static void get_uint32(Object *obj, Visitor *v, const char *name,
> > +                       void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    uint32_t *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_uint32(v, name, ptr, errp);
> > +}
> > +
> > +static void set_uint32(Object *obj, Visitor *v, const char *name,
> > +                       void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    uint32_t *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_uint32(v, name, ptr, errp);
> > +}
> > +
> > +void field_prop_get_int32(Object *obj, Visitor *v, const char *name,
> > +                          void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    int32_t *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_int32(v, name, ptr, errp);
> > +}
> > +
> > +static void set_int32(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > +                      Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    int32_t *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_int32(v, name, ptr, errp);
> > +}
> > +
> > +const PropertyInfo prop_info_uint32 = {
> > +    .name  = "uint32",
> > +    .get   = get_uint32,
> > +    .set   = set_uint32,
> > +    .set_default_value = field_prop_set_default_value_uint,
> > +};
> > +
> > +const PropertyInfo prop_info_int32 = {
> > +    .name  = "int32",
> > +    .get   = field_prop_get_int32,
> > +    .set   = set_int32,
> > +    .set_default_value = field_prop_set_default_value_int,
> > +};
> > +
> > +/* --- 64bit integer --- */
> > +
> > +static void get_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);
> > +}
> > +
> > +static void set_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);
> > +}
> > +
> > +static void get_int64(Object *obj, Visitor *v, const char *name,
> > +                      void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    int64_t *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_int64(v, name, ptr, errp);
> > +}
> > +
> > +static void set_int64(Object *obj, Visitor *v, const char *name,
> > +                      void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    int64_t *ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    visit_type_int64(v, name, ptr, errp);
> > +}
> > +
> > +const PropertyInfo prop_info_uint64 = {
> > +    .name  = "uint64",
> > +    .get   = get_uint64,
> > +    .set   = set_uint64,
> > +    .set_default_value = field_prop_set_default_value_uint,
> > +};
> > +
> > +const PropertyInfo prop_info_int64 = {
> > +    .name  = "int64",
> > +    .get   = get_int64,
> > +    .set   = set_int64,
> > +    .set_default_value = field_prop_set_default_value_int,
> > +};
> > +
> > +/* --- string --- */
> > +
> > +static void release_string(Object *obj, const char *name, void *opaque)
> > +{
> > +    Property *prop = opaque;
> > +    g_free(*(char **)object_field_prop_ptr(obj, prop));
> > +}
> > +
> > +static void get_string(Object *obj, Visitor *v, const char *name,
> > +                       void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    char **ptr = object_field_prop_ptr(obj, prop);
> > +
> > +    if (!*ptr) {
> > +        char *str = (char *)"";
> > +        visit_type_str(v, name, &str, errp);
> > +    } else {
> > +        visit_type_str(v, name, ptr, errp);
> > +    }
> > +}
> > +
> > +static void set_string(Object *obj, Visitor *v, const char *name,
> > +                       void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    char **ptr = object_field_prop_ptr(obj, prop);
> > +    char *str;
> > +
> > +    if (!visit_type_str(v, name, &str, errp)) {
> > +        return;
> > +    }
> > +    g_free(*ptr);
> > +    *ptr = str;
> > +}
> > +
> > +const PropertyInfo prop_info_string = {
> > +    .name  = "str",
> > +    .release = release_string,
> > +    .get   = get_string,
> > +    .set   = set_string,
> > +};
> > +
> > +/* --- on/off/auto --- */
> > +
> > +const PropertyInfo prop_info_on_off_auto = {
> > +    .name = "OnOffAuto",
> > +    .description = "on/off/auto",
> > +    .enum_table = &OnOffAuto_lookup,
> > +    .get = field_prop_get_enum,
> > +    .set = field_prop_set_enum,
> > +    .set_default_value = field_prop_set_default_value_enum,
> > +};
> > +
> > +/* --- 32bit unsigned int 'size' type --- */
> > +
> > +void field_prop_get_size32(Object *obj, Visitor *v, const char *name,
> > +                           void *opaque, Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    uint32_t *ptr = object_field_prop_ptr(obj, prop);
> > +    uint64_t value = *ptr;
> > +
> > +    visit_type_size(v, name, &value, errp);
> > +}
> > +
> > +static void set_size32(Object *obj, Visitor *v, const char *name, void 
> > *opaque,
> > +                       Error **errp)
> > +{
> > +    Property *prop = opaque;
> > +    uint32_t *ptr = object_field_prop_ptr(obj, prop);
> > +    uint64_t value;
> > +
> > +    if (!visit_type_size(v, name, &value, errp)) {
> > +        return;
> > +    }
> > +
> > +    if (value > UINT32_MAX) {
> > +        error_setg(errp,
> > +                   "Property %s.%s doesn't take value %" PRIu64
> > +                   " (maximum: %u)",
> > +                   object_get_typename(obj), name, value, UINT32_MAX);
> > +        return;
> > +    }
> > +
> > +    *ptr = value;
> > +}
> > +
> > +const PropertyInfo prop_info_size32 = {
> > +    .name  = "size",
> > +    .get = field_prop_get_size32,
> > +    .set = set_size32,
> > +    .set_default_value = field_prop_set_default_value_uint,
> > +};
> > +
> > +/* --- support for array properties --- */
> > +
> > +static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
> > +                              void *opaque, Error **errp)
> > +{
> > +    /* Setter for the property which defines the length of a
> > +     * variable-sized property array. As well as actually setting the
> > +     * array-length field in the device struct, we have to create the
> > +     * array itself and dynamically add the corresponding properties.
> > +     */
> > +    Property *prop = opaque;
> > +    ObjectProperty *op = object_property_find_err(obj, name, &error_abort);
> > +    uint32_t *alenptr = object_field_prop_ptr(obj, prop);
> > +    void **arrayptr = (void *)obj + prop->arrayoffset;
> > +    void *eltptr;
> > +    const char *arrayname;
> > +    int i;
> > +
> > +    if (*alenptr) {
> > +        error_setg(errp, "array size property %s may not be set more than 
> > once",
> > +                   name);
> > +        return;
> > +    }
> > +    if (!visit_type_uint32(v, name, alenptr, errp)) {
> > +        return;
> > +    }
> > +    if (!*alenptr) {
> > +        return;
> > +    }
> > +
> > +    /* DEFINE_PROP_ARRAY guarantees that name should start with this 
> > prefix;
> > +     * strip it off so we can get the name of the array itself.
> > +     */
> > +    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
> > +                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
> > +    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
> > +
> > +    /* Note that it is the responsibility of the individual device's deinit
> > +     * to free the array proper.
> > +     */
> > +    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
> > +    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
> > +        g_autofree char *propname = g_strdup_printf("%s[%d]", arrayname, 
> > i);
> > +        Property *arrayprop = g_new0(Property, 1);
> > +        arrayprop->info = prop->arrayinfo;
> > +        /* This ugly piece of pointer arithmetic sets up the offset so
> > +         * that when the underlying get/set hooks call qdev_get_prop_ptr
> > +         * they get the right answer despite the array element not actually
> > +         * being inside the device struct.
> > +         */
> > +        arrayprop->offset = eltptr - (void *)obj;
> > +        assert(object_field_prop_ptr(obj, arrayprop) == eltptr);
> > +        object_property_add_field(obj, propname, arrayprop, op->allow_set);
> > +    }
> > +}
> > +
> > +const PropertyInfo prop_info_arraylen = {
> > +    .name = "uint32",
> > +    .get = get_uint32,
> > +    .set = set_prop_arraylen,
> > +    .set_default_value = field_prop_set_default_value_uint,
> > +};
> > +
> > +/* --- 64bit unsigned int 'size' type --- */
> > +
> > +static void get_size(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_size(v, name, ptr, errp);
> > +}
> > +
> > +static void set_size(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_size(v, name, ptr, errp);
> > +}
> > +
> > +const PropertyInfo prop_info_size = {
> > +    .name  = "size",
> > +    .get = get_size,
> > +    .set = set_size,
> > +    .set_default_value = field_prop_set_default_value_uint,
> > +};
> > +
> > +/* --- object link property --- */
> > +
> > +static ObjectProperty *create_link_property(ObjectClass *oc, const char 
> > *name,
> > +                                            Property *prop)
> > +{
> > +    /*
> > +     * NOTE: object_property_allow_set_link is unconditional, but
> > +     *       ObjectProperty.allow_set may be set for the property too.
> > +     */
> > +    return object_class_property_add_link(oc, name, prop->link_type,
> > +                                          prop->offset,
> > +                                          object_property_allow_set_link,
> > +                                          OBJ_PROP_LINK_STRONG);
> > +}
> > +
> > +const PropertyInfo prop_info_link = {
> > +    .name = "link",
> > +    .create = create_link_property,
> > +};
> > diff --git a/qom/meson.build b/qom/meson.build
> > index e83794454d..7fdfd6fe7b 100644
> > --- a/qom/meson.build
> > +++ b/qom/meson.build
> > @@ -5,6 +5,7 @@ qom_ss.add(files(
> >     'object_interfaces.c',
> >     'qom-qobject.c',
> >     'field-property.c',
> > +  'property-types.c',
> >   ))
> >   qmp_ss.add(files('qom-qmp-cmds.c'))
> > 
> 

-- 
Eduardo


Reply via email to