diff --git a/hypervisor/arch/x86/guest/pm.c b/hypervisor/arch/x86/guest/pm.c index 60a23a53d..36fa180e8 100644 --- a/hypervisor/arch/x86/guest/pm.c +++ b/hypervisor/arch/x86/guest/pm.c @@ -291,7 +291,7 @@ static bool rt_vm_pm1a_io_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t wi pr_dbg("Invalid address (0x%x) or width (0x%x)", addr, width); } else { if ((((v & VIRTUAL_PM1A_SLP_EN) != 0U) && (((v & VIRTUAL_PM1A_SLP_TYP) >> 10U) == 5U)) != 0U) { - vcpu->vm->state = VM_READY_TO_POWEROFF; + poweroff_if_rt_vm(vcpu->vm); } } @@ -346,9 +346,7 @@ static bool prelaunched_vm_sleep_io_write(struct acrn_vcpu *vcpu, uint16_t addr, if (slp_en && (slp_type == 5U)) { get_vm_lock(vm); - if (is_rt_vm(vm)) { - vm->state = VM_READY_TO_POWEROFF; - } + poweroff_if_rt_vm(vm); pause_vm(vm); put_vm_lock(vm); diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 3d725abb9..eb2015cdf 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -722,6 +722,16 @@ int32_t reset_vm(struct acrn_vm *vm) return ret; } +/** + * @pre vm != NULL + */ +void poweroff_if_rt_vm(struct acrn_vm *vm) +{ + if (is_rt_vm(vm) && !is_paused_vm(vm) && !is_poweroff_vm(vm)) { + vm->state = VM_READY_TO_POWEROFF; + } +} + /** * @pre vm != NULL */ diff --git a/hypervisor/arch/x86/guest/vm_reset.c b/hypervisor/arch/x86/guest/vm_reset.c index bf9a72156..7ec419c57 100644 --- a/hypervisor/arch/x86/guest/vm_reset.c +++ b/hypervisor/arch/x86/guest/vm_reset.c @@ -49,6 +49,7 @@ void triple_fault_shutdown_vm(struct acrn_vcpu *vcpu) /* Either SOS or pre-launched VMs */ get_vm_lock(vm); + poweroff_if_rt_vm(vm); pause_vm(vm); put_vm_lock(vm); @@ -91,15 +92,13 @@ static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset) get_vm_lock(vm); if (reset) { + poweroff_if_rt_vm(vm); + if (get_highest_severity_vm(true) == vm) { reset_host(); } else if (is_postlaunched_vm(vm)) { /* re-inject to DM */ ret = false; - - if (is_rt_vm(vm)) { - vm->state = VM_READY_TO_POWEROFF; - } } else { /* * If it's SOS reset while RTVM is still alive @@ -117,8 +116,8 @@ static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset) ret = false; } /* - * ignore writes from SOS and pre-launched VM. - * equivalent to hide this port from guests. + * Ignore writes from SOS and pre-launched VM. + * Equivalent to hiding this port from the guest. */ } put_vm_lock(vm); diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index 70264746a..9994295dd 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -214,6 +214,7 @@ static inline uint16_t vmid_2_rel_vmid(uint16_t sos_vmid, uint16_t vmid) { void make_shutdown_vm_request(uint16_t pcpu_id); bool need_shutdown_vm(uint16_t pcpu_id); int32_t shutdown_vm(struct acrn_vm *vm); +void poweroff_if_rt_vm(struct acrn_vm *vm); void pause_vm(struct acrn_vm *vm); void resume_vm_from_s3(struct acrn_vm *vm, uint32_t wakeup_vec); void start_vm(struct acrn_vm *vm);