qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v1 3/5] RISC-V: 'info gmem' to show hypervisor guest -> physical


From: Konrad Schwarz
Subject: [PATCH v1 3/5] RISC-V: 'info gmem' to show hypervisor guest -> physical address translations
Date: Sun, 2 Jan 2022 17:06:10 +0100

This is analog to the existing 'info mem' command and is implemented
using the same machinery.

Signed-off-by: Konrad Schwarz <konrad.schwarz@siemens.com>
---
 hmp-commands-info.hx         |  16 +++++
 include/monitor/hmp-target.h |   2 +
 target/riscv/monitor.c       | 135 +++++++++++++++++++++++++----------
 3 files changed, 117 insertions(+), 36 deletions(-)

diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index 407a1da800..fa519f0129 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -237,6 +237,22 @@ SRST
     Show the active virtual memory mappings.
 ERST
 
+#if defined TARGET_RISCV
+    {
+        .name       = "gmem",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show the hypervisor guest's physical address"
+                   " translation",
+        .cmd        = hmp_info_gmem,
+    },
+#endif
+
+SRST
+  ``info gmem``
+    Show the hypervisor guest's physical address translation.
+ERST
+
     {
         .name       = "mtree",
         .args_type  = "flatview:-f,dispatch_tree:-d,owner:-o,disabled:-D",
diff --git a/include/monitor/hmp-target.h b/include/monitor/hmp-target.h
index ffdc15a34b..9f2dd976f6 100644
--- a/include/monitor/hmp-target.h
+++ b/include/monitor/hmp-target.h
@@ -2,6 +2,7 @@
  * QEMU monitor
  *
  * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2021 Siemens AG, konrad.schwarz@siemens.com
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to 
deal
@@ -45,6 +46,7 @@ CPUArchState *mon_get_cpu_env(Monitor *mon);
 CPUState *mon_get_cpu(Monitor *mon);
 
 void hmp_info_mem(Monitor *mon, const QDict *qdict);
+void hmp_info_gmem(Monitor *mon, const QDict *qdict);
 void hmp_info_tlb(Monitor *mon, const QDict *qdict);
 void hmp_mce(Monitor *mon, const QDict *qdict);
 void hmp_info_local_apic(Monitor *mon, const QDict *qdict);
diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c
index 3f74ea9934..ad58bdf9ca 100644
--- a/target/riscv/monitor.c
+++ b/target/riscv/monitor.c
@@ -25,16 +25,6 @@
 #include "monitor/monitor.h"
 #include "monitor/hmp-target.h"
 
-#ifdef TARGET_RISCV64
-#define PTE_HEADER_FIELDS       "vaddr            paddr            "\
-                                "size             attr\n"
-#define PTE_HEADER_DELIMITER    "---------------- ---------------- "\
-                                "---------------- -------\n"
-#else
-#define PTE_HEADER_FIELDS       "vaddr    paddr            size     attr\n"
-#define PTE_HEADER_DELIMITER    "-------- ---------------- -------- -------\n"
-#endif
-
 /* Perform linear address sign extension */
 static target_ulong addr_canonical(int va_bits, target_ulong addr)
 {
@@ -47,10 +37,34 @@ static target_ulong addr_canonical(int va_bits, 
target_ulong addr)
     return addr;
 }
 
-static void print_pte_header(Monitor *mon)
+static void print_pte_header(Monitor *mon,
+        char const vaddr_char, char const paddr_char)
 {
-    monitor_printf(mon, PTE_HEADER_FIELDS);
-    monitor_printf(mon, PTE_HEADER_DELIMITER);
+
+# define        VIRTUAL_WIDTH\
+        ((int) ((sizeof "ff" - sizeof "") * sizeof(target_ulong)))
+# define        PHYSICAL_WIDTH\
+        ((int) ((sizeof "ff" - sizeof "") * sizeof(hwaddr)))
+# define        ATTRIBUTE_WIDTH ((int) (sizeof "rwxugad" - sizeof ""))
+
+# define        VIRTUAL_COLUMN_WIDTH    (1 + VIRTUAL_WIDTH)
+# define        PHYSICAL_COLUMN_WIDTH   (1 + PHYSICAL_WIDTH)
+
+    static char const dashes[PHYSICAL_WIDTH] = "----------------";
+
+    monitor_printf(mon,
+            "%c%-*s%c%-*s%-*s%-*s\n"
+            "%-*.*s%-*.*s%-*.*s%-*.*s\n",
+
+            vaddr_char, VIRTUAL_COLUMN_WIDTH - 1, "addr",
+            paddr_char, PHYSICAL_COLUMN_WIDTH - 1, "addr",
+            VIRTUAL_COLUMN_WIDTH, "size",
+            ATTRIBUTE_WIDTH, "attr",
+
+            VIRTUAL_COLUMN_WIDTH, VIRTUAL_WIDTH, dashes,
+            PHYSICAL_COLUMN_WIDTH, PHYSICAL_WIDTH, dashes,
+            VIRTUAL_COLUMN_WIDTH, VIRTUAL_WIDTH, dashes,
+            ATTRIBUTE_WIDTH, ATTRIBUTE_WIDTH, dashes);
 }
 
 static void print_pte(Monitor *mon, int va_bits, target_ulong vaddr,
@@ -65,21 +79,36 @@ static void print_pte(Monitor *mon, int va_bits, 
target_ulong vaddr,
         return;
     }
 
-    monitor_printf(mon, TARGET_FMT_lx " " TARGET_FMT_plx " " TARGET_FMT_lx
-                   " %c%c%c%c%c%c%c\n",
-                   addr_canonical(va_bits, vaddr),
-                   paddr, size,
-                   attr & PTE_R ? 'r' : '-',
-                   attr & PTE_W ? 'w' : '-',
-                   attr & PTE_X ? 'x' : '-',
-                   attr & PTE_U ? 'u' : '-',
-                   attr & PTE_G ? 'g' : '-',
-                   attr & PTE_A ? 'a' : '-',
-                   attr & PTE_D ? 'd' : '-');
+# if 4 == TARGET_LONG_SIZE
+#       define  TARGET_xFMT     PRIx32
+# elif 8 == TARGET_LONG_SIZE
+#       define  TARGET_xFMT     PRIx64
+# else
+#       error TARGET_LONG_SIZE not handled
+# endif
+
+    /* note: RISC-V physical addresses are actually xlen + 2 bits long
+    OTHO, QEMU wil probably never support addresses longer than 64 bits */
+    monitor_printf(mon,
+            "%-*.*" TARGET_xFMT
+            "%-*.*" PRIx64
+            "%-*.*" TARGET_xFMT
+            "%c%c%c%c%c%c%c\n",
+            VIRTUAL_COLUMN_WIDTH, VIRTUAL_WIDTH, addr_canonical(va_bits, 
vaddr),
+            PHYSICAL_COLUMN_WIDTH, PHYSICAL_WIDTH, paddr,
+            VIRTUAL_COLUMN_WIDTH, VIRTUAL_WIDTH, size,
+            attr & PTE_R ? 'r' : '-',
+            attr & PTE_W ? 'w' : '-',
+            attr & PTE_X ? 'x' : '-',
+            attr & PTE_U ? 'u' : '-',
+            attr & PTE_G ? 'g' : '-',
+            attr & PTE_A ? 'a' : '-',
+            attr & PTE_D ? 'd' : '-');
 }
 
 static void walk_pte(Monitor *mon, hwaddr base, target_ulong start,
                      int level, int ptidxbits, int ptesize, int va_bits,
+                     int guest,
                      target_ulong *vbase, hwaddr *pbase, hwaddr *last_paddr,
                      target_ulong *last_size, int *last_attr)
 {
@@ -89,7 +118,7 @@ static void walk_pte(Monitor *mon, hwaddr base, target_ulong 
start,
     target_ulong pte;
     int ptshift;
     int attr;
-    int idx;
+    int idx, idx_end;
 
     if (level < 0) {
         return;
@@ -98,7 +127,8 @@ static void walk_pte(Monitor *mon, hwaddr base, target_ulong 
start,
     ptshift = level * ptidxbits;
     pgsize = 1UL << (PGSHIFT + ptshift);
 
-    for (idx = 0; idx < (1UL << ptidxbits); idx++) {
+    for (idx = 0, idx_end = 1 << (ptidxbits + (guest ? 2 : 0));
+            idx_end > idx; idx++) {
         pte_addr = base + idx * ptesize;
         cpu_physical_memory_read(pte_addr, &pte, ptesize);
 
@@ -131,7 +161,9 @@ static void walk_pte(Monitor *mon, hwaddr base, 
target_ulong start,
             } else {
                 /* pointer to the next level of the page table */
                 walk_pte(mon, paddr, start, level - 1, ptidxbits, ptesize,
-                         va_bits, vbase, pbase, last_paddr,
+                         va_bits,
+                         0 /* guest */,
+                         vbase, pbase, last_paddr,
                          last_size, last_attr);
             }
         }
@@ -141,7 +173,9 @@ static void walk_pte(Monitor *mon, hwaddr base, 
target_ulong start,
 
 }
 
-static void mem_info_svxx(Monitor *mon, CPUArchState *env)
+static void mem_info_svxx(Monitor *mon, CPUArchState *env,
+        target_ulong const atp,
+        int guest, char const vaddr_char, char const paddr_char)
 {
     int levels, ptidxbits, ptesize, vm, va_bits;
     hwaddr base;
@@ -152,11 +186,11 @@ static void mem_info_svxx(Monitor *mon, CPUArchState *env)
     int last_attr;
 
     if (riscv_cpu_mxl(env) == MXL_RV32) {
-        base = (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHIFT;
-        vm = get_field(env->satp, SATP32_MODE);
+        base = (hwaddr)get_field(atp, SATP32_PPN) << PGSHIFT;
+        vm = get_field(atp, SATP32_MODE);
     } else {
-        base = (hwaddr)get_field(env->satp, SATP64_PPN) << PGSHIFT;
-        vm = get_field(env->satp, SATP64_MODE);
+        base = (hwaddr)get_field(atp, SATP64_PPN) << PGSHIFT;
+        vm = get_field(atp, SATP64_MODE);
     }
 
     switch (vm) {
@@ -189,7 +223,7 @@ static void mem_info_svxx(Monitor *mon, CPUArchState *env)
     va_bits = PGSHIFT + levels * ptidxbits;
 
     /* print header */
-    print_pte_header(mon);
+    print_pte_header(mon, vaddr_char, paddr_char);
 
     vbase = -1;
     pbase = -1;
@@ -199,6 +233,7 @@ static void mem_info_svxx(Monitor *mon, CPUArchState *env)
 
     /* walk page tables, starting from address 0 */
     walk_pte(mon, base, 0, levels - 1, ptidxbits, ptesize, va_bits,
+             guest,
              &vbase, &pbase, &last_paddr, &last_size, &last_attr);
 
     /* don't forget the last one */
@@ -209,6 +244,7 @@ static void mem_info_svxx(Monitor *mon, CPUArchState *env)
 void hmp_info_mem(Monitor *mon, const QDict *qdict)
 {
     CPUArchState *env;
+    target_ulong atp;
 
     env = mon_get_cpu_env(mon);
     if (!env) {
@@ -221,19 +257,46 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict)
         return;
     }
 
+    atp = env->satp;
     if (riscv_cpu_mxl(env) == MXL_RV32) {
-        if (!(env->satp & SATP32_MODE)) {
+        if (!(atp & SATP32_MODE)) {
             monitor_printf(mon, "No translation or protection\n");
             return;
         }
     } else {
-        if (!(env->satp & SATP64_MODE)) {
+        if (!(atp & SATP64_MODE)) {
             monitor_printf(mon, "No translation or protection\n");
             return;
         }
     }
 
-    mem_info_svxx(mon, env);
+    mem_info_svxx(mon, env, atp, 0, 'v', 'p');
+}
+
+void hmp_info_gmem(Monitor *mon, const QDict *qdict)
+{
+    CPUArchState *env;
+    target_ulong atp;
+
+    env = mon_get_cpu_env(mon);
+    if (!env) {
+        monitor_printf(mon, "No CPU available\n");
+        return;
+    }
+
+    if (!riscv_has_ext(env, RVH)) {
+        monitor_printf(mon, "hypervisor extension not available\n");
+        return;
+    }
+
+    atp = env->hgatp;
+    if (!((MXL_RV32 == riscv_cpu_mxl(env) ? SATP32_MODE : SATP64_MODE)
+            & atp)) {
+        monitor_printf(mon, "No translation or protection\n");
+        return;
+    }
+
+    mem_info_svxx(mon, env, atp, 1, 'g', 'p');
 }
 
 static const MonitorDef monitor_defs[] = {
-- 
Konrad Schwarz




reply via email to

[Prev in Thread] Current Thread [Next in Thread]