From: Gong Chen <gong.chen@xxxxxxxxx> 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.chen@xxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html