Blame SOURCES/kvm-memory-Rework-info-mtree-to-print-flat-views-and-dis.patch

4a2fec
From 6a1a074890aa228417dffb2afb49f56234e99c8d Mon Sep 17 00:00:00 2001
4a2fec
From: David Gibson <dgibson@redhat.com>
4a2fec
Date: Thu, 16 Nov 2017 03:07:27 +0100
4a2fec
Subject: [PATCH 23/30] memory: Rework "info mtree" to print flat views and
4a2fec
 dispatch trees
4a2fec
4a2fec
RH-Author: David Gibson <dgibson@redhat.com>
4a2fec
Message-id: <20171116030732.8560-18-dgibson@redhat.com>
4a2fec
Patchwork-id: 77709
4a2fec
O-Subject: [PATCH 17/22] memory: Rework "info mtree" to print flat views and dispatch trees
4a2fec
Bugzilla: 1481593
4a2fec
RH-Acked-by: Thomas Huth <thuth@redhat.com>
4a2fec
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
4a2fec
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
4a2fec
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
4a2fec
4a2fec
From: Alexey Kardashevskiy <aik@ozlabs.ru>
4a2fec
4a2fec
This adds a new "-d" switch to "info mtree" to print dispatch tree
4a2fec
internals.
4a2fec
4a2fec
This changes the way "-f" is handled - it prints now flat views and
4a2fec
associated address spaces.
4a2fec
4a2fec
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
4a2fec
Message-Id: <20170921085110.25598-15-aik@ozlabs.ru>
4a2fec
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4a2fec
(cherry picked from commit 5e8fd947e2670c3c18f139de6a83fafcb56abbcc)
4a2fec
4a2fec
Signed-off-by: David Gibson <dgibson@redhat.com>
4a2fec
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
---
4a2fec
 exec.c                         | 84 +++++++++++++++++++++++++++++++++++++++
4a2fec
 hmp-commands-info.hx           |  7 ++--
4a2fec
 include/exec/memory-internal.h |  4 ++
4a2fec
 include/exec/memory.h          |  3 +-
4a2fec
 memory.c                       | 90 +++++++++++++++++++++++++++++++++++++-----
4a2fec
 monitor.c                      |  3 +-
4a2fec
 6 files changed, 176 insertions(+), 15 deletions(-)
4a2fec
4a2fec
diff --git a/exec.c b/exec.c
4a2fec
index 1b30e1e..5a12e55 100644
4a2fec
--- a/exec.c
4a2fec
+++ b/exec.c
4a2fec
@@ -3628,3 +3628,87 @@ void page_size_init(void)
4a2fec
     }
4a2fec
     qemu_host_page_mask = -(intptr_t)qemu_host_page_size;
4a2fec
 }
4a2fec
+
4a2fec
+#if !defined(CONFIG_USER_ONLY)
4a2fec
+
4a2fec
+static void mtree_print_phys_entries(fprintf_function mon, void *f,
4a2fec
+                                     int start, int end, int skip, int ptr)
4a2fec
+{
4a2fec
+    if (start == end - 1) {
4a2fec
+        mon(f, "\t%3d      ", start);
4a2fec
+    } else {
4a2fec
+        mon(f, "\t%3d..%-3d ", start, end - 1);
4a2fec
+    }
4a2fec
+    mon(f, " skip=%d ", skip);
4a2fec
+    if (ptr == PHYS_MAP_NODE_NIL) {
4a2fec
+        mon(f, " ptr=NIL");
4a2fec
+    } else if (!skip) {
4a2fec
+        mon(f, " ptr=#%d", ptr);
4a2fec
+    } else {
4a2fec
+        mon(f, " ptr=[%d]", ptr);
4a2fec
+    }
4a2fec
+    mon(f, "\n");
4a2fec
+}
4a2fec
+
4a2fec
+#define MR_SIZE(size) (int128_nz(size) ? (hwaddr)int128_get64( \
4a2fec
+                           int128_sub((size), int128_one())) : 0)
4a2fec
+
4a2fec
+void mtree_print_dispatch(fprintf_function mon, void *f,
4a2fec
+                          AddressSpaceDispatch *d, MemoryRegion *root)
4a2fec
+{
4a2fec
+    int i;
4a2fec
+
4a2fec
+    mon(f, "  Dispatch\n");
4a2fec
+    mon(f, "    Physical sections\n");
4a2fec
+
4a2fec
+    for (i = 0; i < d->map.sections_nb; ++i) {
4a2fec
+        MemoryRegionSection *s = d->map.sections + i;
4a2fec
+        const char *names[] = { " [unassigned]", " [not dirty]",
4a2fec
+                                " [ROM]", " [watch]" };
4a2fec
+
4a2fec
+        mon(f, "      #%d @" TARGET_FMT_plx ".." TARGET_FMT_plx " %s%s%s%s%s",
4a2fec
+            i,
4a2fec
+            s->offset_within_address_space,
4a2fec
+            s->offset_within_address_space + MR_SIZE(s->mr->size),
4a2fec
+            s->mr->name ? s->mr->name : "(noname)",
4a2fec
+            i < ARRAY_SIZE(names) ? names[i] : "",
4a2fec
+            s->mr == root ? " [ROOT]" : "",
4a2fec
+            s == d->mru_section ? " [MRU]" : "",
4a2fec
+            s->mr->is_iommu ? " [iommu]" : "");
4a2fec
+
4a2fec
+        if (s->mr->alias) {
4a2fec
+            mon(f, " alias=%s", s->mr->alias->name ?
4a2fec
+                    s->mr->alias->name : "noname");
4a2fec
+        }
4a2fec
+        mon(f, "\n");
4a2fec
+    }
4a2fec
+
4a2fec
+    mon(f, "    Nodes (%d bits per level, %d levels) ptr=[%d] skip=%d\n",
4a2fec
+               P_L2_BITS, P_L2_LEVELS, d->phys_map.ptr, d->phys_map.skip);
4a2fec
+    for (i = 0; i < d->map.nodes_nb; ++i) {
4a2fec
+        int j, jprev;
4a2fec
+        PhysPageEntry prev;
4a2fec
+        Node *n = d->map.nodes + i;
4a2fec
+
4a2fec
+        mon(f, "      [%d]\n", i);
4a2fec
+
4a2fec
+        for (j = 0, jprev = 0, prev = *n[0]; j < ARRAY_SIZE(*n); ++j) {
4a2fec
+            PhysPageEntry *pe = *n + j;
4a2fec
+
4a2fec
+            if (pe->ptr == prev.ptr && pe->skip == prev.skip) {
4a2fec
+                continue;
4a2fec
+            }
4a2fec
+
4a2fec
+            mtree_print_phys_entries(mon, f, jprev, j, prev.skip, prev.ptr);
4a2fec
+
4a2fec
+            jprev = j;
4a2fec
+            prev = *pe;
4a2fec
+        }
4a2fec
+
4a2fec
+        if (jprev != ARRAY_SIZE(*n)) {
4a2fec
+            mtree_print_phys_entries(mon, f, jprev, j, prev.skip, prev.ptr);
4a2fec
+        }
4a2fec
+    }
4a2fec
+}
4a2fec
+
4a2fec
+#endif
4a2fec
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
4a2fec
index 0967e41..30b335f 100644
4a2fec
--- a/hmp-commands-info.hx
4a2fec
+++ b/hmp-commands-info.hx
4a2fec
@@ -253,9 +253,10 @@ ETEXI
4a2fec
 
4a2fec
     {
4a2fec
         .name       = "mtree",
4a2fec
-        .args_type  = "flatview:-f",
4a2fec
-        .params     = "[-f]",
4a2fec
-        .help       = "show memory tree (-f: dump flat view for address spaces)",
4a2fec
+        .args_type  = "flatview:-f,dispatch_tree:-d",
4a2fec
+        .params     = "[-f][-d]",
4a2fec
+        .help       = "show memory tree (-f: dump flat view for address spaces;"
4a2fec
+                      "-d: dump dispatch tree, valid with -f only)",
4a2fec
         .cmd        = hmp_info_mtree,
4a2fec
     },
4a2fec
 
4a2fec
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
4a2fec
index d4a35c6..647e9bd 100644
4a2fec
--- a/include/exec/memory-internal.h
4a2fec
+++ b/include/exec/memory-internal.h
4a2fec
@@ -35,5 +35,9 @@ AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as);
4a2fec
 AddressSpaceDispatch *flatview_to_dispatch(FlatView *fv);
4a2fec
 void address_space_dispatch_free(AddressSpaceDispatch *d);
4a2fec
 
4a2fec
+void mtree_print_dispatch(fprintf_function mon, void *f,
4a2fec
+                          struct AddressSpaceDispatch *d,
4a2fec
+                          MemoryRegion *root);
4a2fec
+
4a2fec
 #endif
4a2fec
 #endif
4a2fec
diff --git a/include/exec/memory.h b/include/exec/memory.h
4a2fec
index 6715551..157eae6 100644
4a2fec
--- a/include/exec/memory.h
4a2fec
+++ b/include/exec/memory.h
4a2fec
@@ -1525,7 +1525,8 @@ void memory_global_dirty_log_start(void);
4a2fec
  */
4a2fec
 void memory_global_dirty_log_stop(void);
4a2fec
 
4a2fec
-void mtree_info(fprintf_function mon_printf, void *f, bool flatview);
4a2fec
+void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
4a2fec
+                bool dispatch_tree);
4a2fec
 
4a2fec
 /**
4a2fec
  * memory_region_request_mmio_ptr: request a pointer to an mmio
4a2fec
diff --git a/memory.c b/memory.c
4a2fec
index 6914d87..25a8bf2 100644
4a2fec
--- a/memory.c
4a2fec
+++ b/memory.c
4a2fec
@@ -2906,18 +2906,44 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
4a2fec
     }
4a2fec
 }
4a2fec
 
4a2fec
-static void mtree_print_flatview(fprintf_function p, void *f,
4a2fec
-                                 AddressSpace *as)
4a2fec
+struct FlatViewInfo {
4a2fec
+    fprintf_function mon_printf;
4a2fec
+    void *f;
4a2fec
+    int counter;
4a2fec
+    bool dispatch_tree;
4a2fec
+};
4a2fec
+
4a2fec
+static void mtree_print_flatview(gpointer key, gpointer value,
4a2fec
+                                 gpointer user_data)
4a2fec
 {
4a2fec
-    FlatView *view = address_space_get_flatview(as);
4a2fec
+    FlatView *view = key;
4a2fec
+    GArray *fv_address_spaces = value;
4a2fec
+    struct FlatViewInfo *fvi = user_data;
4a2fec
+    fprintf_function p = fvi->mon_printf;
4a2fec
+    void *f = fvi->f;
4a2fec
     FlatRange *range = &view->ranges[0];
4a2fec
     MemoryRegion *mr;
4a2fec
     int n = view->nr;
4a2fec
+    int i;
4a2fec
+    AddressSpace *as;
4a2fec
+
4a2fec
+    p(f, "FlatView #%d\n", fvi->counter);
4a2fec
+    ++fvi->counter;
4a2fec
+
4a2fec
+    for (i = 0; i < fv_address_spaces->len; ++i) {
4a2fec
+        as = g_array_index(fv_address_spaces, AddressSpace*, i);
4a2fec
+        p(f, " AS \"%s\", root: %s", as->name, memory_region_name(as->root));
4a2fec
+        if (as->root->alias) {
4a2fec
+            p(f, ", alias %s", memory_region_name(as->root->alias));
4a2fec
+        }
4a2fec
+        p(f, "\n");
4a2fec
+    }
4a2fec
+
4a2fec
+    p(f, " Root memory region: %s\n",
4a2fec
+      view->root ? memory_region_name(view->root) : "(none)");
4a2fec
 
4a2fec
     if (n <= 0) {
4a2fec
-        p(f, MTREE_INDENT "No rendered FlatView for "
4a2fec
-          "address space '%s'\n", as->name);
4a2fec
-        flatview_unref(view);
4a2fec
+        p(f, MTREE_INDENT "No rendered FlatView\n\n");
4a2fec
         return;
4a2fec
     }
4a2fec
 
4a2fec
@@ -2944,21 +2970,65 @@ static void mtree_print_flatview(fprintf_function p, void *f,
4a2fec
         range++;
4a2fec
     }
4a2fec
 
4a2fec
+#if !defined(CONFIG_USER_ONLY)
4a2fec
+    if (fvi->dispatch_tree && view->root) {
4a2fec
+        mtree_print_dispatch(p, f, view->dispatch, view->root);
4a2fec
+    }
4a2fec
+#endif
4a2fec
+
4a2fec
+    p(f, "\n");
4a2fec
+}
4a2fec
+
4a2fec
+static gboolean mtree_info_flatview_free(gpointer key, gpointer value,
4a2fec
+                                      gpointer user_data)
4a2fec
+{
4a2fec
+    FlatView *view = key;
4a2fec
+    GArray *fv_address_spaces = value;
4a2fec
+
4a2fec
+    g_array_unref(fv_address_spaces);
4a2fec
     flatview_unref(view);
4a2fec
+
4a2fec
+    return true;
4a2fec
 }
4a2fec
 
4a2fec
-void mtree_info(fprintf_function mon_printf, void *f, bool flatview)
4a2fec
+void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
4a2fec
+                bool dispatch_tree)
4a2fec
 {
4a2fec
     MemoryRegionListHead ml_head;
4a2fec
     MemoryRegionList *ml, *ml2;
4a2fec
     AddressSpace *as;
4a2fec
 
4a2fec
     if (flatview) {
4a2fec
+        FlatView *view;
4a2fec
+        struct FlatViewInfo fvi = {
4a2fec
+            .mon_printf = mon_printf,
4a2fec
+            .f = f,
4a2fec
+            .counter = 0,
4a2fec
+            .dispatch_tree = dispatch_tree
4a2fec
+        };
4a2fec
+        GArray *fv_address_spaces;
4a2fec
+        GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal);
4a2fec
+
4a2fec
+        /* Gather all FVs in one table */
4a2fec
         QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
4a2fec
-            mon_printf(f, "address-space (flat view): %s\n", as->name);
4a2fec
-            mtree_print_flatview(mon_printf, f, as);
4a2fec
-            mon_printf(f, "\n");
4a2fec
+            view = address_space_get_flatview(as);
4a2fec
+
4a2fec
+            fv_address_spaces = g_hash_table_lookup(views, view);
4a2fec
+            if (!fv_address_spaces) {
4a2fec
+                fv_address_spaces = g_array_new(false, false, sizeof(as));
4a2fec
+                g_hash_table_insert(views, view, fv_address_spaces);
4a2fec
+            }
4a2fec
+
4a2fec
+            g_array_append_val(fv_address_spaces, as);
4a2fec
         }
4a2fec
+
4a2fec
+        /* Print */
4a2fec
+        g_hash_table_foreach(views, mtree_print_flatview, &fvi);
4a2fec
+
4a2fec
+        /* Free */
4a2fec
+        g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0);
4a2fec
+        g_hash_table_unref(views);
4a2fec
+
4a2fec
         return;
4a2fec
     }
4a2fec
 
4a2fec
diff --git a/monitor.c b/monitor.c
4a2fec
index c0a8dbc..6380e4a 100644
4a2fec
--- a/monitor.c
4a2fec
+++ b/monitor.c
4a2fec
@@ -1734,8 +1734,9 @@ static void hmp_boot_set(Monitor *mon, const QDict *qdict)
4a2fec
 static void hmp_info_mtree(Monitor *mon, const QDict *qdict)
4a2fec
 {
4a2fec
     bool flatview = qdict_get_try_bool(qdict, "flatview", false);
4a2fec
+    bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false);
4a2fec
 
4a2fec
-    mtree_info((fprintf_function)monitor_printf, mon, flatview);
4a2fec
+    mtree_info((fprintf_function)monitor_printf, mon, flatview, dispatch_tree);
4a2fec
 }
4a2fec
 
4a2fec
 static void hmp_info_numa(Monitor *mon, const QDict *qdict)
4a2fec
-- 
4a2fec
1.8.3.1
4a2fec