diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index 45f83bfe5..f35453d21 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -513,7 +513,7 @@ int32_t create_vcpu(uint16_t pcpu_id, struct acrn_vm *vm, struct acrn_vcpu **rtn /* Populate the return handle */ *rtn_vcpu_handle = vcpu; - vcpu->state = VCPU_INIT; + vcpu_set_state(vcpu, VCPU_INIT); init_xsave(vcpu); vcpu_reset_internal(vcpu, POWER_ON_RESET); @@ -670,7 +670,7 @@ void offline_vcpu(struct acrn_vcpu *vcpu) /* This operation must be atomic to avoid contention with posted interrupt handler */ per_cpu(vcpu_array, pcpuid_from_vcpu(vcpu))[vcpu->vm->vm_id] = NULL; - vcpu->state = VCPU_OFFLINE; + vcpu_set_state(vcpu, VCPU_OFFLINE); } void kick_vcpu(const struct acrn_vcpu *vcpu) @@ -716,7 +716,7 @@ void reset_vcpu(struct acrn_vcpu *vcpu, enum reset_mode mode) pr_dbg("vcpu%hu reset", vcpu->vcpu_id); vcpu_reset_internal(vcpu, mode); - vcpu->state = VCPU_INIT; + vcpu_set_state(vcpu, VCPU_INIT); } void pause_vcpu(struct acrn_vcpu *vcpu, enum vcpu_state new_state) @@ -727,7 +727,7 @@ void pause_vcpu(struct acrn_vcpu *vcpu, enum vcpu_state new_state) if (((vcpu->state == VCPU_RUNNING) || (vcpu->state == VCPU_INIT)) && (new_state == VCPU_ZOMBIE)) { vcpu->prev_state = vcpu->state; - vcpu->state = new_state; + vcpu_set_state(vcpu, new_state); if (vcpu->prev_state == VCPU_RUNNING) { sleep_thread(&vcpu->thread_obj); @@ -747,7 +747,7 @@ int32_t resume_vcpu(struct acrn_vcpu *vcpu) pr_dbg("vcpu%hu resumed", vcpu->vcpu_id); if (vcpu->state == VCPU_PAUSED) { - vcpu->state = vcpu->prev_state; + vcpu_set_state(vcpu, vcpu->prev_state); if (vcpu->state == VCPU_RUNNING) { wake_thread(&vcpu->thread_obj); } @@ -818,7 +818,7 @@ void launch_vcpu(struct acrn_vcpu *vcpu) uint16_t pcpu_id = pcpuid_from_vcpu(vcpu); pr_dbg("vcpu%hu scheduled on pcpu%hu", vcpu->vcpu_id, pcpu_id); - vcpu->state = VCPU_RUNNING; + vcpu_set_state(vcpu, VCPU_RUNNING); wake_thread(&vcpu->thread_obj); } @@ -922,3 +922,17 @@ void vcpu_handle_pi_notification(uint32_t vcpu_index) } } } + +/* + * @brief Update the state of vCPU and state of vlapic + * + * The vlapic state of VM shall be updated for some vCPU + * state update cases, such as from VCPU_INIT to VCPU_RUNNING. + + * @pre (vcpu != NULL) + */ +void vcpu_set_state(struct acrn_vcpu *vcpu, enum vcpu_state new_state) +{ + vcpu->state = new_state; + update_vm_vlapic_state(vcpu->vm); +} diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 5a47a9110..8c89d3546 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -1135,6 +1135,7 @@ vlapic_process_init_sipi(struct acrn_vcpu* target_vcpu, uint32_t mode, uint32_t pr_err("Start Secondary VCPU%hu for VM[%d]...", target_vcpu->vcpu_id, target_vcpu->vm->vm_id); + set_vcpu_startup_entry(target_vcpu, (icr_low & APIC_VECTOR_MASK) << 12U); 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 1e61f9edc..655f95740 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -801,9 +801,6 @@ void launch_vms(uint16_t pcpu_id) * VM_VLAPIC_DISABLED - All the online vCPUs/vLAPICs of this VM are in Disabled mode * VM_VLAPIC_TRANSITION - Online vCPUs/vLAPICs of this VM are in between transistion * - * TODO: offline_vcpu need to call this API to reflect the status of rest of the - * vLAPICs that are online. - * * @pre vm != NULL */ void update_vm_vlapic_state(struct acrn_vm *vm) @@ -817,14 +814,17 @@ void update_vm_vlapic_state(struct acrn_vm *vm) vcpus_in_xapic = 0U; spinlock_obtain(&vm->vm_lock); foreach_vcpu(i, vm, vcpu) { - if (is_x2apic_enabled(vcpu_vlapic(vcpu))) { - vcpus_in_x2apic++; - } else if (is_xapic_enabled(vcpu_vlapic(vcpu))) { - vcpus_in_xapic++; - } else { - /* - * vCPU is using vLAPIC in Disabled mode - */ + /* Skip vCPU in state outside of VCPU_RUNNING as it may be offline. */ + if (vcpu->state == VCPU_RUNNING) { + if (is_x2apic_enabled(vcpu_vlapic(vcpu))) { + vcpus_in_x2apic++; + } else if (is_xapic_enabled(vcpu_vlapic(vcpu))) { + vcpus_in_xapic++; + } else { + /* + * vCPU is using vLAPIC in Disabled mode + */ + } } } diff --git a/hypervisor/include/arch/x86/guest/vcpu.h b/hypervisor/include/arch/x86/guest/vcpu.h index e07ffbe21..d51b1c25e 100644 --- a/hypervisor/include/arch/x86/guest/vcpu.h +++ b/hypervisor/include/arch/x86/guest/vcpu.h @@ -715,6 +715,17 @@ bool is_lapic_pt_enabled(struct acrn_vcpu *vcpu); * @return None */ void vcpu_handle_pi_notification(uint32_t vcpu_index); + +/* + * @brief Update the state of vCPU and state of vlapic + * + * The vlapic state of VM shall be updated for some vCPU + * state update cases, such as from VCPU_INIT to VCPU_RUNNING. + + * @pre (vcpu != NULL) + */ +void vcpu_set_state(struct acrn_vcpu *vcpu, enum vcpu_state new_state); + /** * @} */