From 445999af5d3e471a98f750be89a94c733b03879f Mon Sep 17 00:00:00 2001 From: Victor Sun Date: Tue, 9 Apr 2019 20:39:49 +0800 Subject: [PATCH] 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 Acked-by: Eddie Dong --- hypervisor/arch/x86/configs/vm_config.c | 51 ++++++++++++++++++- hypervisor/arch/x86/guest/vm.c | 33 ++++-------- hypervisor/common/hypercall.c | 7 +-- hypervisor/include/arch/x86/guest/vm.h | 2 +- hypervisor/include/arch/x86/vm_config.h | 3 +- .../logical_partition/vm_configurations.c | 6 +++ hypervisor/scenarios/sdc/vm_configurations.c | 9 ++++ 7 files changed, 77 insertions(+), 34 deletions(-) diff --git a/hypervisor/arch/x86/configs/vm_config.c b/hypervisor/arch/x86/configs/vm_config.c index b357e9d73..1eed5219c 100644 --- a/hypervisor/arch/x86/configs/vm_config.c +++ b/hypervisor/arch/x86/configs/vm_config.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -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; } diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index c981a3c3d..a2f2deabd 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -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; diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index 1d6e0a9b6..e17aad930 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -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) diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index c309ecec1..5edb93d47 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -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); diff --git a/hypervisor/include/arch/x86/vm_config.h b/hypervisor/include/arch/x86/vm_config.h index d97f74c6e..988014df9 100644 --- a/hypervisor/include/arch/x86/vm_config.h +++ b/hypervisor/include/arch/x86/vm_config.h @@ -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]; diff --git a/hypervisor/scenarios/logical_partition/vm_configurations.c b/hypervisor/scenarios/logical_partition/vm_configurations.c index 9c81f19db..3317c9414 100644 --- a/hypervisor/scenarios/logical_partition/vm_configurations.c +++ b/hypervisor/scenarios/logical_partition/vm_configurations.c @@ -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, diff --git a/hypervisor/scenarios/sdc/vm_configurations.c b/hypervisor/scenarios/sdc/vm_configurations.c index 904070ad0..30df5b93e 100644 --- a/hypervisor/scenarios/sdc/vm_configurations.c +++ b/hypervisor/scenarios/sdc/vm_configurations.c @@ -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 */ + } };