|
| 1 | +/* |
| 2 | + * Copyright (C) 2018 Intel Corporation. All rights reserved. |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: BSD-3-Clause |
| 5 | + */ |
| 6 | + |
| 7 | +#include <hv_lib.h> |
| 8 | +#include <acrn_common.h> |
| 9 | +#include <hv_arch.h> |
| 10 | +#include <hv_debug.h> |
| 11 | +#include <bsp_extern.h> |
| 12 | +#include <mptable.h> |
| 13 | + |
| 14 | +#define MPTABLE_BASE 0xF0000U |
| 15 | + |
| 16 | +/* floating pointer length + maximum length of configuration table */ |
| 17 | +#define MPTABLE_MAX_LENGTH (65536 + 16)U |
| 18 | + |
| 19 | +#define LAPIC_VERSION 16U |
| 20 | + |
| 21 | +#define MP_SPECREV 4U |
| 22 | +#define MPFP_SIG "_MP_" |
| 23 | + |
| 24 | +/* Configuration header defines */ |
| 25 | +#define MPCH_SIG "PCMP" |
| 26 | +#define MPCH_OEMID "BHyVe " |
| 27 | +#define MPCH_OEMID_LEN 8U |
| 28 | +#define MPCH_PRODID "Hypervisor " |
| 29 | +#define MPCH_PRODID_LEN 12U |
| 30 | + |
| 31 | +/* Processor entry defines */ |
| 32 | +#define MPEP_SIG_FAMILY 6U /* XXX cwpdm should supply this */ |
| 33 | +#define MPEP_SIG_MODEL 26U |
| 34 | +#define MPEP_SIG_STEPPING 5U |
| 35 | +#define MPEP_SIG \ |
| 36 | + ((MPEP_SIG_FAMILY << 8U) | \ |
| 37 | + (MPEP_SIG_MODEL << 4U) | \ |
| 38 | + (MPEP_SIG_STEPPING)) |
| 39 | + |
| 40 | +#define MPEP_FEATURES 0xBFEBFBFFU /* XXX Intel i7 */ |
| 41 | + |
| 42 | +/* Number of local intr entries */ |
| 43 | +#define MPEII_NUM_LOCAL_IRQ 2U |
| 44 | + |
| 45 | +/* Bus entry defines */ |
| 46 | +#define MPE_NUM_BUSES 2U |
| 47 | +#define MPE_BUSNAME_LEN 6U |
| 48 | +#define MPE_BUSNAME_ISA "ISA " |
| 49 | +#define MPE_BUSNAME_PCI "PCI " |
| 50 | + |
| 51 | +/* Base table entries */ |
| 52 | + |
| 53 | +#define MPCT_ENTRY_PROCESSOR 0U |
| 54 | +#define MPCT_ENTRY_BUS 1U |
| 55 | +#define MPCT_ENTRY_LOCAL_INT 4U |
| 56 | + |
| 57 | +#define PROCENTRY_FLAG_EN 0x01U |
| 58 | +#define PROCENTRY_FLAG_BP 0x02U |
| 59 | + |
| 60 | +#define INTENTRY_TYPE_NMI 1U |
| 61 | +#define INTENTRY_TYPE_EXTINT 3U |
| 62 | + |
| 63 | +#define INTENTRY_FLAGS_POLARITY_CONFORM 0x0U |
| 64 | +#define INTENTRY_FLAGS_TRIGGER_CONFORM 0x0U |
| 65 | + |
| 66 | +#define VM1_NUM_CPUS 2U |
| 67 | +#define VM2_NUM_CPUS 2U |
| 68 | + |
| 69 | +/* MP Floating Pointer Structure */ |
| 70 | +struct mpfps { |
| 71 | + uint8_t signature[4]; |
| 72 | + uint32_t pap; |
| 73 | + uint8_t length; |
| 74 | + uint8_t spec_rev; |
| 75 | + uint8_t checksum; |
| 76 | + uint8_t config_type; |
| 77 | + uint8_t mpfb2; |
| 78 | + uint8_t mpfb3; |
| 79 | + uint8_t mpfb4; |
| 80 | + uint8_t mpfb5; |
| 81 | +} __attribute__((packed)); |
| 82 | + |
| 83 | +/* MP Configuration Table Header */ |
| 84 | +struct mpcth { |
| 85 | + uint8_t signature[4]; |
| 86 | + uint16_t base_table_length; |
| 87 | + uint8_t spec_rev; |
| 88 | + uint8_t checksum; |
| 89 | + uint8_t oem_id[8]; |
| 90 | + uint8_t product_id[12]; |
| 91 | + uint32_t oem_table_pointer; |
| 92 | + uint16_t oem_table_size; |
| 93 | + uint16_t entry_count; |
| 94 | + uint32_t apic_address; |
| 95 | + uint16_t extended_table_length; |
| 96 | + uint8_t extended_table_checksum; |
| 97 | + uint8_t reserved; |
| 98 | +} __attribute__((packed)); |
| 99 | + |
| 100 | +struct proc_entry { |
| 101 | + uint8_t type; |
| 102 | + uint8_t apic_id; |
| 103 | + uint8_t apic_version; |
| 104 | + uint8_t cpu_flags; |
| 105 | + uint32_t cpu_signature; |
| 106 | + uint32_t feature_flags; |
| 107 | + uint32_t reserved1; |
| 108 | + uint32_t reserved2; |
| 109 | +} __attribute__((packed)); |
| 110 | + |
| 111 | +struct bus_entry { |
| 112 | + uint8_t type; |
| 113 | + uint8_t bus_id; |
| 114 | + uint8_t bus_type[6]; |
| 115 | +} __attribute__((packed)); |
| 116 | + |
| 117 | +struct int_entry { |
| 118 | + uint8_t type; |
| 119 | + uint8_t int_type; |
| 120 | + uint16_t int_flags; |
| 121 | + uint8_t src_bus_id; |
| 122 | + uint8_t src_bus_irq; |
| 123 | + uint8_t dst_apic_id; |
| 124 | + uint8_t dst_apic_int; |
| 125 | +} __attribute__((packed)); |
| 126 | + |
| 127 | +struct mptable_info { |
| 128 | + struct mpfps mpfp; |
| 129 | + struct mpcth mpch; |
| 130 | + struct bus_entry bus_entry_array[MPE_NUM_BUSES]; |
| 131 | + struct int_entry int_entry_array[MPEII_NUM_LOCAL_IRQ]; |
| 132 | + struct proc_entry proc_entry_array[]; |
| 133 | +}; |
| 134 | + |
| 135 | +struct mptable_info mptable_vm1 = { |
| 136 | + .mpfp = { |
| 137 | + .signature = MPFP_SIG, |
| 138 | + .pap = MPTABLE_BASE + sizeof(struct mpfps), |
| 139 | + .length = 1U, |
| 140 | + .spec_rev = MP_SPECREV, |
| 141 | + }, |
| 142 | + .mpch = { |
| 143 | + .signature = MPCH_SIG, |
| 144 | + .spec_rev = MP_SPECREV, |
| 145 | + .oem_id = MPCH_OEMID, |
| 146 | + .product_id = MPCH_PRODID, |
| 147 | + .apic_address = LAPIC_BASE, |
| 148 | + .entry_count = (VM1_NUM_CPUS + MPE_NUM_BUSES \ |
| 149 | + + MPEII_NUM_LOCAL_IRQ), |
| 150 | + .base_table_length = (sizeof(struct mpcth) \ |
| 151 | + + VM1_NUM_CPUS * sizeof(struct proc_entry) \ |
| 152 | + + MPE_NUM_BUSES * sizeof(struct bus_entry) \ |
| 153 | + + MPEII_NUM_LOCAL_IRQ * sizeof(struct int_entry)) |
| 154 | + }, |
| 155 | + .proc_entry_array = { |
| 156 | + { |
| 157 | + .type = MPCT_ENTRY_PROCESSOR, |
| 158 | + .apic_id = 0U, |
| 159 | + .apic_version = LAPIC_VERSION, |
| 160 | + .cpu_flags = PROCENTRY_FLAG_EN | PROCENTRY_FLAG_BP, |
| 161 | + .cpu_signature = MPEP_SIG, |
| 162 | + .feature_flags = MPEP_FEATURES |
| 163 | + }, |
| 164 | + { |
| 165 | + .type = MPCT_ENTRY_PROCESSOR, |
| 166 | + .apic_id = 4U, |
| 167 | + .apic_version = LAPIC_VERSION, |
| 168 | + .cpu_flags = PROCENTRY_FLAG_EN, |
| 169 | + .cpu_signature = MPEP_SIG, |
| 170 | + .feature_flags = MPEP_FEATURES, |
| 171 | + } |
| 172 | + }, |
| 173 | + .bus_entry_array = { |
| 174 | + { |
| 175 | + .type = MPCT_ENTRY_BUS, |
| 176 | + .bus_id = 0U, |
| 177 | + .bus_type = MPE_BUSNAME_PCI, |
| 178 | + }, |
| 179 | + { |
| 180 | + .type = MPCT_ENTRY_BUS, |
| 181 | + .bus_id = 1U, |
| 182 | + .bus_type = MPE_BUSNAME_ISA, |
| 183 | + }, |
| 184 | + }, |
| 185 | + .int_entry_array = { |
| 186 | + { |
| 187 | + .type = MPCT_ENTRY_LOCAL_INT, |
| 188 | + .int_type = INTENTRY_TYPE_EXTINT, |
| 189 | + .int_flags = INTENTRY_FLAGS_POLARITY_CONFORM \ |
| 190 | + | INTENTRY_FLAGS_TRIGGER_CONFORM, |
| 191 | + .dst_apic_id = 0xFFU, |
| 192 | + .dst_apic_int = 0U, |
| 193 | + }, |
| 194 | + { |
| 195 | + .type = MPCT_ENTRY_LOCAL_INT, |
| 196 | + .int_type = INTENTRY_TYPE_NMI, |
| 197 | + .int_flags = INTENTRY_FLAGS_POLARITY_CONFORM \ |
| 198 | + | INTENTRY_FLAGS_TRIGGER_CONFORM, |
| 199 | + .dst_apic_id = 0xFFU, |
| 200 | + .dst_apic_int = 1U, |
| 201 | + }, |
| 202 | + }, |
| 203 | +}; |
| 204 | + |
| 205 | +struct mptable_info mptable_vm2 = { |
| 206 | + .mpfp = { |
| 207 | + .signature = MPFP_SIG, |
| 208 | + .pap = MPTABLE_BASE + sizeof(struct mpfps), |
| 209 | + .length = 1U, |
| 210 | + .spec_rev = MP_SPECREV, |
| 211 | + }, |
| 212 | + .mpch = { |
| 213 | + .signature = MPCH_SIG, |
| 214 | + .spec_rev = MP_SPECREV, |
| 215 | + .oem_id = MPCH_OEMID, |
| 216 | + .product_id = MPCH_PRODID, |
| 217 | + .apic_address = LAPIC_BASE, |
| 218 | + .entry_count = (VM2_NUM_CPUS + MPE_NUM_BUSES \ |
| 219 | + + MPEII_NUM_LOCAL_IRQ), |
| 220 | + .base_table_length = (sizeof(struct mpcth) \ |
| 221 | + + VM2_NUM_CPUS * sizeof(struct proc_entry) \ |
| 222 | + + MPE_NUM_BUSES * sizeof(struct bus_entry) \ |
| 223 | + + MPEII_NUM_LOCAL_IRQ * sizeof(struct int_entry)) |
| 224 | + }, |
| 225 | + .proc_entry_array = { |
| 226 | + { |
| 227 | + .type = MPCT_ENTRY_PROCESSOR, |
| 228 | + .apic_id = 2U, |
| 229 | + .apic_version = LAPIC_VERSION, |
| 230 | + .cpu_flags = PROCENTRY_FLAG_EN | PROCENTRY_FLAG_BP, |
| 231 | + .cpu_signature = MPEP_SIG, |
| 232 | + .feature_flags = MPEP_FEATURES |
| 233 | + }, |
| 234 | + { |
| 235 | + .type = MPCT_ENTRY_PROCESSOR, |
| 236 | + .apic_id = 6U, |
| 237 | + .apic_version = LAPIC_VERSION, |
| 238 | + .cpu_flags = PROCENTRY_FLAG_EN, |
| 239 | + .cpu_signature = MPEP_SIG, |
| 240 | + .feature_flags = MPEP_FEATURES, |
| 241 | + } |
| 242 | + }, |
| 243 | + .bus_entry_array = { |
| 244 | + { |
| 245 | + .type = MPCT_ENTRY_BUS, |
| 246 | + .bus_id = 0U, |
| 247 | + .bus_type = MPE_BUSNAME_PCI, |
| 248 | + }, |
| 249 | + { |
| 250 | + .type = MPCT_ENTRY_BUS, |
| 251 | + .bus_id = 1U, |
| 252 | + .bus_type = MPE_BUSNAME_ISA, |
| 253 | + }, |
| 254 | + }, |
| 255 | + .int_entry_array = { |
| 256 | + { |
| 257 | + .type = MPCT_ENTRY_LOCAL_INT, |
| 258 | + .int_type = INTENTRY_TYPE_EXTINT, |
| 259 | + .int_flags = INTENTRY_FLAGS_POLARITY_CONFORM \ |
| 260 | + | INTENTRY_FLAGS_TRIGGER_CONFORM, |
| 261 | + .dst_apic_id = 0xFFU, |
| 262 | + .dst_apic_int = 0U, |
| 263 | + }, |
| 264 | + { |
| 265 | + .type = MPCT_ENTRY_LOCAL_INT, |
| 266 | + .int_type = INTENTRY_TYPE_NMI, |
| 267 | + .int_flags = INTENTRY_FLAGS_POLARITY_CONFORM \ |
| 268 | + | INTENTRY_FLAGS_TRIGGER_CONFORM, |
| 269 | + .dst_apic_id = 0xFFU, |
| 270 | + .dst_apic_int = 1U, |
| 271 | + }, |
| 272 | + }, |
| 273 | +}; |
| 274 | + |
| 275 | +static uint8_t mpt_compute_checksum(void *base, size_t len) |
| 276 | +{ |
| 277 | + uint8_t *bytes; |
| 278 | + uint8_t sum; |
| 279 | + size_t length = len; |
| 280 | + |
| 281 | + for (bytes = base, sum = 0U; length > 0U; length--) { |
| 282 | + sum += *bytes; |
| 283 | + bytes++; |
| 284 | + } |
| 285 | + |
| 286 | + return (256U - sum); |
| 287 | +} |
| 288 | + |
| 289 | +int mptable_build(struct vm *vm) |
| 290 | +{ |
| 291 | + char *startaddr; |
| 292 | + char *curraddr; |
| 293 | + struct mpcth *mpch; |
| 294 | + struct mpfps *mpfp; |
| 295 | + |
| 296 | + startaddr = (char *)GPA2HVA(vm, MPTABLE_BASE); |
| 297 | + /* Copy mptable info into guest memory */ |
| 298 | + (void)memcpy_s((void *)startaddr, sizeof(struct mptable_info), |
| 299 | + (void *)vm->vm_desc->mptable, |
| 300 | + sizeof(struct mptable_info)); |
| 301 | + |
| 302 | + curraddr = startaddr; |
| 303 | + mpfp = (struct mpfps *)curraddr; |
| 304 | + mpfp->checksum = mpt_compute_checksum(mpfp, sizeof(struct mpfps)); |
| 305 | + curraddr += sizeof(struct mpfps); |
| 306 | + |
| 307 | + mpch = (struct mpcth *)curraddr; |
| 308 | + mpch->checksum = mpt_compute_checksum(mpch, mpch->base_table_length); |
| 309 | + |
| 310 | + return 0U; |
| 311 | +} |
0 commit comments