From: Gong Chen <gong.c...@intel.com>

When we need to test error injection to a specific address using EINJ,
there needs to be a way to translate GPA to HPA. This will allow host EINJ
to inject error to test how guest behavior is when a bad address is consumed.
This permits guest OS to perform its own recovery.

Signed-off-by: Gong Chen <gong.c...@intel.com>
---
Sorry about the spam :-(.
Resending with proper Commit Message. Previous had a bogus From. Fixed that.
before sending.

 hmp-commands.hx       | 14 ++++++++++++++
 include/exec/memory.h |  2 ++
 kvm-all.c             | 24 ++++++++++++++++++++++++
 memory.c              | 13 +++++++++++++
 monitor.c             | 16 ++++++++++++++++
 5 files changed, 69 insertions(+)
 mode change 100644 => 100755 include/exec/memory.h
 mode change 100644 => 100755 kvm-all.c
 mode change 100644 => 100755 memory.c
 mode change 100644 => 100755 monitor.c

diff --git a/hmp-commands.hx b/hmp-commands.hx
index bb52e4d..673c00e 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -444,6 +444,20 @@ Start gdbserver session (default @var{port}=1234)
 ETEXI
 
     {
+        .name         = "x-gpa2hva",
+        .args_type    = "fmt:/,addr:l",
+        .params       = "/fmt addr",
+        .help         = "translate guest physical 'addr' to host virtual 
address, only for debugging",
+        .mhandler.cmd = do_gpa2hva,
+    },
+
+STEXI
+@item x-gpa2hva @var{addr}
+@findex x-gpa2hva
+Translate guest physical @var{addr} to host virtual address, only for 
debugging.
+ETEXI
+
+    {
         .name       = "x",
         .args_type  = "fmt:/,addr:l",
         .params     = "/fmt addr",
diff --git a/include/exec/memory.h b/include/exec/memory.h
old mode 100644
new mode 100755
index 0f07159..57d7bf8
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -222,6 +222,7 @@ struct MemoryListener {
                                hwaddr addr, hwaddr len);
     void (*coalesced_mmio_del)(MemoryListener *listener, MemoryRegionSection 
*section,
                                hwaddr addr, hwaddr len);
+    int  (*translate_gpa2hva)(MemoryListener *listener, uint64_t paddr, 
uint64_t *vaddr);
     /* Lower = earlier (during add), later (during del) */
     unsigned priority;
     AddressSpace *address_space_filter;
@@ -1123,6 +1124,7 @@ void memory_global_dirty_log_start(void);
 void memory_global_dirty_log_stop(void);
 
 void mtree_info(fprintf_function mon_printf, void *f);
+int  memory_translate_gpa2hva(hwaddr paddr, uint64_t *vaddr);
 
 /**
  * memory_region_dispatch_read: perform a read directly to the specified
diff --git a/kvm-all.c b/kvm-all.c
old mode 100644
new mode 100755
index c648b81..cb029be
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -197,6 +197,29 @@ static KVMSlot 
*kvm_lookup_overlapping_slot(KVMMemoryListener *kml,
     return found;
 }
 
+
+static int kvm_translate_gpa2hva(MemoryListener *listener, uint64_t paddr, 
uint64_t *vaddr)
+{
+    KVMState *s = kvm_state;
+    KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, 
listener);
+    KVMSlot *mem = NULL;
+    int i;
+
+    for (i = 0; i < s->nr_slots; i++) {
+        mem = &kml->slots[i];
+        if (paddr >= mem->start_addr && paddr < mem->start_addr + 
mem->memory_size) {
+            *vaddr = (uint64_t)mem->ram + paddr - mem->start_addr;
+            break;
+       }
+    }
+
+    if (i == s->nr_slots) {
+        fprintf(stderr, "fail to find target physical addr(%ld) in KVM memory 
range\n", paddr);
+       return 1;
+    }
+    return 0;
+}
+
 int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
                                        hwaddr *phys_addr)
 {
@@ -902,6 +925,7 @@ void kvm_memory_listener_register(KVMState *s, 
KVMMemoryListener *kml,
     kml->listener.log_start = kvm_log_start;
     kml->listener.log_stop = kvm_log_stop;
     kml->listener.log_sync = kvm_log_sync;
+    kml->listener.translate_gpa2hva = kvm_translate_gpa2hva;
     kml->listener.priority = 10;
 
     memory_listener_register(&kml->listener, as);
diff --git a/memory.c b/memory.c
old mode 100644
new mode 100755
index e193658..979dcf8
--- a/memory.c
+++ b/memory.c
@@ -2294,6 +2294,19 @@ static const TypeInfo memory_region_info = {
     .instance_finalize  = memory_region_finalize,
 };
 
+int memory_translate_gpa2hva(hwaddr paddr, uint64_t *vaddr){
+    MemoryListener *ml = NULL;
+    int ret = 1;
+
+    QTAILQ_FOREACH(ml, &memory_listeners, link) {
+        if(ml->translate_gpa2hva)
+            ret = ml->translate_gpa2hva(ml, paddr, vaddr);
+       if(0 == ret)
+           break;
+    }
+    return ret;
+}
+
 static void memory_register_types(void)
 {
     type_register_static(&memory_region_info);
diff --git a/monitor.c b/monitor.c
old mode 100644
new mode 100755
index 9a35d72..408e1fa
--- a/monitor.c
+++ b/monitor.c
@@ -76,6 +76,7 @@
 #include "qapi-event.h"
 #include "qmp-introspect.h"
 #include "sysemu/block-backend.h"
+#include "exec/memory.h"
 
 /* for hmp_info_irq/pic */
 #if defined(TARGET_SPARC)
@@ -1681,6 +1682,21 @@ static void hmp_acl_remove(Monitor *mon, const QDict 
*qdict)
     }
 }
 
+static void do_gpa2hva(Monitor *mon, const QDict *qdict)
+{
+    uint64_t paddr;
+    uint64_t vaddr;
+
+    paddr = qdict_get_int(qdict, "addr");
+    if (memory_translate_gpa2hva(paddr, &vaddr)){
+       monitor_printf(mon, "fail to translate gpa(0x%lx) to hva\n", paddr);
+       return;
+    }
+
+    monitor_printf(mon, "0x%lx\n", (unsigned long)vaddr);
+    return;
+}
+
 void qmp_getfd(const char *fdname, Error **errp)
 {
     mon_fd_t *monfd;
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to