From: Paolo Bonzini <pbonz...@redhat.com> Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> [AF: Move to new qom/object-properties.c, update documentation.] Signed-off-by: Andreas Färber <afaer...@suse.de> --- hw/qdev-properties.c | 487 +++++------------------------------------------ hw/qdev.c | 47 +----- hw/qdev.h | 87 --------- include/qemu/object.h | 98 ++++++++++ qom/Makefile.objs | 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 8dc9de1..8651141 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, "<null>"); - 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_typename(obj), prop->name, value); + break; + default: + case -EINVAL: + error_set(errp, QERR_PROPERTY_VALUE_BAD, + object_get_typename(obj), prop->name, value); + break; + case -ENOENT: + error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND, + object_get_typename(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_typename(obj), prop->name, value); - break; - default: - case -EINVAL: - error_set(errp, QERR_PROPERTY_VALUE_BAD, - object_get_typename(obj), prop->name, value); - break; - case -ENOENT: - error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND, - object_get_typename(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 a82fec8..9aaa60b 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 274c839..048ac86 100644 --- a/include/qemu/object.h +++ b/include/qemu/object.h @@ -989,5 +989,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.objs b/qom/Makefile.objs index 5ef060a..bacddf6 100644 --- a/qom/Makefile.objs +++ b/qom/Makefile.objs @@ -1,4 +1,4 @@ -qom-obj-y = object.o container.o qom-qobject.o +qom-obj-y = object.o object-properties.o container.o qom-qobject.o qom-obj-twice-y = cpu.o common-obj-y = $(qom-obj-twice-y) user-obj-y = $(qom-obj-twice-y) 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, "<null>"); + 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); +} -- 1.7.7