hmp: gpa2hva and gpa2hpa hostaddr command
These commands are useful when testing machine-check passthrough. gpa2hva is useful to inject a MADV_HWPOISON madvise from gdb, while gpa2hpa is useful to inject an error with the mce-inject kernel module. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <1490021158-4469-1-git-send-email-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <20170420133058.12911-1-pbonzini@redhat.com> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
This commit is contained in:
parent
dcaed66cbe
commit
e9628441df
@ -523,6 +523,38 @@ Dump 80 16 bit values at the start of the video memory.
|
||||
0x000b8090: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
|
||||
@end smallexample
|
||||
@end itemize
|
||||
ETEXI
|
||||
|
||||
{
|
||||
.name = "gpa2hva",
|
||||
.args_type = "addr:l",
|
||||
.params = "addr",
|
||||
.help = "print the host virtual address corresponding to a guest physical address",
|
||||
.cmd = hmp_gpa2hva,
|
||||
},
|
||||
|
||||
STEXI
|
||||
@item gpa2hva @var{addr}
|
||||
@findex gpa2hva
|
||||
Print the host virtual address at which the guest's physical address @var{addr}
|
||||
is mapped.
|
||||
ETEXI
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
{
|
||||
.name = "gpa2hpa",
|
||||
.args_type = "addr:l",
|
||||
.params = "addr",
|
||||
.help = "print the host physical address corresponding to a guest physical address",
|
||||
.cmd = hmp_gpa2hpa,
|
||||
},
|
||||
#endif
|
||||
|
||||
STEXI
|
||||
@item gpa2hpa @var{addr}
|
||||
@findex gpa2hpa
|
||||
Print the host physical address at which the guest's physical address @var{addr}
|
||||
is mapped.
|
||||
ETEXI
|
||||
|
||||
{
|
||||
|
101
monitor.c
101
monitor.c
@ -1421,6 +1421,107 @@ static void hmp_physical_memory_dump(Monitor *mon, const QDict *qdict)
|
||||
memory_dump(mon, count, format, size, addr, 1);
|
||||
}
|
||||
|
||||
static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
|
||||
{
|
||||
MemoryRegionSection mrs = memory_region_find(get_system_memory(),
|
||||
addr, 1);
|
||||
|
||||
if (!mrs.mr) {
|
||||
error_setg(errp, "No memory is mapped at address 0x%" HWADDR_PRIx, addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!memory_region_is_ram(mrs.mr) && !memory_region_is_romd(mrs.mr)) {
|
||||
error_setg(errp, "Memory at address 0x%" HWADDR_PRIx "is not RAM", addr);
|
||||
memory_region_unref(mrs.mr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*p_mr = mrs.mr;
|
||||
return qemu_map_ram_ptr(mrs.mr->ram_block, mrs.offset_within_region);
|
||||
}
|
||||
|
||||
static void hmp_gpa2hva(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
hwaddr addr = qdict_get_int(qdict, "addr");
|
||||
Error *local_err = NULL;
|
||||
MemoryRegion *mr = NULL;
|
||||
void *ptr;
|
||||
|
||||
ptr = gpa2hva(&mr, addr, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "Host virtual address for 0x%" HWADDR_PRIx
|
||||
" (%s) is %p\n",
|
||||
addr, mr->name, ptr);
|
||||
|
||||
memory_region_unref(mr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
static uint64_t vtop(void *ptr, Error **errp)
|
||||
{
|
||||
uint64_t pinfo;
|
||||
uint64_t ret = -1;
|
||||
uintptr_t addr = (uintptr_t) ptr;
|
||||
uintptr_t pagesize = getpagesize();
|
||||
off_t offset = addr / pagesize * sizeof(pinfo);
|
||||
int fd;
|
||||
|
||||
fd = open("/proc/self/pagemap", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
error_setg_errno(errp, errno, "Cannot open /proc/self/pagemap");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Force copy-on-write if necessary. */
|
||||
atomic_add((uint8_t *)ptr, 0);
|
||||
|
||||
if (pread(fd, &pinfo, sizeof(pinfo), offset) != sizeof(pinfo)) {
|
||||
error_setg_errno(errp, errno, "Cannot read pagemap");
|
||||
goto out;
|
||||
}
|
||||
if ((pinfo & (1ull << 63)) == 0) {
|
||||
error_setg(errp, "Page not present");
|
||||
goto out;
|
||||
}
|
||||
ret = ((pinfo & 0x007fffffffffffffull) * pagesize) | (addr & (pagesize - 1));
|
||||
|
||||
out:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hmp_gpa2hpa(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
hwaddr addr = qdict_get_int(qdict, "addr");
|
||||
Error *local_err = NULL;
|
||||
MemoryRegion *mr = NULL;
|
||||
void *ptr;
|
||||
uint64_t physaddr;
|
||||
|
||||
ptr = gpa2hva(&mr, addr, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
physaddr = vtop(ptr, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
} else {
|
||||
monitor_printf(mon, "Host physical address for 0x%" HWADDR_PRIx
|
||||
" (%s) is 0x%" PRIx64 "\n",
|
||||
addr, mr->name, (uint64_t) physaddr);
|
||||
}
|
||||
|
||||
memory_region_unref(mr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void do_print(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int format = qdict_get_int(qdict, "format");
|
||||
|
Loading…
Reference in New Issue
Block a user