summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hmp-commands.hx28
-rw-r--r--hmp.c47
-rw-r--r--hmp.h2
-rw-r--r--hw/char/cadence_uart.c26
-rw-r--r--hw/core/qdev.c5
-rw-r--r--include/monitor/qdev.h1
-rw-r--r--memory.c2
-rw-r--r--monitor.c7
-rw-r--r--qdev-monitor.c57
-rwxr-xr-xscripts/qmp/qom-tree70
10 files changed, 231 insertions, 14 deletions
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 9c1e849859..328709dc8d 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1674,6 +1674,32 @@ 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
+
+    {
         .name       = "info",
         .args_type  = "item:s?",
         .params     = "[subcommand]",
@@ -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
@@ -2890,6 +2890,13 @@ static mon_cmd_t info_cmds[] = {
         .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  = "",
         .params     = "",
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   <aliguori@amazon.com>
+#  Andreas Faerber   <afaerber@suse.de>
+#
+# 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=<path | addr:port>
+usage:
+    %s [-h] [-s <QMP socket path | addr:port>] [<path>]
+''' % 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: <EXCEPTION> (%s)' % (item['name'], item['type'])
+    print ''
+    for item in items:
+        if item['type'].startswith('child<'):
+            list_node(path + '/' + item['name'])
+
+list_node('/machine')