From 3cb32bb6e3784e2657bafb6c97d2f05fdc07c6f7 Mon Sep 17 00:00:00 2001 From: Shuo A Liu Date: Mon, 28 Oct 2019 12:03:21 +0800 Subject: [PATCH] hv: make init_vmcs as a event of VCPU After changing init_vmcs to smp call approach and do it before launch_vcpu, it could work with noop scheduler. On real sharing scheudler, it has problem. pcpu0 pcpu1 pcpu1 vmBvcpu0 vmAvcpu1 vmBvcpu1 vmentry init_vmcs(vmBvcpu1) vmexit->do_init_vmcs corrupt current vmcs vmentry fail launch_vcpu(vmBvcpu1) This patch mark a event flag when request vmcs init for specific vcpu. When it is running and checking pending events, will do init_vmcs firstly. Tracked-On: #4178 Signed-off-by: Shuo A Liu Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/virq.c | 6 ++++++ hypervisor/arch/x86/guest/vlapic.c | 3 +-- hypervisor/arch/x86/guest/vm.c | 2 +- hypervisor/arch/x86/guest/vmcs.c | 19 ++++--------------- hypervisor/common/hv_main.c | 4 ++-- hypervisor/include/arch/x86/guest/vcpu.h | 5 +++++ 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/hypervisor/arch/x86/guest/virq.c b/hypervisor/arch/x86/guest/virq.c index 603585345..a0be3c3d8 100644 --- a/hypervisor/arch/x86/guest/virq.c +++ b/hypervisor/arch/x86/guest/virq.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -357,6 +358,11 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu) struct acrn_vcpu_arch *arch = &vcpu->arch; uint64_t *pending_req_bits = &arch->pending_req; + /* make sure ACRN_REQUEST_INIT_VMCS handler as the first one */ + if (bitmap_test_and_clear_lock(ACRN_REQUEST_INIT_VMCS, pending_req_bits)) { + init_vmcs(vcpu); + } + if (bitmap_test_and_clear_lock(ACRN_REQUEST_TRP_FAULT, pending_req_bits)) { pr_fatal("Triple fault happen -> shutdown!"); ret = -EFAULT; diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 9ec000d0d..11bf2c37c 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -1192,8 +1192,7 @@ vlapic_process_init_sipi(struct acrn_vcpu* target_vcpu, uint32_t mode, uint32_t target_vcpu->vcpu_id, target_vcpu->vm->vm_id); set_vcpu_startup_entry(target_vcpu, (icr_low & APIC_VECTOR_MASK) << 12U); - /* init vmcs after set_vcpu_startup_entry */ - init_vmcs(target_vcpu); + vcpu_make_request(target_vcpu, ACRN_REQUEST_INIT_VMCS); launch_vcpu(target_vcpu); } } diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index e15c93f25..e0a4487c3 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -650,7 +650,7 @@ void start_vm(struct acrn_vm *vm) /* Only start BSP (vid = 0) and let BSP start other APs */ bsp = vcpu_from_vid(vm, BOOT_CPU_ID); - init_vmcs(bsp); + vcpu_make_request(bsp, ACRN_REQUEST_INIT_VMCS); launch_vcpu(bsp); } diff --git a/hypervisor/arch/x86/guest/vmcs.c b/hypervisor/arch/x86/guest/vmcs.c index 2bad083e0..e029b8b8a 100644 --- a/hypervisor/arch/x86/guest/vmcs.c +++ b/hypervisor/arch/x86/guest/vmcs.c @@ -496,7 +496,10 @@ static void init_exit_ctrl(const struct acrn_vcpu *vcpu) exec_vmwrite64(VMX_EXIT_MSR_LOAD_ADDR_FULL, hva2hpa((void *)vcpu->arch.msr_area.host)); } -static void do_init_vmcs(struct acrn_vcpu *vcpu) +/** + * @pre vcpu != NULL + */ +void init_vmcs(struct acrn_vcpu *vcpu) { uint64_t vmx_rev_id; uint64_t vmcs_pa; @@ -529,20 +532,6 @@ static void do_init_vmcs(struct acrn_vcpu *vcpu) init_exit_ctrl(vcpu); } -/** - * @pre vcpu != NULL - */ -void init_vmcs(struct acrn_vcpu *vcpu) -{ - uint16_t pcpu_id = pcpuid_from_vcpu(vcpu); - - if (pcpu_id == get_pcpu_id()) { - do_init_vmcs(vcpu); - } else { - smp_call_function((1UL << pcpu_id), (smp_call_func_t)do_init_vmcs, vcpu); - } -} - /** * @pre vcpu != NULL */ diff --git a/hypervisor/common/hv_main.c b/hypervisor/common/hv_main.c index a1a83eb9e..e94914975 100644 --- a/hypervisor/common/hv_main.c +++ b/hypervisor/common/hv_main.c @@ -37,7 +37,7 @@ void vcpu_thread(struct thread_object *obj) pr_fatal("vcpu handling pending request fail"); pause_vcpu(vcpu, VCPU_ZOMBIE); /* Fatal error happened (triple fault). Stop the vcpu running. */ - schedule(); + continue; } profiling_vmenter_handler(vcpu); @@ -48,7 +48,7 @@ void vcpu_thread(struct thread_object *obj) pr_fatal("vcpu resume failed"); pause_vcpu(vcpu, VCPU_ZOMBIE); /* Fatal error happened (resume vcpu failed). Stop the vcpu running. */ - schedule(); + continue; } basic_exit_reason = vcpu->arch.exit_reason & 0xFFFFU; TRACE_2L(TRACE_VM_EXIT, basic_exit_reason, vcpu_get_rip(vcpu)); diff --git a/hypervisor/include/arch/x86/guest/vcpu.h b/hypervisor/include/arch/x86/guest/vcpu.h index af04985d4..bfee6e4b6 100644 --- a/hypervisor/include/arch/x86/guest/vcpu.h +++ b/hypervisor/include/arch/x86/guest/vcpu.h @@ -86,6 +86,11 @@ */ #define ACRN_REQUEST_VPID_FLUSH 7U +/** + * @brief Request for initilizing VMCS + */ +#define ACRN_REQUEST_INIT_VMCS 8U + /** * @} */