diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 35ea3cb624..f450f25295 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -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; } diff --git a/include/sysemu/accel.h b/include/sysemu/accel.h index 81293cdb08..89ce57e404 100644 --- a/include/sysemu/accel.h +++ b/include/sysemu/accel.h @@ -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 diff --git a/memory.c b/memory.c index d4579bbaec..5d8c9a9234 100644 --- a/memory.c +++ b/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) {