All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: Eduardo Habkost <ehabkost@redhat.com>, qemu-devel@nongnu.org
Cc: "Daniel P. Berrange" <berrange@redhat.com>,
	"John Snow" <jsnow@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Philippe Mathieu-Daudé" <philmd@redhat.com>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Igor Mammedov" <imammedo@redhat.com>,
	"Stefan Berger" <stefanb@linux.ibm.com>
Subject: Re: [PATCH v2 41/44] qdev: Move base property types to qom/property-types.c
Date: Wed, 4 Nov 2020 17:36:20 +0100	[thread overview]
Message-ID: <cf1eade5-3e3e-ffce-ac0f-b680f6462c47@redhat.com> (raw)
In-Reply-To: <20201104160021.2342108-42-ehabkost@redhat.com>

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 <ehabkost@redhat.com>
> ---
> Changes v1 -> v2:
> * Rebased after changes in previous patches in the series
> ---
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: "Daniel P. Berrangé" <berrange@redhat.com>
> Cc: Eduardo Habkost <ehabkost@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.

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.

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'))
> 



  reply	other threads:[~2020-11-04 16:39 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-04 15:59 [PATCH v2 00/44] Make qdev static property API usable by any QOM type Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 01/44] cs4231: Get rid of empty property array Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 02/44] cpu: Move cpu_common_props to hw/core/cpu.c Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 03/44] qdev: Move property code to qdev-properties.[ch] Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 04/44] qdev: Check dev->realized at set_size() Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 05/44] sparc: Check dev->realized at sparc_set_nwindows() Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 06/44] qdev: Don't use dev->id on set_size32() error message Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 07/44] qdev: Make PropertyInfo.print method get Object* argument Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 08/44] qdev: Make bit_prop_set() " Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 09/44] qdev: Make qdev_get_prop_ptr() get Object* arg Eduardo Habkost
2020-11-04 15:59   ` Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 10/44] qdev: Make qdev_find_global_prop() get Object* argument Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 11/44] qdev: Make check_prop_still_unset() " Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 12/44] qdev: Make error_set_from_qdev_prop_error() " Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 13/44] qdev: Move UUID property to qdev-properties-system.c Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 14/44] qdev: Move softmmu properties to qdev-properties-system.h Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 15/44] qdev: Reuse DEFINE_PROP in all DEFINE_PROP_* macros Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 16/44] sparc: Use DEFINE_PROP for nwindows property Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 17/44] qdev: Get just property name at error_set_from_qdev_prop_error() Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 18/44] qdev: Avoid using prop->name unnecessarily Eduardo Habkost
2020-11-04 17:25   ` Stefan Berger
2020-11-04 15:59 ` [PATCH v2 19/44] qdev: Add name parameter to qdev_class_add_property() Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 20/44] qdev: Add name argument to PropertyInfo.create method Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 21/44] qdev: Wrap getters and setters in separate helpers Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 22/44] qdev: Move dev->realized check to qdev_property_set() Eduardo Habkost
2020-11-04 15:59   ` Eduardo Habkost
2020-11-04 17:28   ` Stefan Berger
2020-11-04 17:28     ` Stefan Berger
2020-11-04 16:00 ` [PATCH v2 23/44] qdev: Make PropertyInfo.create return ObjectProperty* Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 24/44] qdev: Make qdev_class_add_property() more flexible Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 25/44] qdev: Separate generic and device-specific property registration Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 26/44] qdev: Rename Property.name to Property.qdev_prop_name Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 27/44] qdev: Don't set qdev_prop_name for array elements Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 28/44] qdev: Avoid unnecessary DeviceState* variable at set_prop_arraylen() Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 29/44] qdev: Remove ArrayElementProperty.propname field Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 30/44] qdev: Get rid of ArrayElementProperty struct Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 31/44] qdev: Reuse object_property_add_field() when adding array elements Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 32/44] qom: Add allow_set callback to ObjectProperty Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 33/44] qdev: Make qdev_prop_allow_set() a ObjectProperty.allow_set callback Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 34/44] qdev: Make qdev_propinfo_get_uint16() static Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 35/44] qdev: Rename qdev_propinfo_* to field_prop_* Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 36/44] qdev: Rename qdev_get_prop_ptr() to object_field_prop_ptr() Eduardo Habkost
2020-11-04 16:00   ` Eduardo Habkost
2020-11-05 18:49   ` Stefan Berger
2020-11-05 18:49     ` Stefan Berger
2020-11-04 16:00 ` [PATCH v2 37/44] qdev: Move qdev_prop_tpm declaration to tpm_prop.h Eduardo Habkost
2020-11-05 18:50   ` Stefan Berger
2020-11-04 16:00 ` [PATCH v2 38/44] qdev: Rename qdev_prop_* to prop_info_* Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 39/44] qdev: PROP_* macros Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 40/44] qdev: Move core field property code to QOM Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 41/44] qdev: Move base property types to qom/property-types.c Eduardo Habkost
2020-11-04 16:36   ` Paolo Bonzini [this message]
2020-11-04 20:50     ` Eduardo Habkost
2020-11-05  9:36       ` Paolo Bonzini
2020-11-04 16:00 ` [PATCH v2 42/44] qom: Include static property API reference in documentation Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 43/44] tests: Use field properties at check-qom-proplist test case Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 44/44] machine: Register most properties as field properties Eduardo Habkost
2020-11-04 16:36 ` [PATCH v2 00/44] Make qdev static property API usable by any QOM type no-reply
2020-11-06  9:45 ` Kevin Wolf
2020-11-06 15:50   ` Eduardo Habkost
2020-11-06 21:10     ` Eduardo Habkost
2020-11-08 14:05       ` Paolo Bonzini
2020-11-09 11:34         ` Kevin Wolf
2020-11-09 14:15           ` Paolo Bonzini
2020-11-09 15:21             ` Eduardo Habkost
2020-11-09 16:34               ` Paolo Bonzini
2020-11-09 17:16                 ` Eduardo Habkost
2020-11-09 17:33                   ` Paolo Bonzini
2020-11-09 18:55                     ` Eduardo Habkost
2020-11-09 19:27                       ` Paolo Bonzini
2020-11-09 20:28                         ` Eduardo Habkost
2020-11-10 10:38                           ` Kevin Wolf
2020-11-11 18:39                             ` Eduardo Habkost
2020-11-12  8:11                               ` Paolo Bonzini
2020-11-12 14:53                                 ` Eduardo Habkost
2020-11-10 10:58                           ` Paolo Bonzini
2020-11-10 17:03                             ` Eduardo Habkost

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cf1eade5-3e3e-ffce-ac0f-b680f6462c47@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=philmd@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanb@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.