HV: make vm id statically by uuid

Currently VM id of NORMAL_VM is allocated dymatically, we need to make
VM id statically for FuSa compliance.

This patch will pre-configure UUID for all VMs, then NORMAL_VM could
get its VM id/configuration from vm_configs array by indexing the UUID.

If UUID collisions is found in vm configs array, HV will refuse to
load the VM;

Tracked-On: #2291

Signed-off-by: Victor Sun <victor.sun@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Victor Sun 2019-04-09 20:39:49 +08:00 committed by ACRN System Integration
parent cb10dc7e73
commit 445999af5d
7 changed files with 77 additions and 34 deletions

View File

@ -7,7 +7,6 @@
#include <vm_config.h>
#include <errno.h>
#include <acrn_common.h>
#include <page.h>
#include <logmsg.h>
#include <cat.h>
@ -20,6 +19,50 @@ struct acrn_vm_config *get_vm_config(uint16_t vm_id)
return &vm_configs[vm_id];
}
static inline bool uuid_is_equal(const uint8_t *uuid1, const uint8_t *uuid2)
{
uint64_t uuid1_h = *(uint64_t *)uuid1;
uint64_t uuid1_l = *(uint64_t *)(uuid1 + 8);
uint64_t uuid2_h = *(uint64_t *)uuid2;
uint64_t uuid2_l = *(uint64_t *)(uuid2 + 8);
return ((uuid1_h == uuid2_h) && (uuid1_l == uuid2_l));
}
/**
* return true if the input uuid is configured in VM
*
* @pre vmid < CONFIG_MAX_VM_NUM
*/
bool vm_has_matched_uuid(uint16_t vmid, const uint8_t *uuid)
{
struct acrn_vm_config *vm_config = get_vm_config(vmid);
return (uuid_is_equal(&vm_config->uuid[0], uuid));
}
/**
* return true if no UUID collision is found in vm configs array start from vm_configs[vm_id]
*
* @pre vm_id < CONFIG_MAX_VM_NUM
*/
static bool check_vm_uuid_collision(uint16_t vm_id)
{
uint16_t i;
bool ret = true;
struct acrn_vm_config *start_config = get_vm_config(vm_id);
struct acrn_vm_config *following_config;
for (i = vm_id + 1U; i < CONFIG_MAX_VM_NUM; i++) {
following_config = get_vm_config(i);
if (uuid_is_equal(&start_config->uuid[0], &following_config->uuid[0])) {
ret = false;
break;
}
}
return ret;
}
/**
* @pre vm_config != NULL
*/
@ -62,7 +105,7 @@ bool sanitize_vm_config(void)
}
break;
case NORMAL_VM:
ret = false;
/* Nothing to do here for a NORMAL_VM, break directly. */
break;
default:
/* Nothing to do for a UNDEFINED_VM, break directly. */
@ -78,6 +121,10 @@ bool sanitize_vm_config(void)
}
}
if (ret) {
/* make sure no identical UUID in following VM configurations */
ret = check_vm_uuid_collision(vm_id);
}
if (!ret) {
break;
}

View File

@ -34,28 +34,17 @@ static struct acrn_vm vm_array[CONFIG_MAX_VM_NUM] __aligned(PAGE_SIZE);
static struct acrn_vm *sos_vm_ptr = NULL;
uint16_t find_free_vm_id(void)
uint16_t get_vmid_by_uuid(const uint8_t *uuid)
{
uint16_t id;
struct acrn_vm_config *vm_config;
uint16_t vm_id = 0U;
for (id = 0U; id < CONFIG_MAX_VM_NUM; id++) {
vm_config = get_vm_config(id);
if (vm_config->type == UNDEFINED_VM) {
while (!vm_has_matched_uuid(vm_id, uuid)) {
vm_id++;
if (vm_id == CONFIG_MAX_VM_NUM) {
break;
}
}
return (vm_config->type == UNDEFINED_VM) ? id : INVALID_VM_ID;
}
/**
* @pre vm != NULL && vm->vmid < CONFIG_MAX_VM_NUM
*/
static inline void free_vm_id(const struct acrn_vm *vm)
{
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
vm_config->type = UNDEFINED_VM;
return vm_id;
}
bool is_valid_vm(const struct acrn_vm *vm)
@ -363,6 +352,9 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
register_mmio_default_emulation_handler(vm);
}
(void)memcpy_s(&vm->uuid[0], sizeof(vm->uuid),
&vm_config->uuid[0], sizeof(vm_config->uuid));
if (is_sos_vm(vm)) {
/* Only for SOS_VM */
create_sos_vm_e820(vm);
@ -392,9 +384,6 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
snprintf(vm_config->name, 16, "ACRN VM_%d", vm_id);
}
(void)memcpy_s(&vm->uuid[0], sizeof(vm->uuid),
&vm_config->uuid[0], sizeof(vm_config->uuid));
if (vm_config->type == PRE_LAUNCHED_VM) {
create_prelaunched_vm_e820(vm);
prepare_prelaunched_vm_memmap(vm, vm_config);
@ -469,7 +458,6 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
if (vm->arch_vm.nworld_eptp != NULL) {
(void)memset(vm->arch_vm.nworld_eptp, 0U, PAGE_SIZE);
}
free_vm_id(vm);
}
return status;
}
@ -506,9 +494,6 @@ int32_t shutdown_vm(struct acrn_vm *vm)
/* Free EPT allocated resources assigned to VM */
destroy_ept(vm);
/* Free vm id */
free_vm_id(vm);
ret = 0;
} else {
ret = -EINVAL;

View File

@ -126,15 +126,10 @@ int32_t hcall_create_vm(struct acrn_vm *vm, uint64_t param)
(void)memset((void *)&cv, 0U, sizeof(cv));
if (copy_from_gpa(vm, &cv, param, sizeof(cv)) == 0) {
/* check whether there is a free vm id for use */
/* TODO: pass vm id from DM to make vm_id static */
vm_id = find_free_vm_id();
vm_id = get_vmid_by_uuid(&cv.uuid[0]);
if (vm_id < CONFIG_MAX_VM_NUM) {
vm_config = get_vm_config(vm_id);
/* TODO: set by DM */
vm_config->type = NORMAL_VM;
vm_config->guest_flags |= cv.vm_flag;
(void)memcpy_s(&vm_config->uuid[0], 16U, &cv.uuid[0], 16U);
/* GUEST_FLAG_RT must be set if we have GUEST_FLAG_LAPIC_PASSTHROUGH set in guest_flags */
if (((vm_config->guest_flags & GUEST_FLAG_LAPIC_PASSTHROUGH) != 0U)

View File

@ -213,7 +213,7 @@ void launch_vms(uint16_t pcpu_id);
bool is_valid_vm(const struct acrn_vm *vm);
bool is_sos_vm(const struct acrn_vm *vm);
bool is_prelaunched_vm(const struct acrn_vm *vm);
uint16_t find_free_vm_id(void);
uint16_t get_vmid_by_uuid(const uint8_t *uuid);
struct acrn_vm *get_vm_from_vmid(uint16_t vm_id);
struct acrn_vm *get_sos_vm(void);

View File

@ -45,7 +45,7 @@ struct acrn_vm_pci_ptdev_config {
struct acrn_vm_config {
enum acrn_vm_type type; /* specify the type of VM */
char name[MAX_VM_OS_NAME_LEN]; /* VM name identifier, useful for debug. */
uint8_t uuid[16]; /* UUID of the VM */
const uint8_t uuid[16]; /* UUID of the VM */
uint64_t pcpu_bitmap; /* from pcpu bitmap, we could know VM core number */
uint64_t guest_flags; /* VM flags that we want to configure for guest
* Now we have two flags:
@ -63,6 +63,7 @@ struct acrn_vm_config {
} __aligned(8);
struct acrn_vm_config *get_vm_config(uint16_t vm_id);
bool vm_has_matched_uuid(uint16_t vmid, const uint8_t *uuid);
bool sanitize_vm_config(void);
extern struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM];

View File

@ -15,6 +15,9 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
{ /* VM0 */
.type = PRE_LAUNCHED_VM,
.name = "ACRN PRE-LAUNCHED VM0",
.uuid = {0x26U, 0xc5U, 0xe0U, 0xd8U, 0x8fU, 0x8aU, 0x47U, 0xd8U, \
0x81U, 0x09U, 0xf2U, 0x01U, 0xebU, 0xd6U, 0x1aU, 0x5eU},
/* 26c5e0d8-8f8a-47d8-8109-f201ebd61a5e */
.pcpu_bitmap = VM0_CONFIG_PCPU_BITMAP,
.guest_flags = GUEST_FLAG_IO_COMPLETION_POLLING,
.clos = 0U,
@ -38,6 +41,9 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
{ /* VM1 */
.type = PRE_LAUNCHED_VM,
.name = "ACRN PRE-LAUNCHED VM1",
.uuid = {0xddU, 0x87U, 0xceU, 0x08U, 0x66U, 0xf9U, 0x47U, 0x3dU, \
0xbcU, 0x58U, 0x76U, 0x05U, 0x83U, 0x7fU, 0x93U, 0x5eU},
/* dd87ce08-66f9-473d-bc58-7605837f935e */
.pcpu_bitmap = VM1_CONFIG_PCPU_BITMAP,
.guest_flags = GUEST_FLAG_IO_COMPLETION_POLLING,
.clos = 0U,

View File

@ -12,6 +12,9 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
{
.type = SOS_VM,
.name = "ACRN SOS VM",
.uuid = {0xdbU, 0xbbU, 0xd4U, 0x34U, 0x7aU, 0x57U, 0x42U, 0x16U, \
0xa1U, 0x2cU, 0x22U, 0x01U, 0xf1U, 0xabU, 0x02U, 0x40U},
/* dbbbd434-7a57-4216-a12c-2201f1ab0240 */
.guest_flags = GUEST_FLAG_IO_COMPLETION_POLLING,
.clos = 0U,
.memory = {
@ -22,4 +25,10 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
.name = "ACRN Service OS",
},
},
{
.type = NORMAL_VM,
.uuid = {0xd2U, 0x79U, 0x54U, 0x38U, 0x25U, 0xd6U, 0x11U, 0xe8U, \
0x86U, 0x4eU, 0xcbU, 0x7aU, 0x18U, 0xb3U, 0x46U, 0x43U},
/* d2795438-25d6-11e8-864e-cb7a18b34643 */
}
};