mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-19 04:02:05 +00:00
dump vcpu registers on correct vcpu
after updated cpu context get/set method, the vcpu_dumreg cmd is not correct anymore as the registers may read from VMCS but meantime hv shell may not be running on target vcpu. this patch take use of smp_call_function for vcpu dumpreg and make the dump always come from correct vcpu. v2: - use str pointer to get vcpu_dumpreg context instead of print out directly in notify handler. Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
4b03c97a5e
commit
f8f49d410f
@ -536,3 +536,83 @@ void request_vcpu_pre_work(struct vcpu *vcpu, uint16_t pre_work_id)
|
|||||||
{
|
{
|
||||||
bitmap_set_lock(pre_work_id, &vcpu->pending_pre_work);
|
bitmap_set_lock(pre_work_id, &vcpu->pending_pre_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HV_DEBUG
|
||||||
|
#define DUMPREG_SP_SIZE 32
|
||||||
|
/* the input 'data' must != NULL and indicate a vcpu structure pointer */
|
||||||
|
void vcpu_dumpreg(void *data)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
uint64_t i, fault_addr, tmp[DUMPREG_SP_SIZE];
|
||||||
|
uint32_t err_code = 0;
|
||||||
|
struct vcpu_dump *dump = data;
|
||||||
|
struct vcpu *vcpu = dump->vcpu;
|
||||||
|
char *str = dump->str;
|
||||||
|
int len, size = dump->str_max;
|
||||||
|
|
||||||
|
len = snprintf(str, size,
|
||||||
|
"= VM ID %d ==== CPU ID %hu========================\r\n"
|
||||||
|
"= RIP=0x%016llx RSP=0x%016llx RFLAGS=0x%016llx\r\n"
|
||||||
|
"= CR0=0x%016llx CR2=0x%016llx\r\n"
|
||||||
|
"= CR3=0x%016llx CR4=0x%016llx\r\n"
|
||||||
|
"= RAX=0x%016llx RBX=0x%016llx RCX=0x%016llx\r\n"
|
||||||
|
"= RDX=0x%016llx RDI=0x%016llx RSI=0x%016llx\r\n"
|
||||||
|
"= RBP=0x%016llx R8=0x%016llx R9=0x%016llx\r\n"
|
||||||
|
"= R10=0x%016llx R11=0x%016llx R12=0x%016llx\r\n"
|
||||||
|
"= R13=0x%016llx R14=0x%016llx R15=0x%016llx\r\n",
|
||||||
|
vcpu->vm->vm_id, vcpu->vcpu_id,
|
||||||
|
vcpu_get_rip(vcpu),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_RSP),
|
||||||
|
vcpu_get_rflags(vcpu),
|
||||||
|
vcpu_get_cr0(vcpu), vcpu_get_cr2(vcpu),
|
||||||
|
exec_vmread(VMX_GUEST_CR3), vcpu_get_cr4(vcpu),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_RAX),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_RBX),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_RCX),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_RDX),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_RDI),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_RSI),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_RBP),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_R8),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_R9),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_R10),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_R11),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_R12),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_R13),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_R14),
|
||||||
|
vcpu_get_gpreg(vcpu, CPU_REG_R15));
|
||||||
|
size -= len;
|
||||||
|
str += len;
|
||||||
|
|
||||||
|
/* dump sp */
|
||||||
|
status = copy_from_gva(vcpu, tmp, vcpu_get_gpreg(vcpu, CPU_REG_RSP),
|
||||||
|
DUMPREG_SP_SIZE*sizeof(uint64_t), &err_code,
|
||||||
|
&fault_addr);
|
||||||
|
if (status < 0) {
|
||||||
|
/* copy_from_gva fail */
|
||||||
|
len = snprintf(str, size, "Cannot handle user gva yet!\r\n");
|
||||||
|
size -= len;
|
||||||
|
str += len;
|
||||||
|
} else {
|
||||||
|
len = snprintf(str, size,
|
||||||
|
"\r\nDump RSP for vm %hu, from gva 0x%016llx\r\n",
|
||||||
|
vcpu->vm->vm_id, vcpu_get_gpreg(vcpu, CPU_REG_RSP));
|
||||||
|
size -= len;
|
||||||
|
str += len;
|
||||||
|
|
||||||
|
for (i = 0UL; i < 8UL; i++) {
|
||||||
|
len = snprintf(str, size, "= 0x%016llx 0x%016llx "
|
||||||
|
"0x%016llx 0x%016llx\r\n",
|
||||||
|
tmp[i*4UL], tmp[(i*4UL)+1UL],
|
||||||
|
tmp[(i*4UL)+2UL], tmp[(i*4UL)+3UL]);
|
||||||
|
size -= len;
|
||||||
|
str += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void vcpu_dumpreg(__unused struct vcpu *vcpu)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* HV_DEBUG */
|
||||||
|
@ -606,120 +606,66 @@ static int shell_list_vcpu(__unused int argc, __unused char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DUMPREG_SP_SIZE 32
|
|
||||||
static int shell_vcpu_dumpreg(int argc, char **argv)
|
static int shell_vcpu_dumpreg(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
uint16_t vm_id;
|
uint16_t vm_id;
|
||||||
uint16_t vcpu_id;
|
uint16_t vcpu_id;
|
||||||
char temp_str[MAX_STR_SIZE];
|
|
||||||
struct vm *vm;
|
struct vm *vm;
|
||||||
struct vcpu *vcpu;
|
struct vcpu *vcpu;
|
||||||
uint64_t i, fault_addr;
|
uint64_t mask = 0UL;
|
||||||
uint64_t tmp[DUMPREG_SP_SIZE];
|
struct vcpu_dump dump;
|
||||||
uint32_t err_code = 0;
|
char *temp_str = alloc_page();
|
||||||
|
|
||||||
|
if (temp_str == NULL) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
/* User input invalidation */
|
/* User input invalidation */
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
shell_puts("Please enter cmd with <vm_id, vcpu_id>\r\n");
|
shell_puts("Please enter cmd with <vm_id, vcpu_id>\r\n");
|
||||||
return -EINVAL;
|
status = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = atoi(argv[1]);
|
status = atoi(argv[1]);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
return -EINVAL;
|
goto out;
|
||||||
}
|
}
|
||||||
vm_id = (uint16_t)status;
|
vm_id = (uint16_t)status;
|
||||||
vcpu_id = (uint16_t)atoi(argv[2]);
|
vcpu_id = (uint16_t)atoi(argv[2]);
|
||||||
if (vcpu_id >= phys_cpu_num) {
|
if (vcpu_id >= phys_cpu_num) {
|
||||||
return (-EINVAL);
|
status = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
vm = get_vm_from_vmid(vm_id);
|
vm = get_vm_from_vmid(vm_id);
|
||||||
if (vm == NULL) {
|
if (vm == NULL) {
|
||||||
shell_puts("No vm found in the input <vm_id, vcpu_id>\r\n");
|
shell_puts("No vm found in the input <vm_id, vcpu_id>\r\n");
|
||||||
return -EINVAL;
|
status = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
vcpu = vcpu_from_vid(vm, vcpu_id);
|
vcpu = vcpu_from_vid(vm, vcpu_id);
|
||||||
if (vcpu == NULL) {
|
if (vcpu == NULL) {
|
||||||
shell_puts("No vcpu found in the input <vm_id, vcpu_id>\r\n");
|
shell_puts("No vcpu found in the input <vm_id, vcpu_id>\r\n");
|
||||||
return -EINVAL;
|
status = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vcpu->state != VCPU_PAUSED) {
|
dump.vcpu = vcpu;
|
||||||
shell_puts("NOTE: VCPU unPAUSEed, regdump "
|
dump.str = temp_str;
|
||||||
"may not be accurate\r\n");
|
dump.str_max = CPU_PAGE_SIZE;
|
||||||
|
if (vcpu->pcpu_id == get_cpu_id())
|
||||||
|
vcpu_dumpreg(&dump);
|
||||||
|
else {
|
||||||
|
bitmap_set_nolock(vcpu->pcpu_id, &mask);
|
||||||
|
smp_call_function(mask, vcpu_dumpreg, &dump);
|
||||||
}
|
}
|
||||||
|
shell_puts(temp_str);
|
||||||
|
status = 0;
|
||||||
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE,
|
out:
|
||||||
"= VM ID %d ==== CPU ID %hu========================\r\n",
|
free(temp_str);
|
||||||
vm->vm_id, vcpu->vcpu_id);
|
|
||||||
shell_puts(temp_str);
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE, "= RIP=0x%016llx RSP=0x%016llx "
|
|
||||||
"RFLAGS=0x%016llx\r\n", vcpu_get_rip(vcpu),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_RSP),
|
|
||||||
vcpu_get_rflags(vcpu));
|
|
||||||
shell_puts(temp_str);
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE, "= CR0=0x%016llx CR2=0x%016llx\r\n",
|
|
||||||
vcpu_get_cr0(vcpu), vcpu_get_cr2(vcpu));
|
|
||||||
shell_puts(temp_str);
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE, "= CR3=0x%016llx CR4=0x%016llx\r\n",
|
|
||||||
exec_vmread(VMX_GUEST_CR3), vcpu_get_cr4(vcpu));
|
|
||||||
shell_puts(temp_str);
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE, "= RAX=0x%016llx RBX=0x%016llx "
|
|
||||||
"RCX=0x%016llx\r\n",
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_RAX),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_RBX),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_RCX));
|
|
||||||
shell_puts(temp_str);
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE, "= RDX=0x%016llx RDI=0x%016llx "
|
|
||||||
"RSI=0x%016llx\r\n",
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_RDX),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_RDI),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_RSI));
|
|
||||||
shell_puts(temp_str);
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE, "= RBP=0x%016llx R8=0x%016llx "
|
|
||||||
"R9=0x%016llx\r\n",
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_RBP),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_R8),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_R9));
|
|
||||||
shell_puts(temp_str);
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE, "= R10=0x%016llx R11=0x%016llx "
|
|
||||||
"R12=0x%016llx\r\n",
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_R10),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_R11),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_R12));
|
|
||||||
shell_puts(temp_str);
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE,
|
|
||||||
"= R13=0x%016llx R14=0x%016llx R15=0x%016llx\r\n",
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_R13),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_R14),
|
|
||||||
vcpu_get_gpreg(vcpu, CPU_REG_R15));
|
|
||||||
shell_puts(temp_str);
|
|
||||||
|
|
||||||
/* dump sp */
|
|
||||||
status = copy_from_gva(vcpu, tmp, vcpu_get_gpreg(vcpu, CPU_REG_RSP),
|
|
||||||
DUMPREG_SP_SIZE*sizeof(uint64_t), &err_code,
|
|
||||||
&fault_addr);
|
|
||||||
if (status < 0) {
|
|
||||||
/* copy_from_gva fail */
|
|
||||||
shell_puts("Cannot handle user gva yet!\r\n");
|
|
||||||
} else {
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE,
|
|
||||||
"\r\nDump RSP for vm %hu, from "
|
|
||||||
"gva 0x%016llx\r\n",
|
|
||||||
vm_id, vcpu_get_gpreg(vcpu, CPU_REG_RSP));
|
|
||||||
shell_puts(temp_str);
|
|
||||||
|
|
||||||
for (i = 0UL; i < 8UL; i++) {
|
|
||||||
snprintf(temp_str, MAX_STR_SIZE,
|
|
||||||
"= 0x%016llx 0x%016llx "
|
|
||||||
"0x%016llx 0x%016llx\r\n",
|
|
||||||
tmp[i*4UL], tmp[(i*4UL)+1UL],
|
|
||||||
tmp[(i*4UL)+2UL], tmp[(i*4UL)+3UL]);
|
|
||||||
shell_puts(temp_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -248,6 +248,12 @@ struct vcpu {
|
|||||||
uint64_t reg_updated;
|
uint64_t reg_updated;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct vcpu_dump {
|
||||||
|
struct vcpu *vcpu;
|
||||||
|
char *str;
|
||||||
|
int str_max;
|
||||||
|
};
|
||||||
|
|
||||||
#define is_vcpu_bsp(vcpu) ((vcpu)->vcpu_id == BOOT_CPU_ID)
|
#define is_vcpu_bsp(vcpu) ((vcpu)->vcpu_id == BOOT_CPU_ID)
|
||||||
/* do not update Guest RIP for next VM Enter */
|
/* do not update Guest RIP for next VM Enter */
|
||||||
static inline void vcpu_retain_rip(struct vcpu *vcpu)
|
static inline void vcpu_retain_rip(struct vcpu *vcpu)
|
||||||
@ -289,6 +295,7 @@ int prepare_vcpu(struct vm *vm, uint16_t pcpu_id);
|
|||||||
|
|
||||||
void request_vcpu_pre_work(struct vcpu *vcpu, uint16_t pre_work_id);
|
void request_vcpu_pre_work(struct vcpu *vcpu, uint16_t pre_work_id);
|
||||||
|
|
||||||
|
void vcpu_dumpreg(void *data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user