diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 29111f0e7..d663a02ea 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -132,6 +132,7 @@ C_SRCS += boot/reloc.c C_SRCS += arch/x86/init.c # configuration component +C_SRCS += arch/x86/configs/vm_config.c ifeq ($(CONFIG_SHARING_MODE),y) C_SRCS += arch/x86/configs/sharing_config.c else ifeq ($(CONFIG_PARTITION_MODE),y) diff --git a/hypervisor/arch/x86/configs/vm_config.c b/hypervisor/arch/x86/configs/vm_config.c new file mode 100644 index 000000000..f5d8f3093 --- /dev/null +++ b/hypervisor/arch/x86/configs/vm_config.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/** + * @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; +} diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 79992d691..f720528b2 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -579,72 +579,6 @@ 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 ((vm_config->guest_flags & CLOS_REQUIRED) != 0U) { - if (cat_cap_info.support) { - if (vm_config->clos > cat_cap_info.clos_max) { - pr_err("%s CLOS exceed MAX CLOS\n", __func__); - ret = -EINVAL; - } else { - cat_cap_info.enabled = true; - } - } else { - pr_err("%s set CLOS but CAT is not supported\n", __func__); - ret = -EINVAL; - } - } - - 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 0a2728c58..0f2007160 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef CONFIG_PARTITION_MODE #include @@ -35,8 +36,6 @@ #define INVALID_VM_ID 0xffffU -#define PLUG_CPU(n) (1U << (n)) - struct vm_hw_info { /* vcpu array of this VM */ struct acrn_vcpu vcpu_array[CONFIG_MAX_VCPUS_PER_VM]; @@ -159,59 +158,6 @@ struct acrn_vm { uint64_t intr_inject_delay_delta; /* delay of intr injection */ } __aligned(PAGE_SIZE); -#define MAX_BOOTARGS_SIZE 1024U -#define MAX_CONFIG_NAME_SIZE 32U - -/* - * PRE_LAUNCHED_VM is launched by ACRN hypervisor, with LAPIC_PT; - * SOS_VM is launched by ACRN hypervisor, without LAPIC_PT; - * NORMAL_VM is launched by ACRN devicemodel, with/without LAPIC_PT depends on usecases. - */ -enum acrn_vm_type { - UNDEFINED_VM = 0, - PRE_LAUNCHED_VM, - SOS_VM, - NORMAL_VM /* Post-launched VM */ -}; - -struct acrn_vm_mem_config { - uint64_t start_hpa; /* the start HPA of VM memory configuration, for pre-launched VMs only */ - uint64_t size; /* VM memory size configuration */ -}; - -struct acrn_vm_os_config { - char name[MAX_CONFIG_NAME_SIZE]; /* OS name, useful for debug */ - char bootargs[MAX_BOOTARGS_SIZE]; /* boot args/cmdline */ -} __aligned(8); - -struct acrn_vm_pci_ptdev_config { - union pci_bdf vbdf; /* virtual BDF of PCI PT device */ - union pci_bdf pbdf; /* physical BDF of PCI PT device */ -} __aligned(8); - -struct acrn_vm_config { - enum acrn_vm_type type; /* specify the type of VM */ - char name[MAX_CONFIG_NAME_SIZE]; /* VM name identifier, useful for debug. */ - uint8_t GUID[16]; /* GUID 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: - * SECURE_WORLD_ENABLED - * LAPIC_PASSTHROUGH - * We could add more guest flags in future; - */ - struct acrn_vm_mem_config memory; /* memory configuration of VM */ - uint16_t pci_ptdev_num; /* indicate how many PCI PT devices in VM */ - struct acrn_vm_pci_ptdev_config *pci_ptdevs; /* point to PCI PT devices BDF list */ - struct acrn_vm_os_config os_config; /* OS information the VM */ - -#ifdef CONFIG_PARTITION_MODE - bool vm_vuart; -#endif - - uint16_t clos; /* if guest_flags has CAT_ENABLED, then VM use this CLOS */ -} __aligned(8); - /* * @pre vlapic != NULL */ @@ -283,10 +229,6 @@ 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]; - bool is_sos_vm(const struct acrn_vm *vm); uint16_t find_free_vm_id(void); struct acrn_vm *get_vm_from_vmid(uint16_t vm_id); @@ -302,14 +244,6 @@ uint16_t get_vm_pcpu_nums(const struct acrn_vm_config *vm_config); void vrtc_init(struct acrn_vm *vm); #endif -/* - * @pre vm_id < CONFIG_MAX_VM_NUM - */ -static inline struct acrn_vm_config *get_vm_config(uint16_t vm_id) -{ - return &vm_configs[vm_id]; -} - static inline bool is_lapic_pt(const struct acrn_vm *vm) { return ((vm_configs[vm->vm_id].guest_flags & LAPIC_PASSTHROUGH) != 0U); diff --git a/hypervisor/include/arch/x86/vm_config.h b/hypervisor/include/arch/x86/vm_config.h new file mode 100644 index 000000000..5085faf07 --- /dev/null +++ b/hypervisor/include/arch/x86/vm_config.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef VM_CONFIG_H_ +#define VM_CONFIG_H_ + +#include +#include + +#define MAX_BOOTARGS_SIZE 1024U +#define MAX_CONFIG_NAME_SIZE 32U + +#define PLUG_CPU(n) (1U << (n)) + +/* + * PRE_LAUNCHED_VM is launched by ACRN hypervisor, with LAPIC_PT; + * SOS_VM is launched by ACRN hypervisor, without LAPIC_PT; + * NORMAL_VM is launched by ACRN devicemodel, with/without LAPIC_PT depends on usecases. + */ +enum acrn_vm_type { + UNDEFINED_VM = 0, + PRE_LAUNCHED_VM, + SOS_VM, + NORMAL_VM /* Post-launched VM */ +}; + +struct acrn_vm_mem_config { + uint64_t start_hpa; /* the start HPA of VM memory configuration, for pre-launched VMs only */ + uint64_t size; /* VM memory size configuration */ +}; + +struct acrn_vm_os_config { + char name[MAX_CONFIG_NAME_SIZE]; /* OS name, useful for debug */ + char bootargs[MAX_BOOTARGS_SIZE]; /* boot args/cmdline */ +} __aligned(8); + +struct acrn_vm_pci_ptdev_config { + union pci_bdf vbdf; /* virtual BDF of PCI PT device */ + union pci_bdf pbdf; /* physical BDF of PCI PT device */ +} __aligned(8); + +struct acrn_vm_config { + enum acrn_vm_type type; /* specify the type of VM */ + char name[MAX_CONFIG_NAME_SIZE]; /* VM name identifier, useful for debug. */ + uint8_t GUID[16]; /* GUID 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: + * SECURE_WORLD_ENABLED + * LAPIC_PASSTHROUGH + * We could add more guest flags in future; + */ + struct acrn_vm_mem_config memory; /* memory configuration of VM */ + uint16_t pci_ptdev_num; /* indicate how many PCI PT devices in VM */ + struct acrn_vm_pci_ptdev_config *pci_ptdevs; /* point to PCI PT devices BDF list */ + struct acrn_vm_os_config os_config; /* OS information the VM */ + uint16_t clos; /* if guest_flags has CAT_ENABLED, then VM use this CLOS */ + +#ifdef CONFIG_PARTITION_MODE + bool vm_vuart; +#endif +} __aligned(8); + +extern struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM]; + +/* + * @pre vm_id < CONFIG_MAX_VM_NUM + */ +static inline struct acrn_vm_config *get_vm_config(uint16_t vm_id) +{ + return &vm_configs[vm_id]; +} + +int32_t sanitize_vm_config(void); + +#endif /* VM_CONFIG_H_ */