hv:add pre-condition for vm APIs

check the vm state in hypercall api,
add pre-condition for vm api.

Tracked-On: #4320
Signed-off-by: Mingqiang Chi <mingqiang.chi@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Jason Chen CJ 2020-04-13 14:40:08 +08:00 committed by wenlingz
parent fe929d0a10
commit 0584981c03
3 changed files with 64 additions and 72 deletions

View File

@ -70,6 +70,14 @@ bool is_created_vm(const struct acrn_vm *vm)
return (vm->state == VM_CREATED); return (vm->state == VM_CREATED);
} }
/**
* @pre vm != NULL
*/
bool is_paused_vm(const struct acrn_vm *vm)
{
return (vm->state == VM_PAUSED);
}
bool is_sos_vm(const struct acrn_vm *vm) bool is_sos_vm(const struct acrn_vm *vm)
{ {
return (vm != NULL) && (get_vm_config(vm->vm_id)->load_order == SOS_VM); return (vm != NULL) && (get_vm_config(vm->vm_id)->load_order == SOS_VM);
@ -575,6 +583,7 @@ static int32_t offline_lapic_pt_enabled_pcpus(const struct acrn_vm *vm, uint64_t
/* /*
* @pre vm != NULL * @pre vm != NULL
* @pre vm->state == VM_PAUSED
*/ */
int32_t shutdown_vm(struct acrn_vm *vm) int32_t shutdown_vm(struct acrn_vm *vm)
{ {
@ -585,7 +594,6 @@ int32_t shutdown_vm(struct acrn_vm *vm)
int32_t ret = 0; int32_t ret = 0;
/* Only allow shutdown paused vm */ /* Only allow shutdown paused vm */
if (vm->state == VM_PAUSED) {
vm->state = VM_POWERED_OFF; vm->state = VM_POWERED_OFF;
vm_config = get_vm_config(vm->vm_id); vm_config = get_vm_config(vm->vm_id);
@ -610,9 +618,6 @@ int32_t shutdown_vm(struct acrn_vm *vm)
foreach_vcpu(i, vm, vcpu) { foreach_vcpu(i, vm, vcpu) {
offline_vcpu(vcpu); offline_vcpu(vcpu);
} }
} else {
ret = -EINVAL;
}
if (is_ready_for_system_shutdown()) { if (is_ready_for_system_shutdown()) {
/* If no any guest running, shutdown system */ /* If no any guest running, shutdown system */
@ -624,7 +629,8 @@ int32_t shutdown_vm(struct acrn_vm *vm)
} }
/** /**
* * @pre vm != NULL * @pre vm != NULL
* @pre vm->state == VM_CREATED
*/ */
void start_vm(struct acrn_vm *vm) void start_vm(struct acrn_vm *vm)
{ {
@ -639,7 +645,8 @@ void start_vm(struct acrn_vm *vm)
} }
/** /**
* * @pre vm != NULL * @pre vm != NULL
* @pre vm->state == VM_PAUSED
*/ */
int32_t reset_vm(struct acrn_vm *vm) int32_t reset_vm(struct acrn_vm *vm)
{ {
@ -648,7 +655,6 @@ int32_t reset_vm(struct acrn_vm *vm)
struct acrn_vcpu *vcpu = NULL; struct acrn_vcpu *vcpu = NULL;
int32_t ret = 0; int32_t ret = 0;
if (vm->state == VM_PAUSED) {
mask = lapic_pt_enabled_pcpu_bitmap(vm); mask = lapic_pt_enabled_pcpu_bitmap(vm);
if (mask != 0UL) { if (mask != 0UL) {
ret = offline_lapic_pt_enabled_pcpus(vm, mask); ret = offline_lapic_pt_enabled_pcpus(vm, mask);
@ -664,7 +670,7 @@ int32_t reset_vm(struct acrn_vm *vm)
vm->arch_vm.vlapic_state = VM_VLAPIC_XAPIC; vm->arch_vm.vlapic_state = VM_VLAPIC_XAPIC;
if (is_sos_vm(vm)) { if (is_sos_vm(vm)) {
(void )vm_sw_loader(vm); (void)vm_sw_loader(vm);
} }
reset_vm_ioreqs(vm); reset_vm_ioreqs(vm);
@ -672,43 +678,27 @@ int32_t reset_vm(struct acrn_vm *vm)
destroy_secure_world(vm, false); destroy_secure_world(vm, false);
vm->sworld_control.flag.active = 0UL; vm->sworld_control.flag.active = 0UL;
vm->state = VM_CREATED; vm->state = VM_CREATED;
} else {
ret = -EINVAL;
}
return ret; return ret;
} }
/** /**
* * @pre vm != NULL * @pre vm != NULL
*/ */
void pause_vm(struct acrn_vm *vm) void pause_vm(struct acrn_vm *vm)
{ {
uint16_t i; uint16_t i;
struct acrn_vcpu *vcpu = NULL; struct acrn_vcpu *vcpu = NULL;
if (vm->state != VM_PAUSED) { /* For RTVM, we can only pause its vCPUs when it is powering off by itself */
if (is_rt_vm(vm)) { if (((!is_rt_vm(vm)) && (vm->state == VM_RUNNING)) ||
/** ((is_rt_vm(vm)) && (vm->state == VM_READY_TO_POWEROFF)) ||
* For RTVM, we can only pause its vCPUs when it stays at following states: (vm->state == VM_CREATED)) {
* - It is powering off by itself
* - It is created but doesn't start
*/
if ((vm->state == VM_READY_TO_POWEROFF) || (vm->state == VM_CREATED)) {
foreach_vcpu(i, vm, vcpu) { foreach_vcpu(i, vm, vcpu) {
pause_vcpu(vcpu, VCPU_ZOMBIE); pause_vcpu(vcpu, VCPU_ZOMBIE);
} }
vm->state = VM_PAUSED; vm->state = VM_PAUSED;
} }
} else {
foreach_vcpu(i, vm, vcpu) {
pause_vcpu(vcpu, VCPU_ZOMBIE);
}
vm->state = VM_PAUSED;
}
}
} }
/** /**
@ -724,6 +714,7 @@ void pause_vm(struct acrn_vm *vm)
* @wakeup_vec[in] The resume address of vm * @wakeup_vec[in] The resume address of vm
* *
* @pre vm != NULL * @pre vm != NULL
* @pre is_sos_vm(vm) && vm->state == VM_PAUSED
*/ */
void resume_vm_from_s3(struct acrn_vm *vm, uint32_t wakeup_vec) void resume_vm_from_s3(struct acrn_vm *vm, uint32_t wakeup_vec)
{ {
@ -759,7 +750,7 @@ void prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config)
build_vacpi(vm); build_vacpi(vm);
} }
(void )vm_sw_loader(vm); (void)vm_sw_loader(vm);
/* start vm BSP automatically */ /* start vm BSP automatically */
start_vm(vm); start_vm(vm);

View File

@ -203,7 +203,7 @@ int32_t hcall_destroy_vm(uint16_t vmid)
int32_t ret = -1; int32_t ret = -1;
struct acrn_vm *target_vm = get_vm_from_vmid(vmid); struct acrn_vm *target_vm = get_vm_from_vmid(vmid);
if (!is_poweroff_vm(target_vm) && is_postlaunched_vm(target_vm)) { if (is_paused_vm(target_vm) && is_postlaunched_vm(target_vm)) {
/* TODO: check target_vm guest_flags */ /* TODO: check target_vm guest_flags */
ret = shutdown_vm(target_vm); ret = shutdown_vm(target_vm);
} }
@ -278,7 +278,7 @@ int32_t hcall_reset_vm(uint16_t vmid)
struct acrn_vm *target_vm = get_vm_from_vmid(vmid); struct acrn_vm *target_vm = get_vm_from_vmid(vmid);
int32_t ret = -1; int32_t ret = -1;
if (!is_poweroff_vm(target_vm) && is_postlaunched_vm(target_vm)) { if (is_paused_vm(target_vm) && is_postlaunched_vm(target_vm)) {
/* TODO: check target_vm guest_flags */ /* TODO: check target_vm guest_flags */
ret = reset_vm(target_vm); ret = reset_vm(target_vm);
} }

View File

@ -244,6 +244,7 @@ void prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config);
void launch_vms(uint16_t pcpu_id); void launch_vms(uint16_t pcpu_id);
bool is_poweroff_vm(const struct acrn_vm *vm); bool is_poweroff_vm(const struct acrn_vm *vm);
bool is_created_vm(const struct acrn_vm *vm); bool is_created_vm(const struct acrn_vm *vm);
bool is_paused_vm(const struct acrn_vm *vm);
bool is_sos_vm(const struct acrn_vm *vm); bool is_sos_vm(const struct acrn_vm *vm);
bool is_postlaunched_vm(const struct acrn_vm *vm); bool is_postlaunched_vm(const struct acrn_vm *vm);
bool is_prelaunched_vm(const struct acrn_vm *vm); bool is_prelaunched_vm(const struct acrn_vm *vm);