diff --git a/hmp-commands.hx b/hmp-commands.hx index 9c1e849859..328709dc8d 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1671,6 +1671,32 @@ ETEXI STEXI @item cpu-add @var{id} Add CPU with id @var{id} +ETEXI + + { + .name = "qom-list", + .args_type = "path:s?", + .params = "path", + .help = "list QOM properties", + .mhandler.cmd = hmp_qom_list, + }, + +STEXI +@item qom-list [@var{path}] +Print QOM properties of object at location @var{path} +ETEXI + + { + .name = "qom-set", + .args_type = "path:s,property:s,value:s", + .params = "path property value", + .help = "set QOM property", + .mhandler.cmd = hmp_qom_set, + }, + +STEXI +@item qom-set @var{path} @var{property} @var{value} +Set QOM property @var{property} of object at location @var{path} to value @var{value} ETEXI { @@ -1756,6 +1782,8 @@ show balloon information show device tree @item info qdm show qdev device model list +@item info qom-tree +show object composition tree @item info roms show roms @item info tpm diff --git a/hmp.c b/hmp.c index f6cde86b93..ad1beba80d 100644 --- a/hmp.c +++ b/hmp.c @@ -1866,3 +1866,50 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict) qapi_free_MemoryDeviceInfoList(info_list); } + +void hmp_qom_list(Monitor *mon, const QDict *qdict) +{ + const char *path = qdict_get_try_str(qdict, "path"); + ObjectPropertyInfoList *list; + Error *err = NULL; + + if (path == NULL) { + monitor_printf(mon, "/\n"); + return; + } + + list = qmp_qom_list(path, &err); + if (err == NULL) { + ObjectPropertyInfoList *start = list; + while (list != NULL) { + ObjectPropertyInfo *value = list->value; + + monitor_printf(mon, "%s (%s)\n", + value->name, value->type); + list = list->next; + } + qapi_free_ObjectPropertyInfoList(start); + } + hmp_handle_error(mon, &err); +} + +void hmp_qom_set(Monitor *mon, const QDict *qdict) +{ + const char *path = qdict_get_str(qdict, "path"); + const char *property = qdict_get_str(qdict, "property"); + const char *value = qdict_get_str(qdict, "value"); + Error *err = NULL; + bool ambiguous = false; + Object *obj; + + obj = object_resolve_path(path, &ambiguous); + if (obj == NULL) { + error_set(&err, QERR_DEVICE_NOT_FOUND, path); + } else { + if (ambiguous) { + monitor_printf(mon, "Warning: Path '%s' is ambiguous\n", path); + } + object_property_parse(obj, value, property, &err); + } + hmp_handle_error(mon, &err); +} diff --git a/hmp.h b/hmp.h index 371f8d45cd..2b9308be7c 100644 --- a/hmp.h +++ b/hmp.h @@ -96,6 +96,8 @@ void hmp_object_add(Monitor *mon, const QDict *qdict); void hmp_object_del(Monitor *mon, const QDict *qdict); void hmp_info_memdev(Monitor *mon, const QDict *qdict); void hmp_info_memory_devices(Monitor *mon, const QDict *qdict); +void hmp_qom_list(Monitor *mon, const QDict *qdict); +void hmp_qom_set(Monitor *mon, const QDict *qdict); void object_add_completion(ReadLineState *rs, int nb_args, const char *str); void object_del_completion(ReadLineState *rs, int nb_args, const char *str); void device_add_completion(ReadLineState *rs, int nb_args, const char *str); diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index 7044b357dc..a5dc2a4366 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -476,18 +476,12 @@ static void cadence_uart_reset(DeviceState *dev) uart_update_status(s); } -static int cadence_uart_init(SysBusDevice *dev) +static void cadence_uart_realize(DeviceState *dev, Error **errp) { UartState *s = CADENCE_UART(dev); - memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s, "uart", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - sysbus_init_irq(dev, &s->irq); - s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL, - (QEMUTimerCB *)fifo_trigger_update, s); - - s->char_tx_time = (get_ticks_per_sec() / 9600) * 10; + fifo_trigger_update, s); s->chr = qemu_char_get_next_serial(); @@ -495,8 +489,18 @@ static int cadence_uart_init(SysBusDevice *dev) qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive, uart_event, s); } +} - return 0; +static void cadence_uart_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + UartState *s = CADENCE_UART(obj); + + memory_region_init_io(&s->iomem, obj, &uart_ops, s, "uart", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + + s->char_tx_time = (get_ticks_per_sec() / 9600) * 10; } static int cadence_uart_post_load(void *opaque, int version_id) @@ -528,9 +532,8 @@ static const VMStateDescription vmstate_cadence_uart = { static void cadence_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); - sdc->init = cadence_uart_init; + dc->realize = cadence_uart_realize; dc->vmsd = &vmstate_cadence_uart; dc->reset = cadence_uart_reset; } @@ -539,6 +542,7 @@ static const TypeInfo cadence_uart_info = { .name = TYPE_CADENCE_UART, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(UartState), + .instance_init = cadence_uart_init, .class_init = cadence_uart_class_init, }; diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 6be58669f7..6e6a65d49b 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -501,8 +501,9 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, * with an error without doing anything. If it has none, it will * never fail. So we can just call it with a NULL Error pointer. */ - object_property_add_child(qdev_get_machine(), "non-qdev-gpio[*]", - OBJECT(pin), NULL); + object_property_add_child(container_get(qdev_get_machine(), + "/unattached"), + "non-qdev-gpio[*]", OBJECT(pin), NULL); } object_property_set_link(OBJECT(dev), OBJECT(pin), propname, &error_abort); g_free(propname); diff --git a/include/monitor/qdev.h b/include/monitor/qdev.h index 5eb4a1171e..719075283c 100644 --- a/include/monitor/qdev.h +++ b/include/monitor/qdev.h @@ -8,6 +8,7 @@ void hmp_info_qtree(Monitor *mon, const QDict *qdict); void hmp_info_qdm(Monitor *mon, const QDict *qdict); +void hmp_info_qom_tree(Monitor *mon, const QDict *dict); int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data); int qdev_device_help(QemuOpts *opts); DeviceState *qdev_device_add(QemuOpts *opts); diff --git a/memory.c b/memory.c index 20f6d9eeac..ee3f2a8a95 100644 --- a/memory.c +++ b/memory.c @@ -868,7 +868,7 @@ void memory_region_init(MemoryRegion *mr, uint64_t size) { if (!owner) { - owner = qdev_get_machine(); + owner = container_get(qdev_get_machine(), "/unattached"); } object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION); diff --git a/monitor.c b/monitor.c index 8b703f97be..42116a942e 100644 --- a/monitor.c +++ b/monitor.c @@ -2889,6 +2889,13 @@ static mon_cmd_t info_cmds[] = { .help = "show qdev device model list", .mhandler.cmd = hmp_info_qdm, }, + { + .name = "qom-tree", + .args_type = "path:s?", + .params = "[path]", + .help = "show QOM composition tree", + .mhandler.cmd = hmp_info_qom_tree, + }, { .name = "roms", .args_type = "", diff --git a/qdev-monitor.c b/qdev-monitor.c index 5d30ac534c..1d87f573e8 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -678,6 +678,63 @@ void hmp_info_qdm(Monitor *mon, const QDict *qdict) qdev_print_devinfos(true); } +typedef struct QOMCompositionState { + Monitor *mon; + int indent; +} QOMCompositionState; + +static void print_qom_composition(Monitor *mon, Object *obj, int indent); + +static int print_qom_composition_child(Object *obj, void *opaque) +{ + QOMCompositionState *s = opaque; + + print_qom_composition(s->mon, obj, s->indent); + + return 0; +} + +static void print_qom_composition(Monitor *mon, Object *obj, int indent) +{ + QOMCompositionState s = { + .mon = mon, + .indent = indent + 2, + }; + char *name; + + if (obj == object_get_root()) { + name = g_strdup(""); + } else { + name = object_get_canonical_path_component(obj); + } + monitor_printf(mon, "%*s/%s (%s)\n", indent, "", name, + object_get_typename(obj)); + g_free(name); + object_child_foreach(obj, print_qom_composition_child, &s); +} + +void hmp_info_qom_tree(Monitor *mon, const QDict *dict) +{ + const char *path = qdict_get_try_str(dict, "path"); + Object *obj; + bool ambiguous = false; + + if (path) { + obj = object_resolve_path(path, &ambiguous); + if (!obj) { + monitor_printf(mon, "Path '%s' could not be resolved.\n", path); + return; + } + if (ambiguous) { + monitor_printf(mon, "Warning: Path '%s' is ambiguous.\n", path); + return; + } + } else { + obj = qdev_get_machine(); + } + print_qom_composition(mon, obj, 0); +} + int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data) { Error *local_err = NULL; diff --git a/scripts/qmp/qom-tree b/scripts/qmp/qom-tree new file mode 100755 index 0000000000..aea11d4b1a --- /dev/null +++ b/scripts/qmp/qom-tree @@ -0,0 +1,70 @@ +#!/usr/bin/python +## +# QEMU Object Model test tools +# +# Copyright IBM, Corp. 2011 +# Copyright (c) 2013 SUSE LINUX Products GmbH +# +# Authors: +# Anthony Liguori +# Andreas Faerber +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. See +# the COPYING file in the top-level directory. +## + +import sys +import os +from qmp import QEMUMonitorProtocol + +cmd, args = sys.argv[0], sys.argv[1:] +socket_path = None +path = None +prop = None + +def usage(): + return '''environment variables: + QMP_SOCKET= +usage: + %s [-h] [-s ] [] +''' % cmd + +def usage_error(error_msg = "unspecified error"): + sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg)) + exit(1) + +if len(args) > 0: + if args[0] == "-h": + print usage() + exit(0); + elif args[0] == "-s": + try: + socket_path = args[1] + except: + usage_error("missing argument: QMP socket path or address"); + args = args[2:] + +if not socket_path: + if os.environ.has_key('QMP_SOCKET'): + socket_path = os.environ['QMP_SOCKET'] + else: + usage_error("no QMP socket path or address given"); + +srv = QEMUMonitorProtocol(socket_path) +srv.connect() + +def list_node(path): + print '%s' % path + items = srv.command('qom-list', path=path) + for item in items: + if not item['type'].startswith('child<'): + try: + print ' %s: %s (%s)' % (item['name'], srv.command('qom-get', path=path, property=item['name']), item['type']) + except: + print ' %s: (%s)' % (item['name'], item['type']) + print '' + for item in items: + if item['type'].startswith('child<'): + list_node(path + '/' + item['name']) + +list_node('/machine')