From bd0dbd274d48c95738b770e951406063eb56e4c6 Mon Sep 17 00:00:00 2001 From: Mingqiang Chi Date: Tue, 19 Nov 2019 17:25:04 +0800 Subject: [PATCH] hv:add dump_guest_mem add shell command to support dump dump guest memory e.g. dump_guest_mem vm_id, gva, length Tracked-On: #4144 Signed-off-by: Mingqiang Chi Acked-by: Eddie Dong --- hypervisor/debug/shell.c | 74 ++++++++++++++++++++++++ hypervisor/debug/shell_priv.h | 4 ++ hypervisor/include/arch/x86/guest/vcpu.h | 6 ++ 3 files changed, 84 insertions(+) diff --git a/hypervisor/debug/shell.c b/hypervisor/debug/shell.c index 4ee615ef0..ddd253af2 100644 --- a/hypervisor/debug/shell.c +++ b/hypervisor/debug/shell.c @@ -39,6 +39,7 @@ static int32_t shell_list_vm(__unused int32_t argc, __unused char **argv); static int32_t shell_list_vcpu(__unused int32_t argc, __unused char **argv); static int32_t shell_vcpu_dumpreg(int32_t argc, char **argv); static int32_t shell_dump_host_mem(int32_t argc, char **argv); +static int32_t shell_dump_guest_mem(int32_t argc, char **argv); static int32_t shell_to_vm_console(int32_t argc, char **argv); static int32_t shell_show_cpu_int(__unused int32_t argc, __unused char **argv); static int32_t shell_show_ptdev_info(__unused int32_t argc, __unused char **argv); @@ -87,6 +88,12 @@ static struct shell_cmd shell_cmds[] = { .help_str = SHELL_CMD_DUMP_HOST_MEM_HELP, .fcn = shell_dump_host_mem, }, + { + .str = SHELL_CMD_DUMP_GUEST_MEM, + .cmd_param = SHELL_CMD_DUMP_GUEST_MEM_PARAM, + .help_str = SHELL_CMD_DUMP_GUEST_MEM_HELP, + .fcn = shell_dump_guest_mem, + }, { .str = SHELL_CMD_VM_CONSOLE, .cmd_param = SHELL_CMD_VM_CONSOLE_PARAM, @@ -854,6 +861,73 @@ static int32_t shell_dump_host_mem(int32_t argc, char **argv) return ret; } +static void dump_guest_mem(void *data) +{ + uint64_t i, fault_addr; + uint32_t err_code = 0; + uint64_t loop_cnt; + uint64_t buf[4]; + char temp_str[MAX_STR_SIZE]; + struct guest_mem_dump *dump = (struct guest_mem_dump *)data; + uint64_t length = dump->len; + uint64_t gva = dump->gva; + struct acrn_vcpu *vcpu = dump->vcpu; + + /* Change the length to a multiple of 32 if the length is not */ + loop_cnt = ((length & 0x1fUL) == 0UL) ? ((length >> 5UL)) : ((length >> 5UL) + 1UL); + + for (i = 0UL; i < loop_cnt; i++) { + + if (copy_from_gva(vcpu, buf, gva, 32U, &err_code, &fault_addr) != 0) { + printf("copy_from_gva error! err_code=0x%x fault_addr=0x%llx\r\n", err_code, fault_addr); + break; + } + snprintf(temp_str, MAX_STR_SIZE, "GVA(0x%llx): 0x%016lx 0x%016lx 0x%016lx 0x%016lx\r\n", + gva, buf[0], buf[1], buf[2], buf[3]); + shell_puts(temp_str); + gva += 32UL; + } +} + +static int32_t shell_dump_guest_mem(int32_t argc, char **argv) +{ + uint16_t vm_id, pcpu_id; + int32_t ret; + uint64_t gva; + uint64_t length; + uint64_t mask = 0UL; + struct acrn_vm *vm; + struct acrn_vcpu *vcpu = NULL; + struct guest_mem_dump dump; + + /* User input invalidation */ + if (argc != 4) { + ret = -EINVAL; + } else { + vm_id = sanitize_vmid((uint16_t)strtol_deci(argv[1])); + gva = strtoul_hex(argv[2]); + length = (uint64_t)strtol_deci(argv[3]); + + vm = get_vm_from_vmid(vm_id); + vcpu = vcpu_from_vid(vm, BOOT_CPU_ID); + + dump.vcpu = vcpu; + dump.gva = gva; + dump.len = length; + + pcpu_id = pcpuid_from_vcpu(vcpu); + if (pcpu_id == get_pcpu_id()) { + dump_guest_mem(&dump); + } else { + bitmap_set_nolock(pcpu_id, &mask); + smp_call_function(mask, dump_guest_mem, &dump); + } + ret = 0; + } + + return ret; +} + static int32_t shell_to_vm_console(int32_t argc, char **argv) { char temp_str[TEMP_STR_SIZE]; diff --git a/hypervisor/debug/shell_priv.h b/hypervisor/debug/shell_priv.h index a82d355c3..af741aa26 100644 --- a/hypervisor/debug/shell_priv.h +++ b/hypervisor/debug/shell_priv.h @@ -60,6 +60,10 @@ struct shell { #define SHELL_CMD_DUMP_HOST_MEM_PARAM "" #define SHELL_CMD_DUMP_HOST_MEM_HELP "Dump host memory, starting at a given address(Hex), and for a given length (Dec in bytes)" +#define SHELL_CMD_DUMP_GUEST_MEM "dump_guest_mem" +#define SHELL_CMD_DUMP_GUEST_MEM_PARAM "" +#define SHELL_CMD_DUMP_GUEST_MEM_HELP "Dump guest memory, vm id(Dec), starting at a given address(Hex), and for a given length (Dec in bytes)" + #define SHELL_CMD_VM_CONSOLE "vm_console" #define SHELL_CMD_VM_CONSOLE_PARAM "" #define SHELL_CMD_VM_CONSOLE_HELP "Switch to the VM's console. Use [Ctrl+Spacebar] to return to the ACRN shell "\ diff --git a/hypervisor/include/arch/x86/guest/vcpu.h b/hypervisor/include/arch/x86/guest/vcpu.h index 3d5578f81..4e726e85a 100644 --- a/hypervisor/include/arch/x86/guest/vcpu.h +++ b/hypervisor/include/arch/x86/guest/vcpu.h @@ -263,6 +263,12 @@ struct vcpu_dump { uint32_t str_max; }; +struct guest_mem_dump { + struct acrn_vcpu *vcpu; + uint64_t gva; + uint64_t len; +}; + static inline bool is_vcpu_bsp(const struct acrn_vcpu *vcpu) { return (vcpu->vcpu_id == BOOT_CPU_ID);