From a6ff3a9bdcb33e40851075973f318eecc2523b7d Mon Sep 17 00:00:00 2001 From: Jason Chen CJ Date: Tue, 15 May 2018 10:57:24 +0800 Subject: [PATCH] vm: allocated all pcpus to vm0 at the beginning allocated all pcpus to vm0 to handle possible AP wakeup flow for all cpus, as we pass org ACPI table to VM0 - that means VM0 can see all CPUs. SOS(VM0) start expected CPUs through "maxcpus=" kernel cmdline option. During first hypercall from SOS, calling vm_fixup to free un-expect-enabled vcpus from VM0. Signed-off-by: Jason Chen CJ Acked-by: Xu, Anthony Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/vm.c | 62 +++++++++++++++++++++++--- hypervisor/arch/x86/guest/vmcall.c | 4 ++ hypervisor/include/arch/x86/guest/vm.h | 2 + 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 324f64f37..d23d6c2e9 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -56,7 +56,14 @@ static void init_vm(struct vm_description *vm_desc, struct vm *vm_handle) { /* Populate VM attributes from VM description */ - vm_handle->hw.num_vcpus = vm_desc->vm_hw_num_cores; + if (is_vm0(vm_handle)) { + /* Allocate all cpus to vm0 at the beginning */ + vm_handle->hw.num_vcpus = phy_cpu_num; + vm_handle->hw.exp_num_vcpus = vm_desc->vm_hw_num_cores; + } else { + vm_handle->hw.num_vcpus = vm_desc->vm_hw_num_cores; + vm_handle->hw.exp_num_vcpus = vm_desc->vm_hw_num_cores; + } vm_handle->state_info.privilege = vm_desc->vm_state_info_privilege; vm_handle->state_info.boot_count = 0; } @@ -316,11 +323,9 @@ int prepare_vm0(void) ret = create_vm(vm_desc, &vm); ASSERT(ret == 0, "VM creation failed!"); - prepare_vcpu(vm, vm_desc->vm_hw_logical_core_ids[0]); - - /* Prepare the AP for vm0 */ - for (i = 1; i < vm_desc->vm_hw_num_cores; i++) - prepare_vcpu(vm, vm_desc->vm_hw_logical_core_ids[i]); + /* Allocate all cpus to vm0 at the beginning */ + for (i = 0; i < phy_cpu_num; i++) + prepare_vcpu(vm, i); /* start vm0 BSP automatically */ start_vm(vm); @@ -329,3 +334,48 @@ int prepare_vm0(void) return 0; } + +static inline bool vcpu_in_vm_desc(struct vcpu *vcpu, + struct vm_description *vm_desc) +{ + int i; + + for (i = 0; i < vm_desc->vm_hw_num_cores; i++) { + if (vcpu->pcpu_id == vm_desc->vm_hw_logical_core_ids[i]) + return true; + } + + return false; +} + +/* + * fixup vm0 for expected vcpu: + * vm0 is starting with all physical cpus, it's mainly for UEFI boot to + * handle all physical mapped APs wakeup during boot service exit. + * this fixup is used to pause then destroy non-expect-enabled vcpus from VM0. + * + * NOTE: if you want to enable mult-vpucs for vm0, please make sure the pcpu_id + * is in order, for example: + * - one vcpu: VM0_CPUS[VM0_NUM_CPUS] = {0}; + * - two vcpus: VM0_CPUS[VM0_NUM_CPUS] = {0, 1}; + * - three vcpus: VM0_CPUS[VM0_NUM_CPUS] = {0, 1, 2}; + */ +void vm_fixup(struct vm *vm) +{ + if (is_vm0(vm) && (vm->hw.exp_num_vcpus < vm->hw.num_vcpus)) { + struct vm_description *vm_desc = NULL; + struct vcpu *vcpu; + int i; + + vm_desc = get_vm_desc(0); + foreach_vcpu(i, vm, vcpu) { + if (!vcpu_in_vm_desc(vcpu, vm_desc)) { + pause_vcpu(vcpu, VCPU_ZOMBIE); + reset_vcpu(vcpu); + destroy_vcpu(vcpu); + } + } + + vm->hw.num_vcpus = vm->hw.exp_num_vcpus; + } +} diff --git a/hypervisor/arch/x86/guest/vmcall.c b/hypervisor/arch/x86/guest/vmcall.c index cb2772359..3bb163558 100644 --- a/hypervisor/arch/x86/guest/vmcall.c +++ b/hypervisor/arch/x86/guest/vmcall.c @@ -55,6 +55,10 @@ int vmcall_vmexit_handler(struct vcpu *vcpu) /* Dispatch the hypercall handler */ switch (hypcall_id) { case HC_GET_API_VERSION: + /* vm0 will call HC_GET_API_VERSION as first hypercall, fixup + * vm0 vcpu here. + */ + vm_fixup(vm); ret = hcall_get_api_version(vm, param1); break; diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index 3b608921c..5b264a1ad 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -46,6 +46,7 @@ struct vm_attr { struct vm_hw_info { int num_vcpus; /* Number of total virtual cores */ + int exp_num_vcpus; /* Number of real expected virtual cores */ uint32_t created_vcpus; /* Number of created vcpus */ struct vcpu **vcpu_array; /* vcpu array of this VM */ uint64_t gpa_lowtop; /* top lowmem gpa of this VM */ @@ -218,6 +219,7 @@ int pause_vm(struct vm *vm); int start_vm(struct vm *vm); int create_vm(struct vm_description *vm_desc, struct vm **vm); int prepare_vm0(void); +void vm_fixup(struct vm *vm); struct vm *get_vm_from_vmid(int vm_id); struct vm_description *get_vm_desc(int idx);