[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC] qapi: New command query-mtree
From: |
Paolo Bonzini |
Subject: |
Re: [Qemu-devel] [RFC] qapi: New command query-mtree |
Date: |
Thu, 21 Aug 2014 11:06:51 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.7.0 |
Il 20/08/2014 19:46, Marc Marí ha scritto:
> Add command query-mtree to get the memory tree of the guest.
>
> As we were looking for a flexible solution on accessing the guest memory from
> qtests, Stefan came with the idea to implement this new qmp command.
>
> This way, the result can be parsed, and the RAM direction extracted, so only
> a generic qtest malloc is necessary and not one per machine, as it is
> implemented at the moment (malloc-pc uses fw_cfg).
>
> The actual output is this: http://pastebin.com/nHAH9Jie
> Which corresponds to this info mtree: http://pastebin.com/B5vw8DDf
I don't like this idea very much. libqos should be using the real
memory map information from the machine. In the case of x86, that means
fw_cfg; in the case of ARM, that would mean using the device tree.
Getting the information from an out-of-band channel (such as QMP) is
basically cheating. :)
If you had a memory map abstraction in libqos, malloc could be generic.
Perhaps you can start doing that for PC?
Paolo
> Signed-off-by: Marc Marí <address@hidden>
> ---
> memory.c | 148
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> qapi-schema.json | 68 +++++++++++++++++++++++++
> qmp-commands.hx | 19 +++++++
> 3 files changed, 235 insertions(+)
>
> diff --git a/memory.c b/memory.c
> index 42317a2..6de6fa7 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -20,6 +20,7 @@
> #include "qemu/bitops.h"
> #include "qom/object.h"
> #include "trace.h"
> +#include "qmp-commands.h"
> #include <assert.h>
>
> #include "exec/memory-internal.h"
> @@ -2100,6 +2101,153 @@ void mtree_info(fprintf_function mon_printf, void *f)
> }
> }
>
> +static MemRegion *qmp_mtree_mr(const MemoryRegion *mr, hwaddr base,
> + MemoryRegionListHead *alias_queue)
> +{
> + MemoryRegionList *new_ml, *ml, *next_ml;
> + MemoryRegionListHead submr_print_queue;
> + MemRegionList *cur_item = NULL, *subregion;
> + MemRegion *region = NULL;
> + const MemoryRegion *submr;
> +
> + if (!mr || !mr->enabled) {
> + return region;
> + }
> +
> + region = g_malloc0(sizeof(*region));
> +
> + if (mr->alias) {
> + MemoryRegionList *ml;
> + bool found = false;
> +
> + /* check if the alias is already in the queue */
> + QTAILQ_FOREACH(ml, alias_queue, queue) {
> + if (ml->mr == mr->alias) {
> + found = true;
> + }
> + }
> +
> + if (!found) {
> + ml = g_new(MemoryRegionList, 1);
> + ml->mr = mr->alias;
> + QTAILQ_INSERT_TAIL(alias_queue, ml, queue);
> + }
> +
> + region->base = base+mr->addr;
> + region->size = int128_get64(int128_sub(mr->size, int128_one()));
> + region->prio = mr->priority;
> + region->read = mr->romd_mode;
> + region->write = !mr->readonly && !(mr->rom_device && mr->romd_mode);
> + region->ram = mr->ram;
> + region->name = g_strdup(memory_region_name(mr));
> + region->has_alias = true;
> + region->alias = g_strdup(memory_region_name(mr->alias));
> + } else {
> + region->base = base+mr->addr;
> + region->size = int128_get64(int128_sub(mr->size, int128_one()));
> + region->prio = mr->priority;
> + region->read = mr->romd_mode;
> + region->write = !mr->readonly && !(mr->rom_device && mr->romd_mode);
> + region->ram = mr->ram;
> + region->name = g_strdup(memory_region_name(mr));
> + region->has_alias = false;
> + }
> +
> + QTAILQ_INIT(&submr_print_queue);
> +
> + QTAILQ_FOREACH(submr, &mr->subregions, subregions_link) {
> + new_ml = g_new(MemoryRegionList, 1);
> + new_ml->mr = submr;
> + QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
> + if (new_ml->mr->addr < ml->mr->addr ||
> + (new_ml->mr->addr == ml->mr->addr &&
> + new_ml->mr->priority > ml->mr->priority)) {
> + QTAILQ_INSERT_BEFORE(ml, new_ml, queue);
> + new_ml = NULL;
> + break;
> + }
> + }
> + if (new_ml) {
> + QTAILQ_INSERT_TAIL(&submr_print_queue, new_ml, queue);
> + }
> + }
> +
> + QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
> + subregion = g_malloc0(sizeof(*subregion));
> + subregion->value = qmp_mtree_mr(ml->mr, base + mr->addr,
> alias_queue);
> +
> + if (subregion->value != NULL) {
> + if (!cur_item) {
> + region->submr = cur_item = subregion;
> + } else {
> + cur_item->next = subregion;
> + cur_item = subregion;
> + }
> + } else {
> + g_free(subregion);
> + }
> + }
> +
> + region->has_submr = (region->submr != NULL);
> +
> + QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, queue, next_ml) {
> + g_free(ml);
> + }
> +
> + return region;
> +}
> +
> +MemTree *qmp_query_mtree(Error **errp)
> +{
> + MemoryRegionListHead ml_head;
> + MemoryRegionList *ml, *ml2;
> + AddressSpace *as;
> + AddrSpaceList *head = NULL, *cur_item = NULL, *space;
> + MemTree *mt = g_malloc0(sizeof(*mt));
> +
> + QTAILQ_INIT(&ml_head);
> +
> + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
> + space = g_malloc0(sizeof(*space));
> + space->value = g_malloc0(sizeof(*space->value));
> + space->value->name = g_strdup(as->name);
> + space->value->mem = qmp_mtree_mr(as->root, 0, &ml_head);
> +
> + if (!cur_item) {
> + head = cur_item = space;
> + } else {
> + cur_item->next = space;
> + cur_item = space;
> + }
> + }
> +
> + mt->spaces = head;
> + head = NULL;
> + cur_item = NULL;
> +
> + QTAILQ_FOREACH(ml, &ml_head, queue) {
> + space = g_malloc0(sizeof(*space));
> + space->value = g_malloc0(sizeof(*space->value));
> + space->value->name = g_strdup(memory_region_name(ml->mr));
> + space->value->mem = qmp_mtree_mr(ml->mr, 0, &ml_head);
> +
> + if (!cur_item) {
> + head = cur_item = space;
> + } else {
> + cur_item->next = space;
> + cur_item = space;
> + }
> + }
> +
> + mt->aliases = head;
> +
> + QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) {
> + g_free(ml);
> + }
> +
> + return mt;
> +}
> +
> static const TypeInfo memory_region_info = {
> .parent = TYPE_OBJECT,
> .name = TYPE_MEMORY_REGION,
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 341f417..bc35bd9 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3481,3 +3481,71 @@
> # Since: 2.1
> ##
> { 'command': 'rtc-reset-reinjection' }
> +
> +##
> +# @MemRegion:
> +#
> +# Information about a memory region
> +#
> +# @base: base address
> +#
> +# @size: size
> +#
> +# @prio: priority
> +#
> +# @read: read permitted
> +#
> +# @write: write permitted
> +#
> +# @ram: RAM region
> +#
> +# @name: name of the region
> +#
> +# @alias: #optional alias of this region
> +#
> +# @submr: #optional submemory regions of this region
> +#
> +# Since: 2.x
> +##
> +{ 'type': 'MemRegion',
> + 'data': {'base': 'uint64', 'size': 'uint64', 'prio': 'uint32', 'read':
> 'bool',
> + 'write': 'bool', 'ram': 'bool', 'name': 'str',
> + '*alias': 'str', '*submr': ['MemRegion']} }
> +
> +##
> +# @AddrSpace:
> +#
> +# An address space of the system
> +#
> +# @name: name of the address space
> +#
> +# @mem: a list of memory regions in the address space
> +#
> +# Since: 2.x
> +##
> +{ 'type': 'AddrSpace', 'data': {'name': 'str', 'mem': 'MemRegion'} }
> +
> +##
> +# @MemTree:
> +#
> +# Memory tree of the system
> +#
> +# @spaces: Address spaces of the system
> +#
> +# @aliases: Aliased memory regions
> +#
> +# Since: 2.x
> +##
> +{ 'type': 'MemTree', 'data': {'spaces': ['AddrSpace'],
> + 'aliases': ['AddrSpace']} }
> +
> +##
> +# @query-mtree:
> +#
> +# Return the memory distribution of the guest
> +#
> +# Returns: a list of @AddrSpace
> +#
> +# Since: 2.x
> +##
> +{ 'command': 'query-mtree', 'returns': 'MemTree' }
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 4be4765..22f91b0 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -3755,3 +3755,22 @@ Example:
> <- { "return": {} }
>
> EQMP
> + {
> + .name = "query-mtree",
> + .args_type = "",
> + .mhandler.cmd_new = qmp_marshal_input_query_mtree,
> + },
> +SQMP
> +query-mtree
> +---------
> +
> +Memory tree.
> +
> +The returned value is a json-array of the memory distribution of the system.
> +Each address space is represented by a json-object, which has a name, and a
> +json-array of all memory regions that contain. Each memory region is
> +represented by a json-object.
> +
> +(Missing schema and example)
> +
> +EQMP
>