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:
commit
1a87e52770
@ -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
47
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);
|
||||
}
|
||||
|
2
hmp.h
2
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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
2
memory.c
2
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);
|
||||
|
@ -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 = "",
|
||||
|
@ -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
70
scripts/qmp/qom-tree
Executable 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')
|
Loading…
Reference in New Issue
Block a user