From ab82f67cb975088ffd2a6580cba1f06590814fbe Mon Sep 17 00:00:00 2001 From: Tao Yuhong Date: Thu, 24 Jun 2021 06:44:43 -0400 Subject: [PATCH] HV: TPM: check tpm2 start method and event log If TPM device is passthrough to pre-launched VM, need check its start method and event log settings in native TPM2 ACPI table. Because when connect different TPM devices, TPM start method can change in native ACPI table. And event log address change in native ACPI table is expected by BIOS updating. Need fixup pre-launched VM's ACPI table and vm_config if they are misaligned with native platform. We add acrn_vm_fixup() in prepare_vm(), where the acrn_vm structure is not created. This is suitable for checking between vm_config and HW real configurations, and try fixup for native ACPI updating. Tracked-On: #6320 Signed-off-by: Tao Yuhong --- hypervisor/Makefile | 1 + hypervisor/arch/x86/guest/vm.c | 2 + hypervisor/boot/guest/vboot_info.c | 2 +- hypervisor/boot/include/acpi.h | 3 + hypervisor/boot/include/boot.h | 2 +- hypervisor/quirks/acrn_vm_fixup.c | 94 ++++++++++++++++++++++++++++++ hypervisor/quirks/fixup.h | 12 ++++ 7 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 hypervisor/quirks/acrn_vm_fixup.c create mode 100644 hypervisor/quirks/fixup.h diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 71119c3b6..9100ebf2a 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -290,6 +290,7 @@ VP_BASE_C_SRCS += common/hv_main.c VP_BASE_C_SRCS += common/vm_load.c VP_BASE_C_SRCS += arch/x86/configs/pci_dev.c VP_BASE_C_SRCS += arch/x86/configs/vacpi.c +VP_BASE_C_SRCS += quirks/acrn_vm_fixup.c # virtual platform device model VP_DM_C_SRCS += dm/vpic.c diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 8adbcaafe..ef4e5a909 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -39,6 +39,7 @@ #include #include #include +#include /* Local variables */ @@ -897,6 +898,7 @@ void prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config) int32_t err = 0; struct acrn_vm *vm = NULL; + acrn_vm_fixup(vm_id); /* SOS and pre-launched VMs launch on all pCPUs defined in vm_config->cpu_affinity */ err = create_vm(vm_id, vm_config->cpu_affinity, vm_config, &vm); diff --git a/hypervisor/boot/guest/vboot_info.c b/hypervisor/boot/guest/vboot_info.c index 27bcad211..bac840f32 100644 --- a/hypervisor/boot/guest/vboot_info.c +++ b/hypervisor/boot/guest/vboot_info.c @@ -277,7 +277,7 @@ static void init_vm_bootargs_info(struct acrn_vm *vm, const struct acrn_boot_inf /* @pre abi != NULL && tag != NULL */ -static struct abi_module *get_mod_by_tag(const struct acrn_boot_info *abi, const char *tag) +struct abi_module *get_mod_by_tag(const struct acrn_boot_info *abi, const char *tag) { uint8_t i; struct abi_module *mod = NULL; diff --git a/hypervisor/boot/include/acpi.h b/hypervisor/boot/include/acpi.h index 7fdefe358..2dc69906a 100644 --- a/hypervisor/boot/include/acpi.h +++ b/hypervisor/boot/include/acpi.h @@ -235,6 +235,9 @@ struct acpi_table_tpm2 { uint16_t reserved; uint64_t control_address; uint32_t start_method; + uint8_t start_method_spec_para[12]; + uint32_t laml; + uint64_t lasa; } __packed; void init_acpi(void); diff --git a/hypervisor/boot/include/boot.h b/hypervisor/boot/include/boot.h index 117f9caf0..a020b4bdd 100644 --- a/hypervisor/boot/include/boot.h +++ b/hypervisor/boot/include/boot.h @@ -78,5 +78,5 @@ int32_t init_multiboot2_info(uint32_t *registers); void init_acrn_boot_info(uint32_t *registers); int32_t sanitize_acrn_boot_info(struct acrn_boot_info *abi); struct acrn_boot_info *get_acrn_boot_info(void); - +struct abi_module *get_mod_by_tag(const struct acrn_boot_info *abi, const char *tag); #endif /* BOOT_H */ diff --git a/hypervisor/quirks/acrn_vm_fixup.c b/hypervisor/quirks/acrn_vm_fixup.c new file mode 100644 index 000000000..7f91368df --- /dev/null +++ b/hypervisor/quirks/acrn_vm_fixup.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + +static void *get_acpi_mod_entry(const char *signature, void *acpi) +{ + struct acpi_table_xsdt *xsdt; + uint32_t i, entry_cnt = 0U; + struct acpi_table_header *header = NULL, *find = NULL; + + xsdt = acpi + VIRT_XSDT_ADDR - VIRT_ACPI_DATA_ADDR; + entry_cnt = (xsdt->header.length - sizeof(xsdt->header)) / (sizeof(xsdt->table_offset_entry[0])); + + for (i = 0; i < entry_cnt; i++) { + header = acpi + xsdt->table_offset_entry[i] - VIRT_ACPI_DATA_ADDR; + if (strncmp(header->signature, signature, ACPI_NAME_SIZE) == 0) { + find = header; + break; + } + } + + return find; +} + +static void tpm2_fixup(uint16_t vm_id) +{ + struct acpi_table_tpm2 *tpm2 = NULL, *native = NULL; + struct acrn_vm_config *config = get_vm_config(vm_id); + bool need_fix = false; + uint8_t checksum; + struct acrn_boot_info *abi = get_acrn_boot_info(); + struct abi_module *mod; + + mod = get_mod_by_tag(abi, config->acpi_config.acpi_mod_tag); + + tpm2 = get_acpi_mod_entry(ACPI_SIG_TPM2, mod->start); + native = get_acpi_tbl(ACPI_SIG_TPM2); + + if (config->pt_tpm2) { + if ((tpm2 != NULL) && (native != NULL)) { + /* Native has different start method */ + need_fix = tpm2->start_method != native->start_method; + + /* Native has event log */ + if (native->header.length == + sizeof(struct acpi_table_tpm2)) { + need_fix |= tpm2->header.length == 0x34U; + need_fix |= strncmp((char *)tpm2->start_method_spec_para, (char *)native->start_method_spec_para, + sizeof(tpm2->start_method_spec_para)) != 0; + need_fix |= tpm2->laml != native->laml; + need_fix |= tpm2->lasa != native->lasa; + } + + if (need_fix) { + pr_err("%s tpm2 fix start method and event log field", __FUNCTION__); + tpm2->start_method = native->start_method; + tpm2->header.length = native->header.length; + tpm2->header.revision = native->header.revision; + memcpy_s(&native->start_method_spec_para, sizeof(native->start_method_spec_para), + &tpm2->start_method_spec_para, sizeof(native->start_method_spec_para)); + tpm2->laml = native->laml; + tpm2->lasa = config->mmiodevs[0].mmiores[1].base_gpa; + + tpm2->header.checksum = 0; + checksum = calculate_checksum8(tpm2, sizeof(struct acpi_table_tpm2)); + tpm2->header.checksum = checksum; + + config->mmiodevs[0].mmiores[1].base_hpa = native->lasa; + config->mmiodevs[0].mmiores[1].size = tpm2->laml; + } + } else { + pr_err("VM or native can't find TPM2 ACPI table"); + } + } +} + +void acrn_vm_fixup(uint16_t vm_id) +{ + struct acrn_vm_config *vm_config = get_vm_config(vm_id); + + if ((vm_config->load_order == PRE_LAUNCHED_VM)) { + stac(); + tpm2_fixup(vm_id); + clac(); + } +} + diff --git a/hypervisor/quirks/fixup.h b/hypervisor/quirks/fixup.h new file mode 100644 index 000000000..58061240d --- /dev/null +++ b/hypervisor/quirks/fixup.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FIXUP_H_ +#define _FIXUP_H_ + +void acrn_vm_fixup(uint16_t vm_id); + +#endif /* _FIXUP_H_ */