1 /*
2 * Copyright (C) 2020-2022 Intel Corporation.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <asm/lib/bits.h>
8 #include <asm/page.h>
9 #include <asm/vm_config.h>
10 #include <asm/rdt.h>
11 #include <vuart.h>
12 #include <ivshmem.h>
13 #include <vmcs9900.h>
14 #include <vpci.h>
15 #include <hv_prebuild.h>
16
17
18 /* sanity check for below structs is not needed, so use a empty struct instead */
19 const struct pci_vdev_ops vhostbridge_ops;
20 const struct pci_vdev_ops vpci_ivshmem_ops;
21 const struct pci_vdev_ops vmcs9900_ops;
22
23 #define PLATFORM_CPUS_MASK ((1UL << MAX_PCPU_NUM) - 1UL)
24
25
26 #ifdef CONFIG_RDT_ENABLED
check_vm_clos_config(uint16_t vm_id)27 static bool check_vm_clos_config(uint16_t vm_id)
28 {
29 uint16_t i;
30 uint16_t platform_clos_num = HV_SUPPORTED_MAX_CLOS;
31 bool ret = true;
32 struct acrn_vm_config *vm_config = get_vm_config(vm_id);
33
34 for (i = 0U; i < vm_config->num_pclosids; i++) {
35 if (((platform_clos_num != 0U) && (vm_config->pclosids[i] == platform_clos_num))
36 || (vm_config->pclosids[i] > platform_clos_num)) {
37 printf("vm%u: vcpu%u clos(%u) exceed the max clos(%u).",
38 vm_id, i, vm_config->pclosids[i], platform_clos_num);
39 ret = false;
40 break;
41 }
42 }
43 return ret;
44 }
45 #endif
46
47 /**
48 * @pre vm_config != NULL
49 */
sanitize_vm_config(void)50 bool sanitize_vm_config(void)
51 {
52 bool ret = true;
53 uint16_t vm_id, vuart_idx;
54 struct acrn_vm_config *vm_config;
55
56 /* We need to setup a rule, that the vm_configs[] array should follow
57 * the order of PRE_LAUNCHED_VM first, and then Service VM.
58 */
59 for (vm_id = 0U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) {
60 vm_config = get_vm_config(vm_id);
61
62 if ((vm_config->name[0] != '\0')
63 && ((vm_config->cpu_affinity == 0UL) || ((vm_config->cpu_affinity & ~PLATFORM_CPUS_MASK) != 0UL))) {
64 printf("%s: vm%u assigns invalid PCPU (affinity: 0x%016x)\n", __func__, vm_id, vm_config->cpu_affinity);
65 ret = false;
66 }
67
68 switch (vm_config->load_order) {
69 case PRE_LAUNCHED_VM:
70 /* GUEST_FLAG_LAPIC_PASSTHROUGH must be set if we have GUEST_FLAG_RT set in guest_flags */
71 if (((vm_config->guest_flags & GUEST_FLAG_RT) != 0U)
72 && ((vm_config->guest_flags & GUEST_FLAG_LAPIC_PASSTHROUGH)== 0U)) {
73 ret = false;
74 } else if (vm_config->epc.size != 0UL) {
75 ret = false;
76 }
77 break;
78 case SERVICE_VM:
79 break;
80 case POST_LAUNCHED_VM:
81 if ((vm_config->severity == (uint8_t)SEVERITY_SAFETY_VM) || (vm_config->severity == (uint8_t)SEVERITY_SERVICE_VM)) {
82 ret = false;
83 }
84 break;
85 default:
86 /* Nothing to do for a unknown VM, break directly. */
87 break;
88 }
89
90 #ifdef CONFIG_RDT_ENABLED
91 if (ret) {
92 ret = check_vm_clos_config(vm_id);
93 }
94 #endif
95
96 if (ret &&
97 (((vm_config->epc.size | vm_config->epc.base) & ~PAGE_MASK) != 0UL)) {
98 ret = false;
99 }
100
101 if (ret) {
102 /* vuart[1+] are used for VM communications */
103 for (vuart_idx = 1U; vuart_idx < MAX_VUART_NUM_PER_VM; vuart_idx++) {
104 const struct vuart_config *vu_config = &vm_config->vuart[vuart_idx];
105
106 if (!(vu_config->type == VUART_LEGACY_PIO) &&
107 (vu_config->addr.port_base == INVALID_COM_BASE)) {
108 if ((vu_config->t_vuart.vm_id >= CONFIG_MAX_VM_NUM) ||
109 (vu_config->t_vuart.vm_id == vm_id)) {
110 printf("%s invalid vuart configuration for VM %d\n", __func__, vm_id);
111 ret = false;
112 }
113 }
114 }
115 }
116
117 if (!ret) {
118 break;
119 }
120 }
121 return ret;
122 }
123