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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABAgAGBQJVCEIhAAoJEPou0S0+fgE/pswP/jJBPRXpE70MNpRr34Q3SloS
 ILmFbRGeodVvb/QgJq8p3xjBH56K9A0Pxz6yGYv0K57qU+mjogAN50zmGGa+pAQ8
 1hkV158aGQQVinOb6ILq9BObHXiqgKXqyLboIBORU+IgtmluVYSKyCP3MQtwOvKn
 L5DXETAj4NVPvaHChxQkZnQasWo5+BreC84nq9BCnBZPr9OGpI5zscrkafBY5TLl
 2OW35mSID2gu60aULWOLT7FYnkUJB8xqBoBdP+NhYRDSlmkNIofyKoypv0e4bNtL
 Sfmj3oMjxLfoShZLUaQRjxLyzhMUawf45RBJhlOGTlCkRn64K7H3HsI5LA2j3XNb
 XgJacvxX0SUr+Wj6w19nwaR1absI+BCPnF2k0dvFR6SsCu+p0S9DjIYq2BT2bR+x
 rl0akkdrRALADPDDhdYTOKzfHSzezWJMyLgcur/ytuRezruVSY4Dzsp8MWvWCM57
 ytZIuz9Jiu9+c2pY4IKvT6mOy/Zk3+ZQaczjzbGXXp+ZsM0UUW0P1aBIib8zsT22
 5Wvc3olt+she4fH6G/6nsWJEebXOr6tCTK5JDiTher8FIRskGgqniDRsIkCU88ml
 L432FvroRQDT9JnDrNvrw1dg95Gt2r+mTL6AVUSYUaxusRoU7rUHIBqOTl77+nFa
 8gL4dtjQLN4sP5tuSESK
 =o/sw
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/afaerber/tags/qom-devices-for-peter' 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>
This commit is contained in:
Peter Maydell 2015-03-17 15:23:23 +00:00
commit 1a87e52770
10 changed files with 231 additions and 14 deletions

View File

@ -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

47
hmp.c
View File

@ -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
hmp.h
View File

@ -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);

View File

@ -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,
};

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 = "",

View File

@ -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;

70
scripts/qmp/qom-tree Executable file
View File

@ -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')