hv: tpm2: do tpm2 fixup for security vm

ACRN used to prepare the vTPM2 ACPI Table for pre-launched VM at the build stage
using config tools. This is OK if the TPM2 ACPI Table never changes. However,
TPM2 ACPI Table may be changed in some conditions: change BIOS configuration or
update BIOS.

This patch do TPM2 fixup to update the vTPM2 ACPI Table and TPM2 MMIO resource
configuration according to the physical TPM2 ACPI Table.

Tracked-On: #6366
Signed-off-by: Tao Yuhong <yuhong.tao@intel.com>
Signed-off-by: Fei Li <fei1.li@intel.com>
This commit is contained in:
Fei Li
2021-08-06 14:12:13 +08:00
committed by wenlingz
parent f81b39225c
commit 74e68e39d1
11 changed files with 125 additions and 4 deletions

View File

@@ -287,6 +287,9 @@ 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
ifeq ($(CONFIG_SECURITY_VM_FIXUP),y)
VP_BASE_C_SRCS += quirks/security_vm_fixup.c
endif
# virtual platform device model
VP_DM_C_SRCS += dm/vpic.c

View File

@@ -39,6 +39,9 @@
#include <asm/rtcm.h>
#include <asm/irq.h>
#include <uart16550.h>
#ifdef CONFIG_SECURITY_VM_FIXUP
#include <quirks/security_vm_fixup.h>
#endif
/* Local variables */
@@ -898,6 +901,9 @@ void prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config)
int32_t err = 0;
struct acrn_vm *vm = NULL;
#ifdef CONFIG_SECURITY_VM_FIXUP
security_vm_fixup(vm_id);
#endif
/* 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

@@ -124,7 +124,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,11 @@ struct acpi_table_tpm2 {
uint16_t reserved;
uint64_t control_address;
uint32_t start_method;
#ifdef CONFIG_SECURITY_VM_FIXUP
uint8_t start_method_spec_para[12];
uint32_t laml;
uint64_t lasa;
#endif
} __packed;
void init_acpi(void);

View File

@@ -73,4 +73,5 @@ 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

@@ -56,6 +56,7 @@
#define GUEST_FLAG_HIDE_MTRR (1UL << 3U) /* Whether hide MTRR from VM */
#define GUEST_FLAG_RT (1UL << 4U) /* Whether the vm is RT-VM */
#define GUEST_FLAG_NVMX_ENABLED (1UL << 5U) /* Whether this VM supports nested virtualization */
#define GUEST_FLAG_TPM2_FIXUP (1UL << 6U) /* Whether this VM needs to do TPM2 fixup */
/* TODO: We may need to get this addr from guest ACPI instead of hardcode here */
#define VIRTUAL_SLEEP_CTL_ADDR 0x400U /* Pre-launched VM uses ACPI reduced HW mode and sleep control register */

View File

@@ -0,0 +1,91 @@
/*
* 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 *vtpm2 = NULL, *tpm2 = NULL;
struct acrn_vm_config *config = get_vm_config(vm_id);
uint8_t checksum, i;
struct acrn_boot_info *abi = get_acrn_boot_info();
struct acrn_mmiodev *dev = NULL;
struct abi_module *mod = get_mod_by_tag(abi, config->acpi_config.acpi_mod_tag);
if (mod != NULL) {
vtpm2 = get_acpi_mod_entry(ACPI_SIG_TPM2, mod->start);
tpm2 = get_acpi_tbl(ACPI_SIG_TPM2);
if (config->pt_tpm2 && (vtpm2 != NULL) && (tpm2 != NULL)) {
for (i = 0U; i < MAX_MMIO_DEV_NUM; i++) {
if (strncmp(config->mmiodevs[i].name, "tpm2", 4) == 0) {
dev = &config->mmiodevs[i];
break;
}
}
if (dev != NULL) {
vtpm2->start_method = tpm2->start_method;
memcpy_s(&vtpm2->start_method_spec_para, sizeof(tpm2->start_method_spec_para),
&tpm2->start_method_spec_para, sizeof(tpm2->start_method_spec_para));
/* tpm2 has event log */
if (tpm2->laml != 0U) {
vtpm2->header.length = tpm2->header.length;
vtpm2->header.revision = tpm2->header.revision;
vtpm2->laml = tpm2->laml;
vtpm2->lasa = dev->res[1].user_vm_pa;
/* update log buffer length/HPA in vm_config */
dev->res[1].size = tpm2->laml;
dev->res[1].host_pa = tpm2->lasa;
}
/* update checksum */
vtpm2->header.checksum = 0;
checksum = calculate_checksum8(vtpm2, sizeof(struct acpi_table_tpm2));
vtpm2->header.checksum = checksum;
} else {
pr_err("%s, no TPM2 in acrn_vm_config", __func__);
}
}
}
}
void security_vm_fixup(uint16_t vm_id)
{
struct acrn_vm_config *vm_config = get_vm_config(vm_id);
if ((vm_config->guest_flags & GUEST_FLAG_TPM2_FIXUP) != 0UL) {
stac();
tpm2_fixup(vm_id);
clac();
}
}

View File

@@ -0,0 +1,12 @@
/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _SECURITY_VM_FIXUP_H_
#define _SECURITY_VM_FIXUP_H_
void security_vm_fixup(uint16_t vm_id);
#endif /* _SECURITY_VM_FIXUP_H_ */