From 6643adff8bfa05139992dfa1af7d129f8782b2e9 Mon Sep 17 00:00:00 2001 From: Sainath Grandhi Date: Thu, 2 Aug 2018 14:53:28 -0700 Subject: [PATCH] HV: Adding mptable support for partition mode ACRN Partitioning mode of ACRN needs to build mptable for UOS. UOS uses mptable instead of ACPI tables. Signed-off-by: Sainath Grandhi --- hypervisor/Makefile | 4 + hypervisor/arch/x86/guest/mptable.c | 311 ++++++++++++++++++++ hypervisor/include/arch/x86/guest/mptable.h | 31 ++ hypervisor/include/arch/x86/guest/vm.h | 9 + 4 files changed, 355 insertions(+) create mode 100644 hypervisor/arch/x86/guest/mptable.c create mode 100644 hypervisor/include/arch/x86/guest/mptable.h diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 5bb3a094f..bf9b2db71 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -185,6 +185,10 @@ C_SRCS += boot/sbl/hob_parse.c endif endif +ifeq ($(CONFIG_PARTITION_MODE), y) +C_SRCS += arch/x86/guest/mptable.c +endif + # retpoline support ifeq (true, $(shell [ $(GCC_MAJOR) -eq 7 ] && [ $(GCC_MINOR) -ge 3 ] && echo true)) CFLAGS += -mindirect-branch=thunk-extern -mindirect-branch-register diff --git a/hypervisor/arch/x86/guest/mptable.c b/hypervisor/arch/x86/guest/mptable.c new file mode 100644 index 000000000..42d8ffca6 --- /dev/null +++ b/hypervisor/arch/x86/guest/mptable.c @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#define MPTABLE_BASE 0xF0000U + +/* floating pointer length + maximum length of configuration table */ +#define MPTABLE_MAX_LENGTH (65536 + 16)U + +#define LAPIC_VERSION 16U + +#define MP_SPECREV 4U +#define MPFP_SIG "_MP_" + +/* Configuration header defines */ +#define MPCH_SIG "PCMP" +#define MPCH_OEMID "BHyVe " +#define MPCH_OEMID_LEN 8U +#define MPCH_PRODID "Hypervisor " +#define MPCH_PRODID_LEN 12U + +/* Processor entry defines */ +#define MPEP_SIG_FAMILY 6U /* XXX cwpdm should supply this */ +#define MPEP_SIG_MODEL 26U +#define MPEP_SIG_STEPPING 5U +#define MPEP_SIG \ + ((MPEP_SIG_FAMILY << 8U) | \ + (MPEP_SIG_MODEL << 4U) | \ + (MPEP_SIG_STEPPING)) + +#define MPEP_FEATURES 0xBFEBFBFFU /* XXX Intel i7 */ + +/* Number of local intr entries */ +#define MPEII_NUM_LOCAL_IRQ 2U + +/* Bus entry defines */ +#define MPE_NUM_BUSES 2U +#define MPE_BUSNAME_LEN 6U +#define MPE_BUSNAME_ISA "ISA " +#define MPE_BUSNAME_PCI "PCI " + +/* Base table entries */ + +#define MPCT_ENTRY_PROCESSOR 0U +#define MPCT_ENTRY_BUS 1U +#define MPCT_ENTRY_LOCAL_INT 4U + +#define PROCENTRY_FLAG_EN 0x01U +#define PROCENTRY_FLAG_BP 0x02U + +#define INTENTRY_TYPE_NMI 1U +#define INTENTRY_TYPE_EXTINT 3U + +#define INTENTRY_FLAGS_POLARITY_CONFORM 0x0U +#define INTENTRY_FLAGS_TRIGGER_CONFORM 0x0U + +#define VM1_NUM_CPUS 2U +#define VM2_NUM_CPUS 2U + +/* MP Floating Pointer Structure */ +struct mpfps { + uint8_t signature[4]; + uint32_t pap; + uint8_t length; + uint8_t spec_rev; + uint8_t checksum; + uint8_t config_type; + uint8_t mpfb2; + uint8_t mpfb3; + uint8_t mpfb4; + uint8_t mpfb5; +} __attribute__((packed)); + +/* MP Configuration Table Header */ +struct mpcth { + uint8_t signature[4]; + uint16_t base_table_length; + uint8_t spec_rev; + uint8_t checksum; + uint8_t oem_id[8]; + uint8_t product_id[12]; + uint32_t oem_table_pointer; + uint16_t oem_table_size; + uint16_t entry_count; + uint32_t apic_address; + uint16_t extended_table_length; + uint8_t extended_table_checksum; + uint8_t reserved; +} __attribute__((packed)); + +struct proc_entry { + uint8_t type; + uint8_t apic_id; + uint8_t apic_version; + uint8_t cpu_flags; + uint32_t cpu_signature; + uint32_t feature_flags; + uint32_t reserved1; + uint32_t reserved2; +} __attribute__((packed)); + +struct bus_entry { + uint8_t type; + uint8_t bus_id; + uint8_t bus_type[6]; +} __attribute__((packed)); + +struct int_entry { + uint8_t type; + uint8_t int_type; + uint16_t int_flags; + uint8_t src_bus_id; + uint8_t src_bus_irq; + uint8_t dst_apic_id; + uint8_t dst_apic_int; +} __attribute__((packed)); + +struct mptable_info { + struct mpfps mpfp; + struct mpcth mpch; + struct bus_entry bus_entry_array[MPE_NUM_BUSES]; + struct int_entry int_entry_array[MPEII_NUM_LOCAL_IRQ]; + struct proc_entry proc_entry_array[]; +}; + +struct mptable_info mptable_vm1 = { + .mpfp = { + .signature = MPFP_SIG, + .pap = MPTABLE_BASE + sizeof(struct mpfps), + .length = 1U, + .spec_rev = MP_SPECREV, + }, + .mpch = { + .signature = MPCH_SIG, + .spec_rev = MP_SPECREV, + .oem_id = MPCH_OEMID, + .product_id = MPCH_PRODID, + .apic_address = LAPIC_BASE, + .entry_count = (VM1_NUM_CPUS + MPE_NUM_BUSES \ + + MPEII_NUM_LOCAL_IRQ), + .base_table_length = (sizeof(struct mpcth) \ + + VM1_NUM_CPUS * sizeof(struct proc_entry) \ + + MPE_NUM_BUSES * sizeof(struct bus_entry) \ + + MPEII_NUM_LOCAL_IRQ * sizeof(struct int_entry)) + }, + .proc_entry_array = { + { + .type = MPCT_ENTRY_PROCESSOR, + .apic_id = 0U, + .apic_version = LAPIC_VERSION, + .cpu_flags = PROCENTRY_FLAG_EN | PROCENTRY_FLAG_BP, + .cpu_signature = MPEP_SIG, + .feature_flags = MPEP_FEATURES + }, + { + .type = MPCT_ENTRY_PROCESSOR, + .apic_id = 4U, + .apic_version = LAPIC_VERSION, + .cpu_flags = PROCENTRY_FLAG_EN, + .cpu_signature = MPEP_SIG, + .feature_flags = MPEP_FEATURES, + } + }, + .bus_entry_array = { + { + .type = MPCT_ENTRY_BUS, + .bus_id = 0U, + .bus_type = MPE_BUSNAME_PCI, + }, + { + .type = MPCT_ENTRY_BUS, + .bus_id = 1U, + .bus_type = MPE_BUSNAME_ISA, + }, + }, + .int_entry_array = { + { + .type = MPCT_ENTRY_LOCAL_INT, + .int_type = INTENTRY_TYPE_EXTINT, + .int_flags = INTENTRY_FLAGS_POLARITY_CONFORM \ + | INTENTRY_FLAGS_TRIGGER_CONFORM, + .dst_apic_id = 0xFFU, + .dst_apic_int = 0U, + }, + { + .type = MPCT_ENTRY_LOCAL_INT, + .int_type = INTENTRY_TYPE_NMI, + .int_flags = INTENTRY_FLAGS_POLARITY_CONFORM \ + | INTENTRY_FLAGS_TRIGGER_CONFORM, + .dst_apic_id = 0xFFU, + .dst_apic_int = 1U, + }, + }, +}; + +struct mptable_info mptable_vm2 = { + .mpfp = { + .signature = MPFP_SIG, + .pap = MPTABLE_BASE + sizeof(struct mpfps), + .length = 1U, + .spec_rev = MP_SPECREV, + }, + .mpch = { + .signature = MPCH_SIG, + .spec_rev = MP_SPECREV, + .oem_id = MPCH_OEMID, + .product_id = MPCH_PRODID, + .apic_address = LAPIC_BASE, + .entry_count = (VM2_NUM_CPUS + MPE_NUM_BUSES \ + + MPEII_NUM_LOCAL_IRQ), + .base_table_length = (sizeof(struct mpcth) \ + + VM2_NUM_CPUS * sizeof(struct proc_entry) \ + + MPE_NUM_BUSES * sizeof(struct bus_entry) \ + + MPEII_NUM_LOCAL_IRQ * sizeof(struct int_entry)) + }, + .proc_entry_array = { + { + .type = MPCT_ENTRY_PROCESSOR, + .apic_id = 2U, + .apic_version = LAPIC_VERSION, + .cpu_flags = PROCENTRY_FLAG_EN | PROCENTRY_FLAG_BP, + .cpu_signature = MPEP_SIG, + .feature_flags = MPEP_FEATURES + }, + { + .type = MPCT_ENTRY_PROCESSOR, + .apic_id = 6U, + .apic_version = LAPIC_VERSION, + .cpu_flags = PROCENTRY_FLAG_EN, + .cpu_signature = MPEP_SIG, + .feature_flags = MPEP_FEATURES, + } + }, + .bus_entry_array = { + { + .type = MPCT_ENTRY_BUS, + .bus_id = 0U, + .bus_type = MPE_BUSNAME_PCI, + }, + { + .type = MPCT_ENTRY_BUS, + .bus_id = 1U, + .bus_type = MPE_BUSNAME_ISA, + }, + }, + .int_entry_array = { + { + .type = MPCT_ENTRY_LOCAL_INT, + .int_type = INTENTRY_TYPE_EXTINT, + .int_flags = INTENTRY_FLAGS_POLARITY_CONFORM \ + | INTENTRY_FLAGS_TRIGGER_CONFORM, + .dst_apic_id = 0xFFU, + .dst_apic_int = 0U, + }, + { + .type = MPCT_ENTRY_LOCAL_INT, + .int_type = INTENTRY_TYPE_NMI, + .int_flags = INTENTRY_FLAGS_POLARITY_CONFORM \ + | INTENTRY_FLAGS_TRIGGER_CONFORM, + .dst_apic_id = 0xFFU, + .dst_apic_int = 1U, + }, + }, +}; + +static uint8_t mpt_compute_checksum(void *base, size_t len) +{ + uint8_t *bytes; + uint8_t sum; + size_t length = len; + + for (bytes = base, sum = 0U; length > 0U; length--) { + sum += *bytes; + bytes++; + } + + return (256U - sum); +} + +int mptable_build(struct vm *vm) +{ + char *startaddr; + char *curraddr; + struct mpcth *mpch; + struct mpfps *mpfp; + + startaddr = (char *)GPA2HVA(vm, MPTABLE_BASE); + /* Copy mptable info into guest memory */ + (void)memcpy_s((void *)startaddr, sizeof(struct mptable_info), + (void *)vm->vm_desc->mptable, + sizeof(struct mptable_info)); + + curraddr = startaddr; + mpfp = (struct mpfps *)curraddr; + mpfp->checksum = mpt_compute_checksum(mpfp, sizeof(struct mpfps)); + curraddr += sizeof(struct mpfps); + + mpch = (struct mpcth *)curraddr; + mpch->checksum = mpt_compute_checksum(mpch, mpch->base_table_length); + + return 0U; +} diff --git a/hypervisor/include/arch/x86/guest/mptable.h b/hypervisor/include/arch/x86/guest/mptable.h new file mode 100644 index 000000000..15e03a006 --- /dev/null +++ b/hypervisor/include/arch/x86/guest/mptable.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************ + * + * FILE NAME + * + * mptable.h + * + * DESCRIPTION + * + * This file defines API and extern variable for VM mptable info + * + ************************************************************************/ +/**********************************/ +/* EXTERNAL VARIABLES */ +/**********************************/ +#ifndef MPTABLE_H +#define MPTABLE_H + +struct mptable_info; + +extern struct mptable_info mptable_vm1; +extern struct mptable_info mptable_vm2; + +int mptable_build(struct vm *vm); + +#endif /* MPTABLE_H */ diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index 47992149c..43e2307d5 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -8,6 +8,9 @@ #define VM_H_ #include +#ifdef CONFIG_PARTITION_MODE +#include +#endif enum vm_privilege_level { VM_PRIVILEGE_LEVEL_HIGH = 0, VM_PRIVILEGE_LEVEL_MEDIUM, @@ -155,6 +158,9 @@ struct vm { uint32_t vcpuid_entry_nr, vcpuid_level, vcpuid_xlevel; struct vcpuid_entry vcpuid_entries[MAX_VM_VCPUID_ENTRIES]; +#ifdef CONFIG_PARTITION_MODE + struct vm_description *vm_desc; +#endif }; struct vm_description { @@ -166,6 +172,9 @@ struct vm_description { uint16_t vm_hw_num_cores; /* Number of virtual cores */ /* Whether secure world is enabled for current VM. */ bool sworld_enabled; +#ifdef CONFIG_PARTITION_MODE + struct mptable_info *mptable; +#endif }; int shutdown_vm(struct vm *vm);