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 <yuhong.tao@intel.com>
This commit is contained in:
Tao Yuhong 2021-06-24 06:44:43 -04:00 committed by Xie, Nanlin
parent 5976c58792
commit ab82f67cb9
7 changed files with 114 additions and 2 deletions

View File

@ -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

View File

@ -39,6 +39,7 @@
#include <asm/rtcm.h>
#include <asm/irq.h>
#include <uart16550.h>
#include <quirks/fixup.h>
/* 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);

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <types.h>
#include <asm/vm_config.h>
#include <asm/guest/vm.h>
#include <vacpi.h>
#include <logmsg.h>
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();
}
}

12
hypervisor/quirks/fixup.h Normal file
View File

@ -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_ */