hmp: Print if memory section is registered with an accelerator
This adds an accelerator name to the "into mtree -f" to tell the user if a particular memory section is registered with the accelerator; the primary user for this is KVM and such information is useful for debugging purposes. This adds a has_memory() callback to the accelerator class allowing any accelerator to have a label in that memory tree dump. Since memory sections are passed to memory listeners and get registered in accelerators (rather than memory regions), this only prints new labels for flatviews attached to the system address space. An example: Root memory region: system 0000000000000000-0000002fffffffff (prio 0, ram): /objects/mem0 kvm 0000003000000000-0000005fffffffff (prio 0, ram): /objects/mem1 kvm 0000200000000020-000020000000003f (prio 1, i/o): virtio-pci 0000200080000000-000020008000003f (prio 0, i/o): capabilities Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Message-Id: <20190614015237.82463-1-aik@ozlabs.ru> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
2f950b1e44
commit
8072aae377
@ -111,6 +111,13 @@ struct KVMState
|
||||
/* memory encryption */
|
||||
void *memcrypt_handle;
|
||||
int (*memcrypt_encrypt_data)(void *handle, uint8_t *ptr, uint64_t len);
|
||||
|
||||
/* For "info mtree -f" to tell if an MR is registered in KVM */
|
||||
int nr_as;
|
||||
struct KVMAs {
|
||||
KVMMemoryListener *ml;
|
||||
AddressSpace *as;
|
||||
} *as;
|
||||
};
|
||||
|
||||
KVMState *kvm_state;
|
||||
@ -1159,6 +1166,14 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
|
||||
kml->listener.priority = 10;
|
||||
|
||||
memory_listener_register(&kml->listener, as);
|
||||
|
||||
for (i = 0; i < s->nr_as; ++i) {
|
||||
if (!s->as[i].as) {
|
||||
s->as[i].as = as;
|
||||
s->as[i].ml = kml;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static MemoryListener kvm_io_listener = {
|
||||
@ -1809,6 +1824,12 @@ static int kvm_init(MachineState *ms)
|
||||
s->nr_slots = 32;
|
||||
}
|
||||
|
||||
s->nr_as = kvm_check_extension(s, KVM_CAP_MULTI_ADDRESS_SPACE);
|
||||
if (s->nr_as <= 1) {
|
||||
s->nr_as = 1;
|
||||
}
|
||||
s->as = g_new0(struct KVMAs, s->nr_as);
|
||||
|
||||
kvm_type = qemu_opt_get(qemu_get_machine_opts(), "kvm-type");
|
||||
if (mc->kvm_type) {
|
||||
type = mc->kvm_type(ms, kvm_type);
|
||||
@ -2828,11 +2849,28 @@ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target)
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool kvm_accel_has_memory(MachineState *ms, AddressSpace *as,
|
||||
hwaddr start_addr, hwaddr size)
|
||||
{
|
||||
KVMState *kvm = KVM_STATE(ms->accelerator);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < kvm->nr_as; ++i) {
|
||||
if (kvm->as[i].as == as && kvm->as[i].ml) {
|
||||
return NULL != kvm_lookup_matching_slot(kvm->as[i].ml,
|
||||
start_addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void kvm_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelClass *ac = ACCEL_CLASS(oc);
|
||||
ac->name = "KVM";
|
||||
ac->init_machine = kvm_init;
|
||||
ac->has_memory = kvm_accel_has_memory;
|
||||
ac->allowed = &kvm_allowed;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "qom/object.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "exec/hwaddr.h"
|
||||
|
||||
typedef struct AccelState {
|
||||
/*< private >*/
|
||||
@ -39,6 +40,8 @@ typedef struct AccelClass {
|
||||
const char *name;
|
||||
int (*init_machine)(MachineState *ms);
|
||||
void (*setup_post)(MachineState *ms, AccelState *accel);
|
||||
bool (*has_memory)(MachineState *ms, AddressSpace *as,
|
||||
hwaddr start_addr, hwaddr size);
|
||||
bool *allowed;
|
||||
/*
|
||||
* Array of global properties that would be applied when specific
|
||||
|
22
memory.c
22
memory.c
@ -30,7 +30,9 @@
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/accel.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/boards.h"
|
||||
#include "migration/vmstate.h"
|
||||
|
||||
//#define DEBUG_UNASSIGNED
|
||||
@ -2999,6 +3001,8 @@ struct FlatViewInfo {
|
||||
int counter;
|
||||
bool dispatch_tree;
|
||||
bool owner;
|
||||
AccelClass *ac;
|
||||
const char *ac_name;
|
||||
};
|
||||
|
||||
static void mtree_print_flatview(gpointer key, gpointer value,
|
||||
@ -3061,6 +3065,17 @@ static void mtree_print_flatview(gpointer key, gpointer value,
|
||||
if (fvi->owner) {
|
||||
mtree_print_mr_owner(mr);
|
||||
}
|
||||
|
||||
if (fvi->ac) {
|
||||
for (i = 0; i < fv_address_spaces->len; ++i) {
|
||||
as = g_array_index(fv_address_spaces, AddressSpace*, i);
|
||||
if (fvi->ac->has_memory(current_machine, as,
|
||||
int128_get64(range->addr.start),
|
||||
MR_SIZE(range->addr.size) + 1)) {
|
||||
qemu_printf(" %s", fvi->ac_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
qemu_printf("\n");
|
||||
range++;
|
||||
}
|
||||
@ -3101,6 +3116,13 @@ void mtree_info(bool flatview, bool dispatch_tree, bool owner)
|
||||
};
|
||||
GArray *fv_address_spaces;
|
||||
GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
AccelClass *ac = ACCEL_GET_CLASS(current_machine->accelerator);
|
||||
|
||||
if (ac->has_memory) {
|
||||
fvi.ac = ac;
|
||||
fvi.ac_name = current_machine->accel ? current_machine->accel :
|
||||
object_class_get_name(OBJECT_CLASS(ac));
|
||||
}
|
||||
|
||||
/* Gather all FVs in one table */
|
||||
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user