From 66e002302933e0c98b39504aed78396d65da46a7 Mon Sep 17 00:00:00 2001 From: Victor Sun Date: Thu, 24 Jan 2019 22:37:51 +0800 Subject: [PATCH] HV: sanitize vm config Add a API to sanitize vm_configs[] array, in this API, we will do sanity check for VM configurations and refill some fields in vm_configs[]. If sanity check is failed, the HV would reject to boot. About pcpu_bitmap of SOS_VM: We should not hard code pcpu_bitmap for SOS_VM, this is not convenient for unconfigured boards. The pcpu_bitmap follows a very simple rule: All physical CPUs except ocuppied by Pre-launched VMs are all belong to SOS_VM. In this way, the pcpu_bitmap of a SOS_VM is decided by pcpu_bitmap status in PRE_LAUNCHED_VMs. To get the correct pcpu_bitmap of SOS_VM, We need to setup another rule, that the vm_configs[] array should follow the order of PRE_LAUNCHED_VM - SOS_VM strictly. With this patch enabled, the pcpu_bitmap field of sos vm config is not needed to configure; Tracked-On: #2291 Signed-off-by: Victor Sun Acked-by: Eddie Dong --- hypervisor/arch/x86/configs/sharing_config.c | 1 - hypervisor/arch/x86/cpu.c | 4 ++ hypervisor/arch/x86/guest/vm.c | 51 ++++++++++++++++++++ hypervisor/include/arch/x86/guest/vm.h | 1 + 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/hypervisor/arch/x86/configs/sharing_config.c b/hypervisor/arch/x86/configs/sharing_config.c index f42f48ec7..6c0a50500 100644 --- a/hypervisor/arch/x86/configs/sharing_config.c +++ b/hypervisor/arch/x86/configs/sharing_config.c @@ -11,7 +11,6 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] __aligned(PAGE_SIZE) = { { .type = SOS_VM, .name = SOS_VM_CONFIG_NAME, - .pcpu_bitmap = SOS_VM_CONFIG_PCPU_BITMAP, .guest_flags = SOS_VM_CONFIG_GUEST_FLAGS, .memory = { .start_hpa = 0x0UL, diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index f488bfd6e..0c723b2d3 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -171,6 +171,10 @@ void init_cpu_post(uint16_t pcpu_id) panic("hardware not support!"); } + if (sanitize_vm_config() != 0) { + panic("VM Configuration Error!"); + } + /* Warn for security feature not ready */ if (!check_cpu_security_cap()) { pr_fatal("SECURITY WARNING!!!!!!"); diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index f3adcf7a1..e537800d7 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -438,6 +438,57 @@ void prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config) } } +/** + * @pre vm_config != NULL + */ +int32_t sanitize_vm_config(void) +{ + int32_t ret = 0; + uint16_t vm_id; + uint64_t sos_pcpu_bitmap, pre_launch_pcpu_bitmap; + struct acrn_vm_config *vm_config; + + sos_pcpu_bitmap = (uint64_t)((((uint64_t)1U) << get_pcpu_nums()) - 1U); + pre_launch_pcpu_bitmap = 0U; + /* All physical CPUs except ocuppied by Pre-launched VMs are all + * belong to SOS_VM. i.e. The pcpu_bitmap of a SOS_VM is decided + * by pcpu_bitmap status in PRE_LAUNCHED_VMs. + * We need to setup a rule, that the vm_configs[] array should follow + * the order of PRE_LAUNCHED_VM first, and then SOS_VM. + */ + for (vm_id = 0U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) { + vm_config = get_vm_config(vm_id); + switch (vm_config->type) { + case PRE_LAUNCHED_VM: + if (vm_config->pcpu_bitmap == 0U) { + ret = -EINVAL; + } else { + pre_launch_pcpu_bitmap |= vm_config->pcpu_bitmap; + } + break; + case SOS_VM: + /* Deduct pcpus of PRE_LAUNCHED_VMs */ + sos_pcpu_bitmap ^= pre_launch_pcpu_bitmap; + if ((sos_pcpu_bitmap == 0U) || ((vm_config->guest_flags & LAPIC_PASSTHROUGH) != 0U)) { + ret = -EINVAL; + } else { + vm_config->pcpu_bitmap = sos_pcpu_bitmap; + } + break; + case NORMAL_VM: + ret = -EINVAL; + break; + default: + /* Nothing to do for a UNDEFINED_VM, break directly. */ + break; + } + if (ret != 0) { + break; + } + } + return ret; +} + /** * @pre vm_config != NULL */ diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index f1d554df1..074524d10 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -295,6 +295,7 @@ int32_t reset_vm(struct acrn_vm *vm); int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_vm **rtn_vm); void prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config); void launch_vms(uint16_t pcpu_id); +int32_t sanitize_vm_config(void); extern struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM];