From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:41445) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ScnyG-0003Yk-97 for qemu-devel@nongnu.org; Thu, 07 Jun 2012 21:26:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ScnyB-0002OP-Li for qemu-devel@nongnu.org; Thu, 07 Jun 2012 21:26:35 -0400 Received: from mail-yx0-f173.google.com ([209.85.213.173]:38042) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ScnyB-0002O6-Ek for qemu-devel@nongnu.org; Thu, 07 Jun 2012 21:26:31 -0400 Received: by yenm4 with SMTP id m4so1029539yen.4 for ; Thu, 07 Jun 2012 18:26:30 -0700 (PDT) Message-ID: <4FD154BE.1040407@codemonkey.ws> Date: Fri, 08 Jun 2012 09:26:22 +0800 From: Anthony Liguori MIME-Version: 1.0 References: <1339097465-22977-1-git-send-email-afaerber@suse.de> <1339097465-22977-5-git-send-email-afaerber@suse.de> In-Reply-To: <1339097465-22977-5-git-send-email-afaerber@suse.de> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Subject: Re: [Qemu-devel] [PATCH qom-next 4/7] qdev: Move bulk of qdev-properties.c to qom/object-properties.c List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: =?UTF-8?B?QW5kcmVhcyBGw6RyYmVy?= Cc: pbonzini@redhat.com, qemu-devel@nongnu.org On 06/08/2012 03:31 AM, Andreas Färber wrote: > From: Paolo Bonzini > > Signed-off-by: Paolo Bonzini > [AF: Move to new qom/object-properties.c, update documentation.] > Signed-off-by: Andreas Färber Reviewed-by: Anthony Liguori Regards, Anthony Liguori > --- > hw/qdev-properties.c | 487 +++++------------------------------------------ > hw/qdev.c | 47 +----- > hw/qdev.h | 87 --------- > include/qemu/object.h | 98 ++++++++++ > qom/Makefile | 2 +- > qom/object-properties.c | 461 ++++++++++++++++++++++++++++++++++++++++++++ > 6 files changed, 607 insertions(+), 575 deletions(-) > create mode 100644 qom/object-properties.c > > diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c > index 910e07f..5187604 100644 > --- a/hw/qdev-properties.c > +++ b/hw/qdev-properties.c > @@ -3,392 +3,27 @@ > #include "qerror.h" > #include "blockdev.h" > > -void *object_get_prop_ptr(Object *obj, Property *prop) > -{ > - void *ptr = obj; > - ptr += prop->offset; > - return ptr; > -} > - > -static uint32_t get_prop_mask(Property *prop) > -{ > - assert(prop->info ==&qdev_prop_bit); > - return 0x1<< prop->bitnr; > -} > - > -static void bit_prop_set(Object *obj, Property *props, bool val) > -{ > - uint32_t *p = object_get_prop_ptr(obj, props); > - uint32_t mask = get_prop_mask(props); > - if (val) > - *p |= mask; > - else > - *p&= ~mask; > -} > - > -/* Bit */ > - > -static int print_bit(Object *obj, Property *prop, char *dest, size_t len) > -{ > - uint32_t *p = object_get_prop_ptr(obj, prop); > - return snprintf(dest, len, (*p& get_prop_mask(prop)) ? "on" : "off"); > -} > - > -static void get_bit(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - uint32_t *p = object_get_prop_ptr(obj, prop); > - bool value = (*p& get_prop_mask(prop)) != 0; > - > - visit_type_bool(v,&value, name, errp); > -} > - > -static void set_bit(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - Error *local_err = NULL; > - bool value; > - > - if (object_is_realized(obj)) { > - error_set(errp, QERR_PERMISSION_DENIED); > - return; > - } > - > - visit_type_bool(v,&value, name,&local_err); > - if (local_err) { > - error_propagate(errp, local_err); > - return; > - } > - bit_prop_set(obj, prop, value); > -} > - > -PropertyInfo qdev_prop_bit = { > - .name = "boolean", > - .legacy_name = "on/off", > - .print = print_bit, > - .get = get_bit, > - .set = set_bit, > -}; > - > -/* --- 8bit integer --- */ > - > -static void get_uint8(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - uint8_t *ptr = object_get_prop_ptr(obj, prop); > - > - visit_type_uint8(v, ptr, name, errp); > -} > - > -static void set_uint8(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - uint8_t *ptr = object_get_prop_ptr(obj, prop); > - > - if (object_is_realized(obj)) { > - error_set(errp, QERR_PERMISSION_DENIED); > - return; > - } > - > - visit_type_uint8(v, ptr, name, errp); > -} > - > -PropertyInfo qdev_prop_uint8 = { > - .name = "uint8", > - .get = get_uint8, > - .set = set_uint8, > -}; > - > -/* --- 8bit hex value --- */ > - > -static int parse_hex8(Object *obj, Property *prop, const char *str) > -{ > - uint8_t *ptr = object_get_prop_ptr(obj, prop); > - char *end; > - > - if (str[0] != '0' || str[1] != 'x') { > - return -EINVAL; > - } > - > - *ptr = strtoul(str,&end, 16); > - if ((*end != '\0') || (end == str)) { > - return -EINVAL; > - } > - > - return 0; > -} > - > -static int print_hex8(Object *obj, Property *prop, char *dest, size_t len) > -{ > - uint8_t *ptr = object_get_prop_ptr(obj, prop); > - return snprintf(dest, len, "0x%" PRIx8, *ptr); > -} > - > -PropertyInfo qdev_prop_hex8 = { > - .name = "uint8", > - .legacy_name = "hex8", > - .parse = parse_hex8, > - .print = print_hex8, > - .get = get_uint8, > - .set = set_uint8, > -}; > - > -/* --- 16bit integer --- */ > - > -static void get_uint16(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - uint16_t *ptr = object_get_prop_ptr(obj, prop); > - > - visit_type_uint16(v, ptr, name, errp); > -} > - > -static void set_uint16(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - uint16_t *ptr = object_get_prop_ptr(obj, prop); > - > - if (object_is_realized(obj)) { > - error_set(errp, QERR_PERMISSION_DENIED); > - return; > - } > - > - visit_type_uint16(v, ptr, name, errp); > -} > - > -PropertyInfo qdev_prop_uint16 = { > - .name = "uint16", > - .get = get_uint16, > - .set = set_uint16, > -}; > - > -/* --- 32bit integer --- */ > - > -static void get_uint32(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - uint32_t *ptr = object_get_prop_ptr(obj, prop); > - > - visit_type_uint32(v, ptr, name, errp); > -} > - > -static void set_uint32(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - uint32_t *ptr = object_get_prop_ptr(obj, prop); > - > - if (object_is_realized(obj)) { > - error_set(errp, QERR_PERMISSION_DENIED); > - return; > - } > - > - visit_type_uint32(v, ptr, name, errp); > -} > - > -static void get_int32(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - int32_t *ptr = object_get_prop_ptr(obj, prop); > - > - visit_type_int32(v, ptr, name, errp); > -} > - > -static void set_int32(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - int32_t *ptr = object_get_prop_ptr(obj, prop); > - > - if (object_is_realized(obj)) { > - error_set(errp, QERR_PERMISSION_DENIED); > - return; > - } > - > - visit_type_int32(v, ptr, name, errp); > -} > - > -PropertyInfo qdev_prop_uint32 = { > - .name = "uint32", > - .get = get_uint32, > - .set = set_uint32, > -}; > - > -PropertyInfo qdev_prop_int32 = { > - .name = "int32", > - .get = get_int32, > - .set = set_int32, > -}; > - > -/* --- 32bit hex value --- */ > - > -static int parse_hex32(Object *obj, Property *prop, const char *str) > -{ > - uint32_t *ptr = object_get_prop_ptr(obj, prop); > - char *end; > - > - if (str[0] != '0' || str[1] != 'x') { > - return -EINVAL; > - } > - > - *ptr = strtoul(str,&end, 16); > - if ((*end != '\0') || (end == str)) { > - return -EINVAL; > - } > - > - return 0; > -} > - > -static int print_hex32(Object *obj, Property *prop, char *dest, size_t len) > -{ > - uint32_t *ptr = object_get_prop_ptr(obj, prop); > - return snprintf(dest, len, "0x%" PRIx32, *ptr); > -} > - > -PropertyInfo qdev_prop_hex32 = { > - .name = "uint32", > - .legacy_name = "hex32", > - .parse = parse_hex32, > - .print = print_hex32, > - .get = get_uint32, > - .set = set_uint32, > -}; > - > -/* --- 64bit integer --- */ > - > -static void get_uint64(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - uint64_t *ptr = object_get_prop_ptr(obj, prop); > - > - visit_type_uint64(v, ptr, name, errp); > -} > - > -static void set_uint64(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - uint64_t *ptr = object_get_prop_ptr(obj, prop); > - > - if (object_is_realized(obj)) { > - error_set(errp, QERR_PERMISSION_DENIED); > - return; > - } > - > - visit_type_uint64(v, ptr, name, errp); > -} > - > -PropertyInfo qdev_prop_uint64 = { > - .name = "uint64", > - .get = get_uint64, > - .set = set_uint64, > -}; > - > -/* --- 64bit hex value --- */ > - > -static int parse_hex64(Object *obj, Property *prop, const char *str) > -{ > - uint64_t *ptr = object_get_prop_ptr(obj, prop); > - char *end; > - > - if (str[0] != '0' || str[1] != 'x') { > - return -EINVAL; > - } > - > - *ptr = strtoull(str,&end, 16); > - if ((*end != '\0') || (end == str)) { > - return -EINVAL; > - } > - > - return 0; > -} > - > -static int print_hex64(Object *obj, Property *prop, char *dest, size_t len) > -{ > - uint64_t *ptr = object_get_prop_ptr(obj, prop); > - return snprintf(dest, len, "0x%" PRIx64, *ptr); > -} > - > -PropertyInfo qdev_prop_hex64 = { > - .name = "uint64", > - .legacy_name = "hex64", > - .parse = parse_hex64, > - .print = print_hex64, > - .get = get_uint64, > - .set = set_uint64, > -}; > - > -/* --- string --- */ > - > -static void release_string(Object *obj, const char *name, void *opaque) > -{ > - Property *prop = opaque; > - g_free(*(char **)object_get_prop_ptr(obj, prop)); > -} > - > -static int print_string(Object *obj, Property *prop, char *dest, size_t len) > -{ > - char **ptr = object_get_prop_ptr(obj, prop); > - if (!*ptr) > - return snprintf(dest, len, ""); > - return snprintf(dest, len, "\"%s\"", *ptr); > -} > - > -static void get_string(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - char **ptr = object_get_prop_ptr(obj, prop); > - > - if (!*ptr) { > - char *str = (char *)""; > - visit_type_str(v,&str, name, errp); > - } else { > - visit_type_str(v, ptr, name, errp); > - } > -} > - > -static void set_string(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > +void error_set_from_prop_error(Error **errp, int ret, Object *obj, > + Property *prop, const char *value) > { > - Property *prop = opaque; > - char **ptr = object_get_prop_ptr(obj, prop); > - Error *local_err = NULL; > - char *str; > - > - if (object_is_realized(obj)) { > - error_set(errp, QERR_PERMISSION_DENIED); > - return; > - } > - > - visit_type_str(v,&str, name,&local_err); > - if (local_err) { > - error_propagate(errp, local_err); > - return; > - } > - if (*ptr) { > - g_free(*ptr); > + switch (ret) { > + case -EEXIST: > + error_set(errp, QERR_PROPERTY_VALUE_IN_USE, > + object_get_id(obj), prop->name, value); > + break; > + default: > + case -EINVAL: > + error_set(errp, QERR_PROPERTY_VALUE_BAD, > + object_get_id(obj), prop->name, value); > + break; > + case -ENOENT: > + error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND, > + object_get_id(obj), prop->name, value); > + break; > + case 0: > + break; > } > - *ptr = str; > } > - > -PropertyInfo qdev_prop_string = { > - .name = "string", > - .print = print_string, > - .release = release_string, > - .get = get_string, > - .set = set_string, > -}; > - > /* --- drive --- */ > > static int parse_drive(Object *obj, const char *str, void **ptr) > @@ -636,13 +271,6 @@ PropertyInfo qdev_prop_vlan = { > .set = set_vlan, > }; > > -/* --- pointer --- */ > - > -/* Not a proper property, just for dirty hacks. TODO Remove it! */ > -PropertyInfo qdev_prop_ptr = { > - .name = "ptr", > -}; > - > /* --- mac address --- */ > > /* > @@ -713,6 +341,12 @@ PropertyInfo qdev_prop_macaddr = { > .set = set_mac, > }; > > +/* --- pointer --- */ > + > +/* Not a proper property, just for dirty hacks. TODO Remove it! */ > +PropertyInfo qdev_prop_ptr = { > + .name = "ptr", > +}; > > /* --- lost tick policy --- */ > > @@ -726,40 +360,24 @@ static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = { > > QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int)); > > -static void get_enum(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - int *ptr = object_get_prop_ptr(obj, prop); > - > - visit_type_enum(v, ptr, prop->info->enum_table, > - prop->info->name, prop->name, errp); > -} > - > -static void set_enum(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - Property *prop = opaque; > - int *ptr = object_get_prop_ptr(obj, prop); > - > - if (object_is_realized(obj)) { > - error_set(errp, QERR_PERMISSION_DENIED); > - return; > - } > - > - visit_type_enum(v, ptr, prop->info->enum_table, > - prop->info->name, prop->name, errp); > -} > - > PropertyInfo qdev_prop_losttickpolicy = { > .name = "LostTickPolicy", > .enum_table = lost_tick_policy_table, > - .get = get_enum, > - .set = set_enum, > + .get = property_get_enum, > + .set = property_set_enum, > }; > > /* --- pci address --- */ > > +static void get_pci_devfn(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + int32_t *ptr = object_get_prop_ptr(obj, prop); > + > + visit_type_int32(v, ptr, name, errp); > +} > + > /* > * bus-local address, i.e. "$slot" or "$slot.$fn" > */ > @@ -826,12 +444,21 @@ PropertyInfo qdev_prop_pci_devfn = { > .name = "int32", > .legacy_name = "pci-devfn", > .print = print_pci_devfn, > - .get = get_int32, > + .get = get_pci_devfn, > .set = set_pci_devfn, > }; > > /* --- blocksize --- */ > > +static void get_blocksize(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + uint16_t *ptr = object_get_prop_ptr(obj, prop); > + > + visit_type_uint16(v, ptr, name, errp); > +} > + > static void set_blocksize(Object *obj, Visitor *v, void *opaque, > const char *name, Error **errp) > { > @@ -869,7 +496,7 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque, > > PropertyInfo qdev_prop_blocksize = { > .name = "blocksize", > - .get = get_uint16, > + .get = get_blocksize, > .set = set_blocksize, > }; > > @@ -905,28 +532,6 @@ static Property *qdev_prop_find(Object *obj, const char *name) > return NULL; > } > > -void error_set_from_prop_error(Error **errp, int ret, Object *obj, > - Property *prop, const char *value) > -{ > - switch (ret) { > - case -EEXIST: > - error_set(errp, QERR_PROPERTY_VALUE_IN_USE, > - object_get_id(obj), prop->name, value); > - break; > - default: > - case -EINVAL: > - error_set(errp, QERR_PROPERTY_VALUE_BAD, > - object_get_id(obj), prop->name, value); > - break; > - case -ENOENT: > - error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND, > - object_get_id(obj), prop->name, value); > - break; > - case 0: > - break; > - } > -} > - > int qdev_prop_parse(DeviceState *dev, const char *name, const char *value) > { > char *legacy_name; > diff --git a/hw/qdev.c b/hw/qdev.c > index fdafd7d..d4b8f91 100644 > --- a/hw/qdev.c > +++ b/hw/qdev.c > @@ -615,51 +615,6 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop, > g_free(name); > } > > -/** > - * @qdev_property_add_static - add a @Property to a device. > - * > - * Static properties access data in a struct. The actual type of the > - * property and the field depends on the property type. > - */ > -void qdev_property_add_static(DeviceState *dev, Property *prop, > - Error **errp) > -{ > - Error *local_err = NULL; > - Object *obj = OBJECT(dev); > - > - /* > - * TODO qdev_prop_ptr does not have getters or setters. It must > - * go now that it can be replaced with links. The test should be > - * removed along with it: all static properties are read/write. > - */ > - if (!prop->info->get&& !prop->info->set) { > - return; > - } > - > - object_property_add(obj, prop->name, prop->info->name, > - prop->info->get, prop->info->set, > - prop->info->release, > - prop,&local_err); > - > - if (local_err) { > - error_propagate(errp, local_err); > - return; > - } > - if (prop->qtype == QTYPE_NONE) { > - return; > - } > - > - if (prop->qtype == QTYPE_QBOOL) { > - object_property_set_bool(obj, prop->defval, prop->name,&local_err); > - } else if (prop->info->enum_table) { > - object_property_set_str(obj, prop->info->enum_table[prop->defval], > - prop->name,&local_err); > - } else if (prop->qtype == QTYPE_QINT) { > - object_property_set_int(obj, prop->defval, prop->name,&local_err); > - } > - assert_no_error(local_err); > -} > - > static void device_initfn(Object *obj) > { > DeviceState *dev = DEVICE(obj); > @@ -677,7 +632,7 @@ static void device_initfn(Object *obj) > do { > for (prop = DEVICE_CLASS(class)->props; prop&& prop->name; prop++) { > qdev_property_add_legacy(dev, prop, NULL); > - qdev_property_add_static(dev, prop, NULL); > + object_property_add_static(OBJECT(dev), prop, NULL); > } > class = object_class_get_parent(class); > } while (class != object_class_by_name(TYPE_DEVICE)); > diff --git a/hw/qdev.h b/hw/qdev.h > index bfa8620..c810d43 100644 > --- a/hw/qdev.h > +++ b/hw/qdev.h > @@ -9,10 +9,6 @@ > #include "qemu/object.h" > #include "error.h" > > -typedef struct Property Property; > - > -typedef struct PropertyInfo PropertyInfo; > - > typedef struct CompatProperty CompatProperty; > > typedef struct BusState BusState; > @@ -117,26 +113,6 @@ struct BusState { > QLIST_ENTRY(BusState) sibling; > }; > > -struct Property { > - const char *name; > - PropertyInfo *info; > - int offset; > - uint8_t bitnr; > - uint8_t qtype; > - int64_t defval; > -}; > - > -struct PropertyInfo { > - const char *name; > - const char *legacy_name; > - const char **enum_table; > - int (*parse)(Object *obj, Property *prop, const char *str); > - int (*print)(Object *obj, Property *prop, char *dest, size_t len); > - ObjectPropertyAccessor *get; > - ObjectPropertyAccessor *set; > - ObjectPropertyRelease *release; > -}; > - > typedef struct GlobalProperty { > const char *driver; > const char *property; > @@ -212,16 +188,6 @@ int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data); > > /*** qdev-properties.c ***/ > > -extern PropertyInfo qdev_prop_bit; > -extern PropertyInfo qdev_prop_uint8; > -extern PropertyInfo qdev_prop_uint16; > -extern PropertyInfo qdev_prop_uint32; > -extern PropertyInfo qdev_prop_int32; > -extern PropertyInfo qdev_prop_uint64; > -extern PropertyInfo qdev_prop_hex8; > -extern PropertyInfo qdev_prop_hex32; > -extern PropertyInfo qdev_prop_hex64; > -extern PropertyInfo qdev_prop_string; > extern PropertyInfo qdev_prop_chr; > extern PropertyInfo qdev_prop_ptr; > extern PropertyInfo qdev_prop_macaddr; > @@ -232,55 +198,12 @@ extern PropertyInfo qdev_prop_vlan; > extern PropertyInfo qdev_prop_pci_devfn; > extern PropertyInfo qdev_prop_blocksize; > > -#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \ > - .name = (_name), \ > - .info =&(_prop), \ > - .offset = offsetof(_state, _field) \ > - + type_check(_type,typeof_field(_state, _field)), \ > - } > -#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \ > - .name = (_name), \ > - .info =&(_prop), \ > - .offset = offsetof(_state, _field) \ > - + type_check(_type,typeof_field(_state, _field)), \ > - .qtype = QTYPE_QINT, \ > - .defval = (_type)_defval, \ > - } > -#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) { \ > - .name = (_name), \ > - .info =&(qdev_prop_bit), \ > - .bitnr = (_bit), \ > - .offset = offsetof(_state, _field) \ > - + type_check(uint32_t,typeof_field(_state, _field)), \ > - .qtype = QTYPE_QBOOL, \ > - .defval = (bool)_defval, \ > - } > - > -#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \ > - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t) > -#define DEFINE_PROP_UINT16(_n, _s, _f, _d) \ > - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t) > -#define DEFINE_PROP_UINT32(_n, _s, _f, _d) \ > - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t) > -#define DEFINE_PROP_INT32(_n, _s, _f, _d) \ > - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t) > -#define DEFINE_PROP_UINT64(_n, _s, _f, _d) \ > - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t) > -#define DEFINE_PROP_HEX8(_n, _s, _f, _d) \ > - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t) > -#define DEFINE_PROP_HEX32(_n, _s, _f, _d) \ > - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t) > -#define DEFINE_PROP_HEX64(_n, _s, _f, _d) \ > - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t) > #define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \ > DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t) > - > #define DEFINE_PROP_PTR(_n, _s, _f) \ > DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*) > #define DEFINE_PROP_CHR(_n, _s, _f) \ > DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*) > -#define DEFINE_PROP_STRING(_n, _s, _f) \ > - DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*) > #define DEFINE_PROP_NETDEV(_n, _s, _f) \ > DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, VLANClientState*) > #define DEFINE_PROP_VLAN(_n, _s, _f) \ > @@ -295,11 +218,7 @@ extern PropertyInfo qdev_prop_blocksize; > #define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \ > DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t) > > -#define DEFINE_PROP_END_OF_LIST() \ > - {} > - > /* Set properties between creation and init. */ > -void *object_get_prop_ptr(Object *obj, Property *prop); > int qdev_prop_parse(DeviceState *dev, const char *name, const char *value); > void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value); > void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value); > @@ -326,12 +245,6 @@ void error_set_from_prop_error(Error **errp, int ret, Object *obj, > char *qdev_get_fw_dev_path(DeviceState *dev); > > /** > - * @qdev_property_add_static - add a @Property to a device referencing a > - * field in a struct. > - */ > -void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp); > - > -/** > * @qdev_machine_init > * > * Initialize platform devices before machine init. This is a hack until full > diff --git a/include/qemu/object.h b/include/qemu/object.h > index 81e0280..ea5f16e 100644 > --- a/include/qemu/object.h > +++ b/include/qemu/object.h > @@ -983,5 +983,103 @@ int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), > */ > Object *container_get(Object *root, const char *path); > > +typedef struct Property Property; > +typedef struct PropertyInfo PropertyInfo; > + > +struct Property { > + const char *name; > + PropertyInfo *info; > + int offset; > + uint8_t bitnr; > + uint8_t qtype; > + int64_t defval; > +}; > + > +struct PropertyInfo { > + const char *name; > + const char *legacy_name; > + const char **enum_table; > + int (*parse)(Object *obj, Property *prop, const char *str); > + int (*print)(Object *obj, Property *prop, char *dest, size_t len); > + ObjectPropertyAccessor *get; > + ObjectPropertyAccessor *set; > + ObjectPropertyRelease *release; > +}; > + > +extern PropertyInfo qdev_prop_bit; > +extern PropertyInfo qdev_prop_uint8; > +extern PropertyInfo qdev_prop_uint16; > +extern PropertyInfo qdev_prop_uint32; > +extern PropertyInfo qdev_prop_int32; > +extern PropertyInfo qdev_prop_uint64; > +extern PropertyInfo qdev_prop_hex8; > +extern PropertyInfo qdev_prop_hex32; > +extern PropertyInfo qdev_prop_hex64; > +extern PropertyInfo qdev_prop_string; > + > +#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \ > + .name = (_name), \ > + .info =&(_prop), \ > + .offset = offsetof(_state, _field) \ > + + type_check(_type,typeof_field(_state, _field)), \ > + } > +#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \ > + .name = (_name), \ > + .info =&(_prop), \ > + .offset = offsetof(_state, _field) \ > + + type_check(_type,typeof_field(_state, _field)), \ > + .qtype = QTYPE_QINT, \ > + .defval = (_type)_defval, \ > + } > +#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) { \ > + .name = (_name), \ > + .info =&(qdev_prop_bit), \ > + .bitnr = (_bit), \ > + .offset = offsetof(_state, _field) \ > + + type_check(uint32_t,typeof_field(_state, _field)), \ > + .qtype = QTYPE_QBOOL, \ > + .defval = (bool)_defval, \ > + } > + > +#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \ > + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t) > +#define DEFINE_PROP_UINT16(_n, _s, _f, _d) \ > + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t) > +#define DEFINE_PROP_UINT32(_n, _s, _f, _d) \ > + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t) > +#define DEFINE_PROP_INT32(_n, _s, _f, _d) \ > + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t) > +#define DEFINE_PROP_UINT64(_n, _s, _f, _d) \ > + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t) > +#define DEFINE_PROP_HEX8(_n, _s, _f, _d) \ > + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t) > +#define DEFINE_PROP_HEX32(_n, _s, _f, _d) \ > + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t) > +#define DEFINE_PROP_HEX64(_n, _s, _f, _d) \ > + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t) > +#define DEFINE_PROP_STRING(_n, _s, _f) \ > + DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*) > + > +#define DEFINE_PROP_END_OF_LIST() \ > + {} > + > +void property_get_enum(Object *obj, struct Visitor *v, void *opaque, > + const char *name, struct Error **errp); > +void property_set_enum(Object *obj, struct Visitor *v, void *opaque, > + const char *name, struct Error **errp); > + > +void *object_get_prop_ptr(Object *obj, Property *prop); > + > +/** > + * object_property_add_static: > + * @obj: the object to add the property to > + * @prop: the property to be added > + * @errp: if an error occurs, a pointer to an area to store the error > + * > + * Add a #Property to an object referencing a field in a struct. > + */ > +void object_property_add_static(Object *obj, Property *prop, > + struct Error **errp); > + > > #endif > diff --git a/qom/Makefile b/qom/Makefile > index 34c6de5..2aae0ba 100644 > --- a/qom/Makefile > +++ b/qom/Makefile > @@ -1,2 +1,2 @@ > -qom-y = object.o container.o qom-qobject.o > +qom-y = object.o object-properties.o container.o qom-qobject.o > qom-twice-y = cpu.o > diff --git a/qom/object-properties.c b/qom/object-properties.c > new file mode 100644 > index 0000000..6765e90 > --- /dev/null > +++ b/qom/object-properties.c > @@ -0,0 +1,461 @@ > +#include "qemu/object.h" > +#include "qapi/qapi-visit-core.h" > + > +void *object_get_prop_ptr(Object *obj, Property *prop) > +{ > + void *ptr = obj; > + ptr += prop->offset; > + return ptr; > +} > + > +static uint32_t get_prop_mask(Property *prop) > +{ > + assert(prop->info ==&qdev_prop_bit); > + return 0x1<< prop->bitnr; > +} > + > +static void bit_prop_set(Object *obj, Property *props, bool val) > +{ > + uint32_t *p = object_get_prop_ptr(obj, props); > + uint32_t mask = get_prop_mask(props); > + if (val) > + *p |= mask; > + else > + *p&= ~mask; > +} > + > +/* Bit */ > + > +static int print_bit(Object *obj, Property *prop, char *dest, size_t len) > +{ > + uint32_t *p = object_get_prop_ptr(obj, prop); > + return snprintf(dest, len, (*p& get_prop_mask(prop)) ? "on" : "off"); > +} > + > +static void get_bit(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + uint32_t *p = object_get_prop_ptr(obj, prop); > + bool value = (*p& get_prop_mask(prop)) != 0; > + > + visit_type_bool(v,&value, name, errp); > +} > + > +static void set_bit(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + Error *local_err = NULL; > + bool value; > + > + if (object_is_realized(obj)) { > + error_set(errp, QERR_PERMISSION_DENIED); > + return; > + } > + > + visit_type_bool(v,&value, name,&local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + bit_prop_set(obj, prop, value); > +} > + > +PropertyInfo qdev_prop_bit = { > + .name = "boolean", > + .legacy_name = "on/off", > + .print = print_bit, > + .get = get_bit, > + .set = set_bit, > +}; > + > +/* --- 8bit integer --- */ > + > +static void get_uint8(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + uint8_t *ptr = object_get_prop_ptr(obj, prop); > + > + visit_type_uint8(v, ptr, name, errp); > +} > + > +static void set_uint8(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + uint8_t *ptr = object_get_prop_ptr(obj, prop); > + > + if (object_is_realized(obj)) { > + error_set(errp, QERR_PERMISSION_DENIED); > + return; > + } > + > + visit_type_uint8(v, ptr, name, errp); > +} > + > +PropertyInfo qdev_prop_uint8 = { > + .name = "uint8", > + .get = get_uint8, > + .set = set_uint8, > +}; > + > +/* --- 8bit hex value --- */ > + > +static int parse_hex8(Object *obj, Property *prop, const char *str) > +{ > + uint8_t *ptr = object_get_prop_ptr(obj, prop); > + char *end; > + > + if (str[0] != '0' || str[1] != 'x') { > + return -EINVAL; > + } > + > + *ptr = strtoul(str,&end, 16); > + if ((*end != '\0') || (end == str)) { > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int print_hex8(Object *obj, Property *prop, char *dest, size_t len) > +{ > + uint8_t *ptr = object_get_prop_ptr(obj, prop); > + return snprintf(dest, len, "0x%" PRIx8, *ptr); > +} > + > +PropertyInfo qdev_prop_hex8 = { > + .name = "uint8", > + .legacy_name = "hex8", > + .parse = parse_hex8, > + .print = print_hex8, > + .get = get_uint8, > + .set = set_uint8, > +}; > + > +/* --- 16bit integer --- */ > + > +static void get_uint16(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + uint16_t *ptr = object_get_prop_ptr(obj, prop); > + > + visit_type_uint16(v, ptr, name, errp); > +} > + > +static void set_uint16(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + uint16_t *ptr = object_get_prop_ptr(obj, prop); > + > + if (object_is_realized(obj)) { > + error_set(errp, QERR_PERMISSION_DENIED); > + return; > + } > + > + visit_type_uint16(v, ptr, name, errp); > +} > + > +PropertyInfo qdev_prop_uint16 = { > + .name = "uint16", > + .get = get_uint16, > + .set = set_uint16, > +}; > + > +/* --- 32bit integer --- */ > + > +static void get_uint32(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + uint32_t *ptr = object_get_prop_ptr(obj, prop); > + > + visit_type_uint32(v, ptr, name, errp); > +} > + > +static void set_uint32(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + uint32_t *ptr = object_get_prop_ptr(obj, prop); > + > + if (object_is_realized(obj)) { > + error_set(errp, QERR_PERMISSION_DENIED); > + return; > + } > + > + visit_type_uint32(v, ptr, name, errp); > +} > + > +static void get_int32(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + int32_t *ptr = object_get_prop_ptr(obj, prop); > + > + visit_type_int32(v, ptr, name, errp); > +} > + > +static void set_int32(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + int32_t *ptr = object_get_prop_ptr(obj, prop); > + > + if (object_is_realized(obj)) { > + error_set(errp, QERR_PERMISSION_DENIED); > + return; > + } > + > + visit_type_int32(v, ptr, name, errp); > +} > + > +PropertyInfo qdev_prop_uint32 = { > + .name = "uint32", > + .get = get_uint32, > + .set = set_uint32, > +}; > + > +PropertyInfo qdev_prop_int32 = { > + .name = "int32", > + .get = get_int32, > + .set = set_int32, > +}; > + > +/* --- 32bit hex value --- */ > + > +static int parse_hex32(Object *obj, Property *prop, const char *str) > +{ > + uint32_t *ptr = object_get_prop_ptr(obj, prop); > + char *end; > + > + if (str[0] != '0' || str[1] != 'x') { > + return -EINVAL; > + } > + > + *ptr = strtoul(str,&end, 16); > + if ((*end != '\0') || (end == str)) { > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int print_hex32(Object *obj, Property *prop, char *dest, size_t len) > +{ > + uint32_t *ptr = object_get_prop_ptr(obj, prop); > + return snprintf(dest, len, "0x%" PRIx32, *ptr); > +} > + > +PropertyInfo qdev_prop_hex32 = { > + .name = "uint32", > + .legacy_name = "hex32", > + .parse = parse_hex32, > + .print = print_hex32, > + .get = get_uint32, > + .set = set_uint32, > +}; > + > +/* --- 64bit integer --- */ > + > +static void get_uint64(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + uint64_t *ptr = object_get_prop_ptr(obj, prop); > + > + visit_type_uint64(v, ptr, name, errp); > +} > + > +static void set_uint64(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + uint64_t *ptr = object_get_prop_ptr(obj, prop); > + > + if (object_is_realized(obj)) { > + error_set(errp, QERR_PERMISSION_DENIED); > + return; > + } > + > + visit_type_uint64(v, ptr, name, errp); > +} > + > +PropertyInfo qdev_prop_uint64 = { > + .name = "uint64", > + .get = get_uint64, > + .set = set_uint64, > +}; > + > +/* --- 64bit hex value --- */ > + > +static int parse_hex64(Object *obj, Property *prop, const char *str) > +{ > + uint64_t *ptr = object_get_prop_ptr(obj, prop); > + char *end; > + > + if (str[0] != '0' || str[1] != 'x') { > + return -EINVAL; > + } > + > + *ptr = strtoull(str,&end, 16); > + if ((*end != '\0') || (end == str)) { > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int print_hex64(Object *obj, Property *prop, char *dest, size_t len) > +{ > + uint64_t *ptr = object_get_prop_ptr(obj, prop); > + return snprintf(dest, len, "0x%" PRIx64, *ptr); > +} > + > +PropertyInfo qdev_prop_hex64 = { > + .name = "uint64", > + .legacy_name = "hex64", > + .parse = parse_hex64, > + .print = print_hex64, > + .get = get_uint64, > + .set = set_uint64, > +}; > + > +/* --- string --- */ > + > +static void release_string(Object *obj, const char *name, void *opaque) > +{ > + Property *prop = opaque; > + g_free(*(char **)object_get_prop_ptr(obj, prop)); > +} > + > +static int print_string(Object *obj, Property *prop, char *dest, size_t len) > +{ > + char **ptr = object_get_prop_ptr(obj, prop); > + if (!*ptr) > + return snprintf(dest, len, ""); > + return snprintf(dest, len, "\"%s\"", *ptr); > +} > + > +static void get_string(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + char **ptr = object_get_prop_ptr(obj, prop); > + > + if (!*ptr) { > + char *str = (char *)""; > + visit_type_str(v,&str, name, errp); > + } else { > + visit_type_str(v, ptr, name, errp); > + } > +} > + > +static void set_string(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + char **ptr = object_get_prop_ptr(obj, prop); > + Error *local_err = NULL; > + char *str; > + > + if (object_is_realized(obj)) { > + error_set(errp, QERR_PERMISSION_DENIED); > + return; > + } > + > + visit_type_str(v,&str, name,&local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + if (*ptr) { > + g_free(*ptr); > + } > + *ptr = str; > +} > + > +PropertyInfo qdev_prop_string = { > + .name = "string", > + .print = print_string, > + .release = release_string, > + .get = get_string, > + .set = set_string, > +}; > + > + > +/* --- enums --- */ > + > +void property_get_enum(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + int *ptr = object_get_prop_ptr(obj, prop); > + > + visit_type_enum(v, ptr, prop->info->enum_table, > + prop->info->name, prop->name, errp); > +} > + > +void property_set_enum(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + Property *prop = opaque; > + int *ptr = object_get_prop_ptr(obj, prop); > + > + if (object_is_realized(obj)) { > + error_set(errp, QERR_PERMISSION_DENIED); > + return; > + } > + > + visit_type_enum(v, ptr, prop->info->enum_table, > + prop->info->name, prop->name, errp); > +} > + > + > +/** > + * @object_property_add_static - add a @Property to a device. > + * > + * Static properties access data in a struct. The actual type of the > + * property and the field depends on the property type. > + */ > +void object_property_add_static(Object *obj, Property *prop, > + Error **errp) > +{ > + Error *local_err = NULL; > + > + /* > + * TODO qdev_prop_ptr does not have getters or setters. It must > + * go now that it can be replaced with links. The test should be > + * removed along with it: all static properties are read/write. > + */ > + if (!prop->info->get&& !prop->info->set) { > + return; > + } > + > + object_property_add(obj, prop->name, prop->info->name, > + prop->info->get, prop->info->set, > + prop->info->release, > + prop,&local_err); > + > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + if (prop->qtype == QTYPE_NONE) { > + return; > + } > + > + if (prop->qtype == QTYPE_QBOOL) { > + object_property_set_bool(obj, prop->defval, prop->name,&local_err); > + } else if (prop->info->enum_table) { > + object_property_set_str(obj, prop->info->enum_table[prop->defval], > + prop->name,&local_err); > + } else if (prop->qtype == QTYPE_QINT) { > + object_property_set_int(obj, prop->defval, prop->name,&local_err); > + } > + assert_no_error(local_err); > +}