hv: pm: avoid duplicate shutdowns on RTVM
It is possible for more than one vCPUs to trigger shutdown on an RTVM. We need to avoid entering VM_READY_TO_POWEROFF state again after the RTVM has been paused or shut down. Also, make sure an RTVM enters VM_READY_TO_POWEROFF state before it can be paused. v1 -> v2: - rename to poweroff_if_rt_vm for better clarity Tracked-On: #5411 Signed-off-by: Peter Fang <peter.fang@intel.com>
This commit is contained in:
parent
e6ca39406a
commit
68dc8d9f8f
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue