hv: don't overwrite the statically configured vm_configs[] in hypercall

The statically configured vm_configs[].cpu_affinity_bitmap should remain
intact during the life cycle of the SOS, otherwise user can't destroy
and create the same VM with different CPU affinity. For example:

- Initially vm_configs[1].cpu_affinity_bitmap is set to 0xF: pCPU 0/1/2/3.
- VM1 is created on pCPU1 and pCPU2 and vm_configs[1].cpu_affinity_bitmap
  is overwritten as 0x6.
- VM1 is destroyed.
- Now VM1 can't be launched again on pCPU0 or pCPU3.

This patch fixes this by saving the static VM configuration before the
create_vm hypercall and restore it when the post-launched VM is shutting
down.

Tracked-On: #4616
Signed-off-by: Zide Chen <zide.chen@intel.com>
This commit is contained in:
Zide Chen 2020-03-23 19:05:15 -07:00 committed by wenlingz
parent cbaf3e782e
commit c390ab01cd
4 changed files with 30 additions and 4 deletions

View File

@ -14,6 +14,15 @@
static uint8_t rtvm_uuid1[16] = POST_RTVM_UUID1; static uint8_t rtvm_uuid1[16] = POST_RTVM_UUID1;
static uint8_t safety_vm_uuid1[16] = SAFETY_VM_UUID1; static uint8_t safety_vm_uuid1[16] = SAFETY_VM_UUID1;
/*
* To be used for post-launched VMS only.
*
* acrn-dm could modify post-launched VM configuration through command line arguments.
* We make use of this additional array to make sure that the dynamic configuration
* from acrn-dm won't overwrite the static vm_configs[].
*/
static struct acrn_vm_config vm_configs_saved[CONFIG_MAX_VM_NUM];
/* /*
* @pre vm_id < CONFIG_MAX_VM_NUM * @pre vm_id < CONFIG_MAX_VM_NUM
* @post return != NULL * @post return != NULL
@ -23,6 +32,20 @@ struct acrn_vm_config *get_vm_config(uint16_t vm_id)
return &vm_configs[vm_id]; return &vm_configs[vm_id];
} }
/*
* @pre vm_id < CONFIG_MAX_VM_NUM
*/
void save_or_restore_vm_config(uint16_t vm_id, bool save)
{
size_t size = sizeof(struct acrn_vm_config);
if (save) {
(void)memcpy_s((void *)&vm_configs_saved[vm_id], size, (void *)&vm_configs[vm_id], size);
} else {
(void)memcpy_s((void *)&vm_configs[vm_id], size, (void *)&vm_configs_saved[vm_id], size);
}
}
static inline bool uuid_is_equal(const uint8_t *uuid1, const uint8_t *uuid2) static inline bool uuid_is_equal(const uint8_t *uuid1, const uint8_t *uuid2)
{ {
uint64_t uuid1_h = *(const uint64_t *)uuid1; uint64_t uuid1_h = *(const uint64_t *)uuid1;

View File

@ -585,7 +585,6 @@ int32_t shutdown_vm(struct acrn_vm *vm)
uint16_t i; uint16_t i;
uint64_t mask; uint64_t mask;
struct acrn_vcpu *vcpu = NULL; struct acrn_vcpu *vcpu = NULL;
struct acrn_vm_config *vm_config = NULL;
int32_t ret = 0; int32_t ret = 0;
pause_vm(vm); pause_vm(vm);
@ -603,9 +602,6 @@ int32_t shutdown_vm(struct acrn_vm *vm)
offline_vcpu(vcpu); offline_vcpu(vcpu);
} }
vm_config = get_vm_config(vm->vm_id);
vm_config->guest_flags &= ~DM_OWNED_GUEST_FLAG_MASK;
if (is_sos_vm(vm)) { if (is_sos_vm(vm)) {
sbuf_reset(); sbuf_reset();
} }

View File

@ -161,6 +161,9 @@ int32_t hcall_create_vm(struct acrn_vm *vm, uint64_t param)
vm_id = get_vmid_by_uuid(&cv.uuid[0]); vm_id = get_vmid_by_uuid(&cv.uuid[0]);
if ((vm_id > vm->vm_id) && (vm_id < CONFIG_MAX_VM_NUM) if ((vm_id > vm->vm_id) && (vm_id < CONFIG_MAX_VM_NUM)
&& (is_poweroff_vm(get_vm_from_vmid(vm_id)))) { && (is_poweroff_vm(get_vm_from_vmid(vm_id)))) {
/* Save a copy of the static vm configuration */
save_or_restore_vm_config(vm_id, true);
vm_config = get_vm_config(vm_id); vm_config = get_vm_config(vm_id);
/* Filter out the bits should not set by DM and then assign it to guest_flags */ /* Filter out the bits should not set by DM and then assign it to guest_flags */
@ -220,6 +223,9 @@ int32_t hcall_destroy_vm(uint16_t vmid)
if (!is_poweroff_vm(target_vm) && is_postlaunched_vm(target_vm)) { if (!is_poweroff_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);
/* restore with the static vm configuration */
save_or_restore_vm_config(vmid, false);
} }
return ret; return ret;

View File

@ -175,6 +175,7 @@ struct acrn_vm_config {
} __aligned(8); } __aligned(8);
struct acrn_vm_config *get_vm_config(uint16_t vm_id); struct acrn_vm_config *get_vm_config(uint16_t vm_id);
void save_or_restore_vm_config(uint16_t vm_id, bool save);
bool vm_has_matched_uuid(uint16_t vmid, const uint8_t *uuid); bool vm_has_matched_uuid(uint16_t vmid, const uint8_t *uuid);
bool sanitize_vm_config(void); bool sanitize_vm_config(void);