diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-05-18 13:18:31 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-05-18 13:42:15 +0300 |
commit | 437fd90c0250dee670290f9b714253671a990160 (patch) | |
tree | b871786c360704244a07411c69fb58da9ead4a06 /qemu/qom | |
parent | 5bbd6fe9b8bab2a93e548c5a53b032d1939eec05 (diff) |
These changes are the raw update to qemu-2.6.
Collission happened in the following patches:
migration: do cleanup operation after completion(738df5b9)
Bug fix.(1750c932f86)
kvmclock: add a new function to update env->tsc.(b52baab2)
The code provided by the patches was already in the upstreamed
version.
Change-Id: I3cc11841a6a76ae20887b2e245710199e1ea7f9a
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'qemu/qom')
-rw-r--r-- | qemu/qom/Makefile.objs | 7 | ||||
-rw-r--r-- | qemu/qom/container.c | 2 | ||||
-rw-r--r-- | qemu/qom/cpu.c | 22 | ||||
-rw-r--r-- | qemu/qom/object.c | 570 | ||||
-rw-r--r-- | qemu/qom/object_interfaces.c | 178 | ||||
-rw-r--r-- | qemu/qom/qom-qobject.c | 20 |
6 files changed, 650 insertions, 149 deletions
diff --git a/qemu/qom/Makefile.objs b/qemu/qom/Makefile.objs index 985003bd0..516349eec 100644 --- a/qemu/qom/Makefile.objs +++ b/qemu/qom/Makefile.objs @@ -1,3 +1,4 @@ -common-obj-y = object.o container.o qom-qobject.o -common-obj-y += cpu.o -common-obj-y += object_interfaces.o +qom-obj-y = object.o container.o qom-qobject.o +qom-obj-y += object_interfaces.o + +common-obj-y = cpu.o diff --git a/qemu/qom/container.c b/qemu/qom/container.c index 62b1648ad..c9eb49b01 100644 --- a/qemu/qom/container.c +++ b/qemu/qom/container.c @@ -10,9 +10,9 @@ * See the COPYING file in the top-level directory. */ +#include "qemu/osdep.h" #include "qom/object.h" #include "qemu/module.h" -#include <assert.h> static const TypeInfo container_info = { .name = "container", diff --git a/qemu/qom/cpu.c b/qemu/qom/cpu.c index eb9cfeca1..c9007d3d0 100644 --- a/qemu/qom/cpu.c +++ b/qemu/qom/cpu.c @@ -18,11 +18,14 @@ * <http://www.gnu.org/licenses/gpl-2.0.html> */ +#include "qemu/osdep.h" +#include "qapi/error.h" #include "qemu-common.h" #include "qom/cpu.h" #include "sysemu/kvm.h" #include "qemu/notify.h" #include "qemu/log.h" +#include "exec/log.h" #include "qemu/error-report.h" #include "sysemu/sysemu.h" @@ -114,6 +117,8 @@ void cpu_reset_interrupt(CPUState *cpu, int mask) void cpu_exit(CPUState *cpu) { cpu->exit_request = 1; + /* Ensure cpu_exec will see the exit request after TCG has exited. */ + smp_wmb(); cpu->tcg_exit_req = 1; } @@ -128,7 +133,7 @@ int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu, static int cpu_common_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu, void *opaque) { - return -1; + return 0; } int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu, @@ -157,7 +162,7 @@ int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu, static int cpu_common_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu, void *opaque) { - return -1; + return 0; } int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu, @@ -186,6 +191,14 @@ static int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg) return 0; } +static bool cpu_common_debug_check_watchpoint(CPUState *cpu, CPUWatchpoint *wp) +{ + /* If no extra check is required, QEMU watchpoint match can be considered + * as an architectural match. + */ + return true; +} + bool target_words_bigendian(void); static bool cpu_common_virtio_is_big_endian(CPUState *cpu) { @@ -247,8 +260,9 @@ static void cpu_common_reset(CPUState *cpu) cpu->mem_io_vaddr = 0; cpu->icount_extra = 0; cpu->icount_decr.u32 = 0; - cpu->can_do_io = 0; + cpu->can_do_io = 1; cpu->exception_index = -1; + cpu->crash_occurred = false; memset(cpu->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof(void *)); } @@ -314,6 +328,7 @@ static void cpu_common_initfn(Object *obj) cpu->cpu_index = -1; cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs; + qemu_mutex_init(&cpu->work_mutex); QTAILQ_INIT(&cpu->breakpoints); QTAILQ_INIT(&cpu->watchpoints); } @@ -348,6 +363,7 @@ static void cpu_class_init(ObjectClass *klass, void *data) k->gdb_write_register = cpu_common_gdb_write_register; k->virtio_is_big_endian = cpu_common_virtio_is_big_endian; k->debug_excp_handler = cpu_common_noop; + k->debug_check_watchpoint = cpu_common_debug_check_watchpoint; k->cpu_exec_enter = cpu_common_noop; k->cpu_exec_exit = cpu_common_noop; k->cpu_exec_interrupt = cpu_common_exec_interrupt; diff --git a/qemu/qom/object.c b/qemu/qom/object.c index eea8edf3d..8e6e68dff 100644 --- a/qemu/qom/object.c +++ b/qemu/qom/object.c @@ -10,9 +10,11 @@ * See the COPYING file in the top-level directory. */ +#include "qemu/osdep.h" +#include "qapi/error.h" #include "qom/object.h" #include "qom/object_interfaces.h" -#include "qemu-common.h" +#include "qemu/cutils.h" #include "qapi/visitor.h" #include "qapi-visit.h" #include "qapi/string-input-visitor.h" @@ -204,7 +206,7 @@ static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type) { assert(target_type); - /* Check if typename is a direct ancestor of type */ + /* Check if target_type is a direct ancestor of type */ while (type) { if (type == target_type) { return true; @@ -242,6 +244,16 @@ static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type, iface_impl->class); } +static void object_property_free(gpointer data) +{ + ObjectProperty *prop = data; + + g_free(prop->name); + g_free(prop->type); + g_free(prop->description); + g_free(prop); +} + static void type_initialize(TypeImpl *ti) { TypeImpl *parent; @@ -261,9 +273,11 @@ static void type_initialize(TypeImpl *ti) GSList *e; int i; - g_assert(parent->class_size <= ti->class_size); + g_assert_cmpint(parent->class_size, <=, ti->class_size); memcpy(ti->class, parent->class, parent->class_size); ti->class->interfaces = NULL; + ti->class->properties = g_hash_table_new_full( + g_str_hash, g_str_equal, g_free, object_property_free); for (e = parent->class->interfaces; e; e = e->next) { InterfaceClass *iface = e->data; @@ -288,6 +302,9 @@ static void type_initialize(TypeImpl *ti) type_initialize_interface(ti, t, t); } + } else { + ti->class->properties = g_hash_table_new_full( + g_str_hash, g_str_equal, g_free, object_property_free); } ti->class->type = ti; @@ -333,14 +350,15 @@ void object_initialize_with_type(void *data, size_t size, TypeImpl *type) g_assert(type != NULL); type_initialize(type); - g_assert(type->instance_size >= sizeof(Object)); + g_assert_cmpint(type->instance_size, >=, sizeof(Object)); g_assert(type->abstract == false); - g_assert(size >= type->instance_size); + g_assert_cmpint(size, >=, type->instance_size); memset(obj, 0, type->instance_size); obj->class = type->class; object_ref(obj); - QTAILQ_INIT(&obj->properties); + obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, object_property_free); object_init_with_type(obj, type); object_post_init_with_type(obj, type); } @@ -359,29 +377,51 @@ static inline bool object_property_is_child(ObjectProperty *prop) static void object_property_del_all(Object *obj) { - while (!QTAILQ_EMPTY(&obj->properties)) { - ObjectProperty *prop = QTAILQ_FIRST(&obj->properties); - - QTAILQ_REMOVE(&obj->properties, prop, node); - - if (prop->release) { - prop->release(obj, prop->name, prop->opaque); + ObjectProperty *prop; + GHashTableIter iter; + gpointer key, value; + bool released; + + do { + released = false; + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, &key, &value)) { + prop = value; + if (prop->release) { + prop->release(obj, prop->name, prop->opaque); + prop->release = NULL; + released = true; + break; + } + g_hash_table_iter_remove(&iter); } + } while (released); - g_free(prop->name); - g_free(prop->type); - g_free(prop->description); - g_free(prop); - } + g_hash_table_unref(obj->properties); } static void object_property_del_child(Object *obj, Object *child, Error **errp) { ObjectProperty *prop; + GHashTableIter iter; + gpointer key, value; - QTAILQ_FOREACH(prop, &obj->properties, node) { + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, &key, &value)) { + prop = value; + if (object_property_is_child(prop) && prop->opaque == child) { + if (prop->release) { + prop->release(obj, prop->name, prop->opaque); + prop->release = NULL; + } + break; + } + } + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, &key, &value)) { + prop = value; if (object_property_is_child(prop) && prop->opaque == child) { - object_property_del(obj, prop->name, errp); + g_hash_table_iter_remove(&iter); break; } } @@ -413,7 +453,7 @@ static void object_finalize(void *data) object_property_del_all(obj); object_deinit(obj, ti); - g_assert(obj->ref == 0); + g_assert_cmpint(obj->ref, ==, 0); if (obj->free) { obj->free(obj); } @@ -775,23 +815,44 @@ void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), enumerating_types = false; } -int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), - void *opaque) +static int do_object_child_foreach(Object *obj, + int (*fn)(Object *child, void *opaque), + void *opaque, bool recurse) { - ObjectProperty *prop, *next; + GHashTableIter iter; + ObjectProperty *prop; int ret = 0; - QTAILQ_FOREACH_SAFE(prop, &obj->properties, node, next) { + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { if (object_property_is_child(prop)) { - ret = fn(prop->opaque, opaque); + Object *child = prop->opaque; + + ret = fn(child, opaque); if (ret != 0) { break; } + if (recurse) { + do_object_child_foreach(child, fn, opaque, true); + } } } return ret; } +int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), + void *opaque) +{ + return do_object_child_foreach(obj, fn, opaque, false); +} + +int object_child_foreach_recursive(Object *obj, + int (*fn)(Object *child, void *opaque), + void *opaque) +{ + return do_object_child_foreach(obj, fn, opaque, true); +} + static void object_class_get_list_tramp(ObjectClass *klass, void *opaque) { GSList **list = opaque; @@ -814,7 +875,7 @@ void object_ref(Object *obj) if (!obj) { return; } - atomic_inc(&obj->ref); + atomic_inc(&obj->ref); } void object_unref(Object *obj) @@ -822,7 +883,7 @@ void object_unref(Object *obj) if (!obj) { return; } - g_assert(obj->ref > 0); + g_assert_cmpint(obj->ref, >, 0); /* parent always holds a reference to its children */ if (atomic_fetch_dec(&obj->ref) == 1) { @@ -860,13 +921,11 @@ object_property_add(Object *obj, const char *name, const char *type, return ret; } - QTAILQ_FOREACH(prop, &obj->properties, node) { - if (strcmp(prop->name, name) == 0) { - error_setg(errp, "attempt to add duplicate property '%s'" - " to object (type '%s')", name, - object_get_typename(obj)); - return NULL; - } + if (object_property_find(obj, name, NULL) != NULL) { + error_setg(errp, "attempt to add duplicate property '%s'" + " to object (type '%s')", name, + object_get_typename(obj)); + return NULL; } prop = g_malloc0(sizeof(*prop)); @@ -879,7 +938,41 @@ object_property_add(Object *obj, const char *name, const char *type, prop->release = release; prop->opaque = opaque; - QTAILQ_INSERT_TAIL(&obj->properties, prop, node); + g_hash_table_insert(obj->properties, prop->name, prop); + return prop; +} + +ObjectProperty * +object_class_property_add(ObjectClass *klass, + const char *name, + const char *type, + ObjectPropertyAccessor *get, + ObjectPropertyAccessor *set, + ObjectPropertyRelease *release, + void *opaque, + Error **errp) +{ + ObjectProperty *prop; + + if (object_class_property_find(klass, name, NULL) != NULL) { + error_setg(errp, "attempt to add duplicate property '%s'" + " to object (type '%s')", name, + object_class_get_name(klass)); + return NULL; + } + + prop = g_malloc0(sizeof(*prop)); + + prop->name = g_strdup(name); + prop->type = g_strdup(type); + + prop->get = get; + prop->set = set; + prop->release = release; + prop->opaque = opaque; + + g_hash_table_insert(klass->properties, g_strdup(name), prop); + return prop; } @@ -887,34 +980,76 @@ ObjectProperty *object_property_find(Object *obj, const char *name, Error **errp) { ObjectProperty *prop; + ObjectClass *klass = object_get_class(obj); - QTAILQ_FOREACH(prop, &obj->properties, node) { - if (strcmp(prop->name, name) == 0) { - return prop; - } + prop = object_class_property_find(klass, name, NULL); + if (prop) { + return prop; + } + + prop = g_hash_table_lookup(obj->properties, name); + if (prop) { + return prop; } error_setg(errp, "Property '.%s' not found", name); return NULL; } +void object_property_iter_init(ObjectPropertyIterator *iter, + Object *obj) +{ + g_hash_table_iter_init(&iter->iter, obj->properties); + iter->nextclass = object_get_class(obj); +} + +ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter) +{ + gpointer key, val; + while (!g_hash_table_iter_next(&iter->iter, &key, &val)) { + if (!iter->nextclass) { + return NULL; + } + g_hash_table_iter_init(&iter->iter, iter->nextclass->properties); + iter->nextclass = object_class_get_parent(iter->nextclass); + } + return val; +} + +ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, + Error **errp) +{ + ObjectProperty *prop; + ObjectClass *parent_klass; + + parent_klass = object_class_get_parent(klass); + if (parent_klass) { + prop = object_class_property_find(parent_klass, name, NULL); + if (prop) { + return prop; + } + } + + prop = g_hash_table_lookup(klass->properties, name); + if (!prop) { + error_setg(errp, "Property '.%s' not found", name); + } + return prop; +} + void object_property_del(Object *obj, const char *name, Error **errp) { - ObjectProperty *prop = object_property_find(obj, name, errp); - if (prop == NULL) { + ObjectProperty *prop = g_hash_table_lookup(obj->properties, name); + + if (!prop) { + error_setg(errp, "Property '.%s' not found", name); return; } if (prop->release) { prop->release(obj, name, prop->opaque); } - - QTAILQ_REMOVE(&obj->properties, prop, node); - - g_free(prop->name); - g_free(prop->type); - g_free(prop->description); - g_free(prop); + g_hash_table_remove(obj->properties, name); } void object_property_get(Object *obj, Visitor *v, const char *name, @@ -928,7 +1063,7 @@ void object_property_get(Object *obj, Visitor *v, const char *name, if (!prop->get) { error_setg(errp, QERR_PERMISSION_DENIED); } else { - prop->get(obj, v, prop->opaque, name, errp); + prop->get(obj, v, name, prop->opaque, errp); } } @@ -943,7 +1078,7 @@ void object_property_set(Object *obj, Visitor *v, const char *name, if (!prop->set) { error_setg(errp, QERR_PERMISSION_DENIED); } else { - prop->set(obj, v, prop->opaque, name, errp); + prop->set(obj, v, name, prop->opaque, errp); } } @@ -1079,6 +1214,7 @@ typedef struct EnumProperty { int object_property_get_enum(Object *obj, const char *name, const char *typename, Error **errp) { + Error *err = NULL; StringOutputVisitor *sov; StringInputVisitor *siv; char *str; @@ -1100,12 +1236,17 @@ int object_property_get_enum(Object *obj, const char *name, enumprop = prop->opaque; sov = string_output_visitor_new(false); - object_property_get(obj, string_output_get_visitor(sov), name, errp); + object_property_get(obj, string_output_get_visitor(sov), name, &err); + if (err) { + error_propagate(errp, err); + string_output_visitor_cleanup(sov); + return 0; + } str = string_output_get_string(sov); siv = string_input_visitor_new(str); string_output_visitor_cleanup(sov); - visit_type_enum(string_input_get_visitor(siv), - &ret, enumprop->strings, NULL, name, errp); + visit_type_enum(string_input_get_visitor(siv), name, &ret, + enumprop->strings, errp); g_free(str); string_input_visitor_cleanup(siv); @@ -1116,51 +1257,56 @@ int object_property_get_enum(Object *obj, const char *name, void object_property_get_uint16List(Object *obj, const char *name, uint16List **list, Error **errp) { + Error *err = NULL; StringOutputVisitor *ov; StringInputVisitor *iv; char *str; ov = string_output_visitor_new(false); object_property_get(obj, string_output_get_visitor(ov), - name, errp); + name, &err); + if (err) { + error_propagate(errp, err); + goto out; + } str = string_output_get_string(ov); iv = string_input_visitor_new(str); - visit_type_uint16List(string_input_get_visitor(iv), - list, NULL, errp); + visit_type_uint16List(string_input_get_visitor(iv), NULL, list, errp); g_free(str); - string_output_visitor_cleanup(ov); string_input_visitor_cleanup(iv); +out: + string_output_visitor_cleanup(ov); } void object_property_parse(Object *obj, const char *string, const char *name, Error **errp) { - StringInputVisitor *mi; - mi = string_input_visitor_new(string); - object_property_set(obj, string_input_get_visitor(mi), name, errp); + StringInputVisitor *siv; + siv = string_input_visitor_new(string); + object_property_set(obj, string_input_get_visitor(siv), name, errp); - string_input_visitor_cleanup(mi); + string_input_visitor_cleanup(siv); } char *object_property_print(Object *obj, const char *name, bool human, Error **errp) { - StringOutputVisitor *mo; + StringOutputVisitor *sov; char *string = NULL; Error *local_err = NULL; - mo = string_output_visitor_new(human); - object_property_get(obj, string_output_get_visitor(mo), name, &local_err); + sov = string_output_visitor_new(human); + object_property_get(obj, string_output_get_visitor(sov), name, &local_err); if (local_err) { error_propagate(errp, local_err); goto out; } - string = string_output_get_string(mo); + string = string_output_get_string(sov); out: - string_output_visitor_cleanup(mo); + string_output_visitor_cleanup(sov); return string; } @@ -1190,14 +1336,15 @@ Object *object_get_objects_root(void) return container_get(object_get_root(), "/objects"); } -static void object_get_child_property(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void object_get_child_property(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) { Object *child = opaque; gchar *path; path = object_get_canonical_path(child); - visit_type_str(v, &path, name, errp); + visit_type_str(v, name, &path, errp); g_free(path); } @@ -1259,8 +1406,9 @@ typedef struct { ObjectPropertyLinkFlags flags; } LinkProperty; -static void object_get_link_property(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void object_get_link_property(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) { LinkProperty *lprop = opaque; Object **child = lprop->child; @@ -1268,11 +1416,11 @@ static void object_get_link_property(Object *obj, Visitor *v, void *opaque, if (*child) { path = object_get_canonical_path(*child); - visit_type_str(v, &path, name, errp); + visit_type_str(v, name, &path, errp); g_free(path); } else { path = (gchar *)""; - visit_type_str(v, &path, name, errp); + visit_type_str(v, name, &path, errp); } } @@ -1299,8 +1447,8 @@ static Object *object_resolve_link(Object *obj, const char *name, target = object_resolve_path_type(path, target_type, &ambiguous); if (ambiguous) { - error_set(errp, ERROR_CLASS_GENERIC_ERROR, - "Path '%s' does not uniquely identify an object", path); + error_setg(errp, "Path '%s' does not uniquely identify an object", + path); } else if (!target) { target = object_resolve_path(path, &ambiguous); if (target || ambiguous) { @@ -1316,8 +1464,9 @@ static Object *object_resolve_link(Object *obj, const char *name, return target; } -static void object_set_link_property(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void object_set_link_property(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) { Error *local_err = NULL; LinkProperty *prop = opaque; @@ -1326,7 +1475,7 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque, Object *new_target = NULL; char *path = NULL; - visit_type_str(v, &path, name, &local_err); + visit_type_str(v, name, &path, &local_err); if (!local_err && strcmp(path, "") != 0) { new_target = object_resolve_link(obj, name, path, &local_err); @@ -1422,11 +1571,13 @@ void object_property_add_const_link(Object *obj, const char *name, gchar *object_get_canonical_path_component(Object *obj) { ObjectProperty *prop = NULL; + GHashTableIter iter; g_assert(obj); g_assert(obj->parent != NULL); - QTAILQ_FOREACH(prop, &obj->parent->properties, node) { + g_hash_table_iter_init(&iter, obj->parent->properties); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { if (!object_property_is_child(prop)) { continue; } @@ -1510,11 +1661,13 @@ static Object *object_resolve_partial_path(Object *parent, bool *ambiguous) { Object *obj; + GHashTableIter iter; ObjectProperty *prop; obj = object_resolve_abs_path(parent, parts, typename, 0); - QTAILQ_FOREACH(prop, &parent->properties, node) { + g_hash_table_iter_init(&iter, parent->properties); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { Object *found; if (!object_property_is_child(prop)) { @@ -1576,27 +1729,31 @@ typedef struct StringProperty void (*set)(Object *, const char *, Error **); } StringProperty; -static void property_get_str(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_get_str(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { StringProperty *prop = opaque; char *value; + Error *err = NULL; - value = prop->get(obj, errp); - if (value) { - visit_type_str(v, &value, name, errp); - g_free(value); + value = prop->get(obj, &err); + if (err) { + error_propagate(errp, err); + return; } + + visit_type_str(v, name, &value, errp); + g_free(value); } -static void property_set_str(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_set_str(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { StringProperty *prop = opaque; char *value; Error *local_err = NULL; - visit_type_str(v, &value, name, &local_err); + visit_type_str(v, name, &value, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1635,30 +1792,59 @@ void object_property_add_str(Object *obj, const char *name, } } +void object_class_property_add_str(ObjectClass *klass, const char *name, + char *(*get)(Object *, Error **), + void (*set)(Object *, const char *, + Error **), + Error **errp) +{ + Error *local_err = NULL; + StringProperty *prop = g_malloc0(sizeof(*prop)); + + prop->get = get; + prop->set = set; + + object_class_property_add(klass, name, "string", + get ? property_get_str : NULL, + set ? property_set_str : NULL, + property_release_str, + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } +} + typedef struct BoolProperty { bool (*get)(Object *, Error **); void (*set)(Object *, bool, Error **); } BoolProperty; -static void property_get_bool(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_get_bool(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { BoolProperty *prop = opaque; bool value; + Error *err = NULL; + + value = prop->get(obj, &err); + if (err) { + error_propagate(errp, err); + return; + } - value = prop->get(obj, errp); - visit_type_bool(v, &value, name, errp); + visit_type_bool(v, name, &value, errp); } -static void property_set_bool(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_set_bool(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { BoolProperty *prop = opaque; bool value; Error *local_err = NULL; - visit_type_bool(v, &value, name, &local_err); + visit_type_bool(v, name, &value, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1696,23 +1882,56 @@ void object_property_add_bool(Object *obj, const char *name, } } -static void property_get_enum(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +void object_class_property_add_bool(ObjectClass *klass, const char *name, + bool (*get)(Object *, Error **), + void (*set)(Object *, bool, Error **), + Error **errp) +{ + Error *local_err = NULL; + BoolProperty *prop = g_malloc0(sizeof(*prop)); + + prop->get = get; + prop->set = set; + + object_class_property_add(klass, name, "bool", + get ? property_get_bool : NULL, + set ? property_set_bool : NULL, + property_release_bool, + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } +} + +static void property_get_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { EnumProperty *prop = opaque; int value; + Error *err = NULL; - value = prop->get(obj, errp); - visit_type_enum(v, &value, prop->strings, NULL, name, errp); + value = prop->get(obj, &err); + if (err) { + error_propagate(errp, err); + return; + } + + visit_type_enum(v, name, &value, prop->strings, errp); } -static void property_set_enum(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_set_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { EnumProperty *prop = opaque; int value; + Error *err = NULL; - visit_type_enum(v, &value, prop->strings, NULL, name, errp); + visit_type_enum(v, name, &value, prop->strings, &err); + if (err) { + error_propagate(errp, err); + return; + } prop->set(obj, value, errp); } @@ -1748,12 +1967,37 @@ void object_property_add_enum(Object *obj, const char *name, } } +void object_class_property_add_enum(ObjectClass *klass, const char *name, + const char *typename, + const char * const *strings, + int (*get)(Object *, Error **), + void (*set)(Object *, int, Error **), + Error **errp) +{ + Error *local_err = NULL; + EnumProperty *prop = g_malloc(sizeof(*prop)); + + prop->strings = strings; + prop->get = get; + prop->set = set; + + object_class_property_add(klass, name, typename, + get ? property_get_enum : NULL, + set ? property_set_enum : NULL, + property_release_enum, + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } +} + typedef struct TMProperty { void (*get)(Object *, struct tm *, Error **); } TMProperty; -static void property_get_tm(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_get_tm(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { TMProperty *prop = opaque; Error *err = NULL; @@ -1764,31 +2008,31 @@ static void property_get_tm(Object *obj, Visitor *v, void *opaque, goto out; } - visit_start_struct(v, NULL, "struct tm", name, 0, &err); + visit_start_struct(v, name, NULL, 0, &err); if (err) { goto out; } - visit_type_int32(v, &value.tm_year, "tm_year", &err); + visit_type_int32(v, "tm_year", &value.tm_year, &err); if (err) { goto out_end; } - visit_type_int32(v, &value.tm_mon, "tm_mon", &err); + visit_type_int32(v, "tm_mon", &value.tm_mon, &err); if (err) { goto out_end; } - visit_type_int32(v, &value.tm_mday, "tm_mday", &err); + visit_type_int32(v, "tm_mday", &value.tm_mday, &err); if (err) { goto out_end; } - visit_type_int32(v, &value.tm_hour, "tm_hour", &err); + visit_type_int32(v, "tm_hour", &value.tm_hour, &err); if (err) { goto out_end; } - visit_type_int32(v, &value.tm_min, "tm_min", &err); + visit_type_int32(v, "tm_min", &value.tm_min, &err); if (err) { goto out_end; } - visit_type_int32(v, &value.tm_sec, "tm_sec", &err); + visit_type_int32(v, "tm_sec", &value.tm_sec, &err); if (err) { goto out_end; } @@ -1827,41 +2071,56 @@ void object_property_add_tm(Object *obj, const char *name, } } +void object_class_property_add_tm(ObjectClass *klass, const char *name, + void (*get)(Object *, struct tm *, Error **), + Error **errp) +{ + Error *local_err = NULL; + TMProperty *prop = g_malloc0(sizeof(*prop)); + + prop->get = get; + + object_class_property_add(klass, name, "struct tm", + get ? property_get_tm : NULL, NULL, + property_release_tm, + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } +} + static char *qdev_get_type(Object *obj, Error **errp) { return g_strdup(object_get_typename(obj)); } -static void property_get_uint8_ptr(Object *obj, Visitor *v, - void *opaque, const char *name, - Error **errp) +static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { uint8_t value = *(uint8_t *)opaque; - visit_type_uint8(v, &value, name, errp); + visit_type_uint8(v, name, &value, errp); } -static void property_get_uint16_ptr(Object *obj, Visitor *v, - void *opaque, const char *name, - Error **errp) +static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { uint16_t value = *(uint16_t *)opaque; - visit_type_uint16(v, &value, name, errp); + visit_type_uint16(v, name, &value, errp); } -static void property_get_uint32_ptr(Object *obj, Visitor *v, - void *opaque, const char *name, - Error **errp) +static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { uint32_t value = *(uint32_t *)opaque; - visit_type_uint32(v, &value, name, errp); + visit_type_uint32(v, name, &value, errp); } -static void property_get_uint64_ptr(Object *obj, Visitor *v, - void *opaque, const char *name, - Error **errp) +static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { uint64_t value = *(uint64_t *)opaque; - visit_type_uint64(v, &value, name, errp); + visit_type_uint64(v, name, &value, errp); } void object_property_add_uint8_ptr(Object *obj, const char *name, @@ -1871,6 +2130,13 @@ void object_property_add_uint8_ptr(Object *obj, const char *name, NULL, NULL, (void *)v, errp); } +void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name, + const uint8_t *v, Error **errp) +{ + object_class_property_add(klass, name, "uint8", property_get_uint8_ptr, + NULL, NULL, (void *)v, errp); +} + void object_property_add_uint16_ptr(Object *obj, const char *name, const uint16_t *v, Error **errp) { @@ -1878,6 +2144,13 @@ void object_property_add_uint16_ptr(Object *obj, const char *name, NULL, NULL, (void *)v, errp); } +void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name, + const uint16_t *v, Error **errp) +{ + object_class_property_add(klass, name, "uint16", property_get_uint16_ptr, + NULL, NULL, (void *)v, errp); +} + void object_property_add_uint32_ptr(Object *obj, const char *name, const uint32_t *v, Error **errp) { @@ -1885,6 +2158,13 @@ void object_property_add_uint32_ptr(Object *obj, const char *name, NULL, NULL, (void *)v, errp); } +void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name, + const uint32_t *v, Error **errp) +{ + object_class_property_add(klass, name, "uint32", property_get_uint32_ptr, + NULL, NULL, (void *)v, errp); +} + void object_property_add_uint64_ptr(Object *obj, const char *name, const uint64_t *v, Error **errp) { @@ -1892,21 +2172,28 @@ void object_property_add_uint64_ptr(Object *obj, const char *name, NULL, NULL, (void *)v, errp); } +void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name, + const uint64_t *v, Error **errp) +{ + object_class_property_add(klass, name, "uint64", property_get_uint64_ptr, + NULL, NULL, (void *)v, errp); +} + typedef struct { Object *target_obj; char *target_name; } AliasProperty; -static void property_get_alias(Object *obj, struct Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_get_alias(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { AliasProperty *prop = opaque; object_property_get(prop->target_obj, v, prop->target_name, errp); } -static void property_set_alias(Object *obj, struct Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_set_alias(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { AliasProperty *prop = opaque; @@ -1989,6 +2276,23 @@ void object_property_set_description(Object *obj, const char *name, op->description = g_strdup(description); } +void object_class_property_set_description(ObjectClass *klass, + const char *name, + const char *description, + Error **errp) +{ + ObjectProperty *op; + + op = g_hash_table_lookup(klass->properties, name); + if (!op) { + error_setg(errp, "Property '.%s' not found", name); + return; + } + + g_free(op->description); + op->description = g_strdup(description); +} + static void object_instance_init(Object *obj) { object_property_add_str(obj, "type", qdev_get_type, NULL, NULL); diff --git a/qemu/qom/object_interfaces.c b/qemu/qom/object_interfaces.c index a66cd6026..393189024 100644 --- a/qemu/qom/object_interfaces.c +++ b/qemu/qom/object_interfaces.c @@ -1,5 +1,10 @@ +#include "qemu/osdep.h" +#include "qapi/error.h" #include "qom/object_interfaces.h" #include "qemu/module.h" +#include "qapi-visit.h" +#include "qapi/qmp-output-visitor.h" +#include "qapi/opts-visitor.h" void user_creatable_complete(Object *obj, Error **errp) { @@ -30,6 +35,179 @@ bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp) } } + +Object *user_creatable_add(const QDict *qdict, + Visitor *v, Error **errp) +{ + char *type = NULL; + char *id = NULL; + Object *obj = NULL; + Error *local_err = NULL, *end_err = NULL; + QDict *pdict; + + pdict = qdict_clone_shallow(qdict); + + visit_start_struct(v, NULL, NULL, 0, &local_err); + if (local_err) { + goto out; + } + + qdict_del(pdict, "qom-type"); + visit_type_str(v, "qom-type", &type, &local_err); + if (local_err) { + goto out_visit; + } + + qdict_del(pdict, "id"); + visit_type_str(v, "id", &id, &local_err); + if (local_err) { + goto out_visit; + } + + obj = user_creatable_add_type(type, id, pdict, v, &local_err); + if (local_err) { + goto out_visit; + } + + out_visit: + visit_end_struct(v, &end_err); + if (end_err) { + error_propagate(&local_err, end_err); + if (obj) { + user_creatable_del(id, NULL); + } + goto out; + } + +out: + QDECREF(pdict); + g_free(id); + g_free(type); + if (local_err) { + error_propagate(errp, local_err); + object_unref(obj); + return NULL; + } + return obj; +} + + +Object *user_creatable_add_type(const char *type, const char *id, + const QDict *qdict, + Visitor *v, Error **errp) +{ + Object *obj; + ObjectClass *klass; + const QDictEntry *e; + Error *local_err = NULL; + + klass = object_class_by_name(type); + if (!klass) { + error_setg(errp, "invalid object type: %s", type); + return NULL; + } + + if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) { + error_setg(errp, "object type '%s' isn't supported by object-add", + type); + return NULL; + } + + if (object_class_is_abstract(klass)) { + error_setg(errp, "object type '%s' is abstract", type); + return NULL; + } + + obj = object_new(type); + if (qdict) { + for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { + object_property_set(obj, v, e->key, &local_err); + if (local_err) { + goto out; + } + } + } + + object_property_add_child(object_get_objects_root(), + id, obj, &local_err); + if (local_err) { + goto out; + } + + user_creatable_complete(obj, &local_err); + if (local_err) { + object_property_del(object_get_objects_root(), + id, &error_abort); + goto out; + } +out: + if (local_err) { + error_propagate(errp, local_err); + object_unref(obj); + return NULL; + } + return obj; +} + + +Object *user_creatable_add_opts(QemuOpts *opts, Error **errp) +{ + OptsVisitor *ov; + QDict *pdict; + Object *obj = NULL; + + ov = opts_visitor_new(opts); + pdict = qemu_opts_to_qdict(opts, NULL); + + obj = user_creatable_add(pdict, opts_get_visitor(ov), errp); + opts_visitor_cleanup(ov); + QDECREF(pdict); + return obj; +} + + +int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp) +{ + bool (*type_predicate)(const char *) = opaque; + Object *obj = NULL; + Error *err = NULL; + const char *type; + + type = qemu_opt_get(opts, "qom-type"); + if (type && type_predicate && + !type_predicate(type)) { + return 0; + } + + obj = user_creatable_add_opts(opts, &err); + if (!obj) { + error_report_err(err); + return -1; + } + object_unref(obj); + return 0; +} + + +void user_creatable_del(const char *id, Error **errp) +{ + Object *container; + Object *obj; + + container = object_get_objects_root(); + obj = object_resolve_path_component(container, id); + if (!obj) { + error_setg(errp, "object '%s' not found", id); + return; + } + + if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) { + error_setg(errp, "object '%s' is in use, can not be deleted", id); + return; + } + object_unparent(obj); +} + static void register_types(void) { static const TypeInfo uc_interface_info = { diff --git a/qemu/qom/qom-qobject.c b/qemu/qom/qom-qobject.c index 6384b8e98..e6b17c1f1 100644 --- a/qemu/qom/qom-qobject.c +++ b/qemu/qom/qom-qobject.c @@ -9,6 +9,8 @@ * See the COPYING file in the top-level directory. */ +#include "qemu/osdep.h" +#include "qapi/error.h" #include "qemu-common.h" #include "qom/object.h" #include "qom/qom-qobject.h" @@ -19,11 +21,11 @@ void object_property_set_qobject(Object *obj, QObject *value, const char *name, Error **errp) { - QmpInputVisitor *mi; - mi = qmp_input_visitor_new(value); - object_property_set(obj, qmp_input_get_visitor(mi), name, errp); + QmpInputVisitor *qiv; + qiv = qmp_input_visitor_new(value); + object_property_set(obj, qmp_input_get_visitor(qiv), name, errp); - qmp_input_visitor_cleanup(mi); + qmp_input_visitor_cleanup(qiv); } QObject *object_property_get_qobject(Object *obj, const char *name, @@ -31,14 +33,14 @@ QObject *object_property_get_qobject(Object *obj, const char *name, { QObject *ret = NULL; Error *local_err = NULL; - QmpOutputVisitor *mo; + QmpOutputVisitor *qov; - mo = qmp_output_visitor_new(); - object_property_get(obj, qmp_output_get_visitor(mo), name, &local_err); + qov = qmp_output_visitor_new(); + object_property_get(obj, qmp_output_get_visitor(qov), name, &local_err); if (!local_err) { - ret = qmp_output_get_qobject(mo); + ret = qmp_output_get_qobject(qov); } error_propagate(errp, local_err); - qmp_output_visitor_cleanup(mo); + qmp_output_visitor_cleanup(qov); return ret; } |