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,33 +594,29 @@ 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);
vm_config->guest_flags &= ~DM_OWNED_GUEST_FLAG_MASK; vm_config->guest_flags &= ~DM_OWNED_GUEST_FLAG_MASK;
if (is_sos_vm(vm)) { if (is_sos_vm(vm)) {
sbuf_reset(); sbuf_reset();
} }
deinit_vuart(vm); deinit_vuart(vm);
deinit_vpci(vm); deinit_vpci(vm);
/* Free EPT allocated resources assigned to VM */ /* Free EPT allocated resources assigned to VM */
destroy_ept(vm); destroy_ept(vm);
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);
} }
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()) {
@ -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,66 +655,49 @@ 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);
}
foreach_vcpu(i, vm, vcpu) {
reset_vcpu(vcpu, COLD_RESET);
}
/*
* Set VM vLAPIC state to VM_VLAPIC_XAPIC
*/
vm->arch_vm.vlapic_state = VM_VLAPIC_XAPIC;
if (is_sos_vm(vm)) {
(void )vm_sw_loader(vm);
}
reset_vm_ioreqs(vm);
reset_vioapics(vm);
destroy_secure_world(vm, false);
vm->sworld_control.flag.active = 0UL;
vm->state = VM_CREATED;
} else {
ret = -EINVAL;
} }
foreach_vcpu(i, vm, vcpu) {
reset_vcpu(vcpu, COLD_RESET);
}
/*
* Set VM vLAPIC state to VM_VLAPIC_XAPIC
*/
vm->arch_vm.vlapic_state = VM_VLAPIC_XAPIC;
if (is_sos_vm(vm)) {
(void)vm_sw_loader(vm);
}
reset_vm_ioreqs(vm);
reset_vioapics(vm);
destroy_secure_world(vm, false);
vm->sworld_control.flag.active = 0UL;
vm->state = VM_CREATED;
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 foreach_vcpu(i, vm, vcpu) {
* - It is created but doesn't start pause_vcpu(vcpu, VCPU_ZOMBIE);
*/
if ((vm->state == VM_READY_TO_POWEROFF) || (vm->state == VM_CREATED)) {
foreach_vcpu(i, vm, vcpu) {
pause_vcpu(vcpu, VCPU_ZOMBIE);
}
vm->state = VM_PAUSED;
}
} else {
foreach_vcpu(i, vm, vcpu) {
pause_vcpu(vcpu, VCPU_ZOMBIE);
}
vm->state = VM_PAUSED;
} }
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);