From d48da2af3aa02fe69c7413bc78e646e8244db4ae Mon Sep 17 00:00:00 2001 From: Conghui Chen Date: Mon, 2 Dec 2019 11:57:12 +0000 Subject: [PATCH] hv: bugfix for debug commands with smp_call With cpu-sharing enabled, there are more than 1 vcpu on 1 pcpu, so the smp_call handler should switch the vmcs to the target vcpu's vmcs. Then get the info. dump_vcpu_reg and dump_guest_mem should run on certain vmcs, otherwise, there will be #GP error. Renaming: vcpu_dumpreg -> dump_vcpu_reg switch_vmcs -> load_vmcs Tracked-On: #4178 Signed-off-by: Conghui Chen Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/vcpu.c | 2 +- hypervisor/arch/x86/guest/vmcs.c | 2 +- hypervisor/debug/shell.c | 34 +++++++++++++++--------- hypervisor/include/arch/x86/guest/vmcs.h | 2 +- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index 42aa69902..3aaf1c387 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -768,7 +768,7 @@ static void context_switch_in(struct thread_object *next) struct acrn_vcpu *vcpu = list_entry(next, struct acrn_vcpu, thread_obj); struct ext_context *ectx = &(vcpu->arch.contexts[vcpu->arch.cur_context].ext_ctx); - switch_vmcs(vcpu); + load_vmcs(vcpu); msr_write(MSR_IA32_STAR, ectx->ia32_star); msr_write(MSR_IA32_LSTAR, ectx->ia32_lstar); diff --git a/hypervisor/arch/x86/guest/vmcs.c b/hypervisor/arch/x86/guest/vmcs.c index 09de997d7..6e2d76692 100644 --- a/hypervisor/arch/x86/guest/vmcs.c +++ b/hypervisor/arch/x86/guest/vmcs.c @@ -540,7 +540,7 @@ void init_vmcs(struct acrn_vcpu *vcpu) /** * @pre vcpu != NULL */ -void switch_vmcs(const struct acrn_vcpu *vcpu) +void load_vmcs(const struct acrn_vcpu *vcpu) { uint64_t vmcs_pa; void **vmcs_ptr = &get_cpu_var(vmcs_run); diff --git a/hypervisor/debug/shell.c b/hypervisor/debug/shell.c index ddd253af2..ccd5d377a 100644 --- a/hypervisor/debug/shell.c +++ b/hypervisor/debug/shell.c @@ -20,6 +20,7 @@ #include #include #include +#include #define TEMP_STR_SIZE 60U #define MAX_STR_SIZE 256U @@ -686,7 +687,7 @@ static int32_t shell_list_vcpu(__unused int32_t argc, __unused char **argv) #define DUMPREG_SP_SIZE 32 /* the input 'data' must != NULL and indicate a vcpu structure pointer */ -static void vcpu_dumpreg(void *data) +static void dump_vcpu_reg(void *data) { int32_t status; uint64_t i, fault_addr, tmp[DUMPREG_SP_SIZE]; @@ -695,6 +696,11 @@ static void vcpu_dumpreg(void *data) struct acrn_vcpu *vcpu = dump->vcpu; char *str = dump->str; size_t len, size = dump->str_max; + uint16_t pcpu_id = get_pcpu_id(); + struct acrn_vcpu *curr = get_running_vcpu(pcpu_id); + + /* switch vmcs */ + load_vmcs(vcpu); len = snprintf(str, size, "= VM ID %d ==== CPU ID %hu========================\r\n" @@ -764,6 +770,9 @@ static void vcpu_dumpreg(void *data) str += len; } } + if (curr != NULL) { + load_vmcs(curr); + } return; overflow: @@ -818,12 +827,8 @@ static int32_t shell_vcpu_dumpreg(int32_t argc, char **argv) dump.vcpu = vcpu; dump.str = shell_log_buf; dump.str_max = SHELL_LOG_BUF_SIZE; - if (pcpu_id == get_pcpu_id()) { - vcpu_dumpreg(&dump); - } else { - bitmap_set_nolock(pcpu_id, &mask); - smp_call_function(mask, vcpu_dumpreg, &dump); - } + bitmap_set_nolock(pcpu_id, &mask); + smp_call_function(mask, dump_vcpu_reg, &dump); shell_puts(shell_log_buf); status = 0; @@ -872,6 +877,10 @@ static void dump_guest_mem(void *data) uint64_t length = dump->len; uint64_t gva = dump->gva; struct acrn_vcpu *vcpu = dump->vcpu; + uint16_t pcpu_id = get_pcpu_id(); + struct acrn_vcpu *curr = get_running_vcpu(pcpu_id); + + load_vmcs(vcpu); /* Change the length to a multiple of 32 if the length is not */ loop_cnt = ((length & 0x1fUL) == 0UL) ? ((length >> 5UL)) : ((length >> 5UL) + 1UL); @@ -887,6 +896,9 @@ static void dump_guest_mem(void *data) shell_puts(temp_str); gva += 32UL; } + if (curr != NULL) { + load_vmcs(curr); + } } static int32_t shell_dump_guest_mem(int32_t argc, char **argv) @@ -916,12 +928,8 @@ static int32_t shell_dump_guest_mem(int32_t argc, char **argv) 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); - } + bitmap_set_nolock(pcpu_id, &mask); + smp_call_function(mask, dump_guest_mem, &dump); ret = 0; } diff --git a/hypervisor/include/arch/x86/guest/vmcs.h b/hypervisor/include/arch/x86/guest/vmcs.h index 5bb94951a..752946f57 100644 --- a/hypervisor/include/arch/x86/guest/vmcs.h +++ b/hypervisor/include/arch/x86/guest/vmcs.h @@ -41,7 +41,7 @@ static inline uint64_t apic_access_offset(uint64_t qual) return (qual & APIC_ACCESS_OFFSET); } void init_vmcs(struct acrn_vcpu *vcpu); -void switch_vmcs(const struct acrn_vcpu *vcpu); +void load_vmcs(const struct acrn_vcpu *vcpu); void switch_apicv_mode_x2apic(struct acrn_vcpu *vcpu); #endif /* ASSEMBLER */