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:
Peter Fang 2020-11-05 17:40:54 -08:00 committed by wenlingz
parent e6ca39406a
commit 68dc8d9f8f
4 changed files with 18 additions and 10 deletions

View File

@ -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);

View File

@ -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
*/

View File

@ -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);

View File

@ -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);