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 <conghui.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Conghui Chen 2019-12-02 11:57:12 +00:00 committed by wenlingz
parent 47139bd78c
commit d48da2af3a
4 changed files with 24 additions and 16 deletions

View File

@ -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 acrn_vcpu *vcpu = list_entry(next, struct acrn_vcpu, thread_obj);
struct ext_context *ectx = &(vcpu->arch.contexts[vcpu->arch.cur_context].ext_ctx); 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_STAR, ectx->ia32_star);
msr_write(MSR_IA32_LSTAR, ectx->ia32_lstar); msr_write(MSR_IA32_LSTAR, ectx->ia32_lstar);

View File

@ -540,7 +540,7 @@ void init_vmcs(struct acrn_vcpu *vcpu)
/** /**
* @pre vcpu != NULL * @pre vcpu != NULL
*/ */
void switch_vmcs(const struct acrn_vcpu *vcpu) void load_vmcs(const struct acrn_vcpu *vcpu)
{ {
uint64_t vmcs_pa; uint64_t vmcs_pa;
void **vmcs_ptr = &get_cpu_var(vmcs_run); void **vmcs_ptr = &get_cpu_var(vmcs_run);

View File

@ -20,6 +20,7 @@
#include <logmsg.h> #include <logmsg.h>
#include <version.h> #include <version.h>
#include <shell.h> #include <shell.h>
#include <vmcs.h>
#define TEMP_STR_SIZE 60U #define TEMP_STR_SIZE 60U
#define MAX_STR_SIZE 256U #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 #define DUMPREG_SP_SIZE 32
/* the input 'data' must != NULL and indicate a vcpu structure pointer */ /* 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; int32_t status;
uint64_t i, fault_addr, tmp[DUMPREG_SP_SIZE]; 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; struct acrn_vcpu *vcpu = dump->vcpu;
char *str = dump->str; char *str = dump->str;
size_t len, size = dump->str_max; 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, len = snprintf(str, size,
"= VM ID %d ==== CPU ID %hu========================\r\n" "= VM ID %d ==== CPU ID %hu========================\r\n"
@ -764,6 +770,9 @@ static void vcpu_dumpreg(void *data)
str += len; str += len;
} }
} }
if (curr != NULL) {
load_vmcs(curr);
}
return; return;
overflow: overflow:
@ -818,12 +827,8 @@ static int32_t shell_vcpu_dumpreg(int32_t argc, char **argv)
dump.vcpu = vcpu; dump.vcpu = vcpu;
dump.str = shell_log_buf; dump.str = shell_log_buf;
dump.str_max = SHELL_LOG_BUF_SIZE; dump.str_max = SHELL_LOG_BUF_SIZE;
if (pcpu_id == get_pcpu_id()) { bitmap_set_nolock(pcpu_id, &mask);
vcpu_dumpreg(&dump); smp_call_function(mask, dump_vcpu_reg, &dump);
} else {
bitmap_set_nolock(pcpu_id, &mask);
smp_call_function(mask, vcpu_dumpreg, &dump);
}
shell_puts(shell_log_buf); shell_puts(shell_log_buf);
status = 0; status = 0;
@ -872,6 +877,10 @@ static void dump_guest_mem(void *data)
uint64_t length = dump->len; uint64_t length = dump->len;
uint64_t gva = dump->gva; uint64_t gva = dump->gva;
struct acrn_vcpu *vcpu = dump->vcpu; 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 */ /* Change the length to a multiple of 32 if the length is not */
loop_cnt = ((length & 0x1fUL) == 0UL) ? ((length >> 5UL)) : ((length >> 5UL) + 1UL); 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); shell_puts(temp_str);
gva += 32UL; gva += 32UL;
} }
if (curr != NULL) {
load_vmcs(curr);
}
} }
static int32_t shell_dump_guest_mem(int32_t argc, char **argv) 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; dump.len = length;
pcpu_id = pcpuid_from_vcpu(vcpu); pcpu_id = pcpuid_from_vcpu(vcpu);
if (pcpu_id == get_pcpu_id()) { bitmap_set_nolock(pcpu_id, &mask);
dump_guest_mem(&dump); smp_call_function(mask, dump_guest_mem, &dump);
} else {
bitmap_set_nolock(pcpu_id, &mask);
smp_call_function(mask, dump_guest_mem, &dump);
}
ret = 0; ret = 0;
} }

View File

@ -41,7 +41,7 @@ static inline uint64_t apic_access_offset(uint64_t qual)
return (qual & APIC_ACCESS_OFFSET); return (qual & APIC_ACCESS_OFFSET);
} }
void init_vmcs(struct acrn_vcpu *vcpu); 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); void switch_apicv_mode_x2apic(struct acrn_vcpu *vcpu);
#endif /* ASSEMBLER */ #endif /* ASSEMBLER */