Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/afaerber/tags/qom-devices-for-p…
Browse files Browse the repository at this point in the history
…eter' into staging

QOM infrastructure fixes and device conversions

* Conversion of cadence_uart to QOM realize
* qom-tree QMP script
* qom-list and qom-set HMP commands to match their QMP counterparts
* Basic qom-tree HMP command
* Cleanups for /machine QOM composition tree

# gpg: Signature made Tue Mar 17 15:02:57 2015 GMT using RSA key ID 3E7E013F
# gpg: Good signature from "Andreas Färber <afaerber@suse.de>"
# gpg:                 aka "Andreas Färber <afaerber@suse.com>"

* remotes/afaerber/tags/qom-devices-for-peter:
  qdev: Move owner-less IRQs to /machine/unattached
  memory: Move owner-less MemoryRegions to /machine/unattached
  qom: Implement info qom-tree HMP command
  qom: Implement qom-set HMP command
  qom: Implement qom-list HMP command
  scripts: Add qom-tree script
  cadence_uart: Convert to QOM realize()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Mar 17, 2015
2 parents 5a49928 + 88950ee commit 1a87e52
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 14 deletions.
28 changes: 28 additions & 0 deletions hmp-commands.hx
Expand Up @@ -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

{
Expand Down Expand Up @@ -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
Expand Down
47 changes: 47 additions & 0 deletions hmp.c
Expand Up @@ -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);
}
2 changes: 2 additions & 0 deletions hmp.h
Expand Up @@ -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);
Expand Down
26 changes: 15 additions & 11 deletions hw/char/cadence_uart.c
Expand Up @@ -476,27 +476,31 @@ 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();

if (s->chr) {
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)
Expand Down Expand Up @@ -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;
}
Expand All @@ -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,
};

Expand Down
5 changes: 3 additions & 2 deletions hw/core/qdev.c
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions include/monitor/qdev.h
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion memory.c
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions monitor.c
Expand Up @@ -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 = "",
Expand Down
57 changes: 57 additions & 0 deletions qdev-monitor.c
Expand Up @@ -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;
Expand Down
70 changes: 70 additions & 0 deletions 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')

0 comments on commit 1a87e52

Please sign in to comment.