[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH v2 21/44] i386/tdx: Create the TD HOB list upon machine init
From: |
isaku . yamahata |
Subject: |
[RFC PATCH v2 21/44] i386/tdx: Create the TD HOB list upon machine init done |
Date: |
Wed, 7 Jul 2021 17:54:51 -0700 |
From: Isaku Yamahata <isaku.yamahata@intel.com>
Build the TD HOB during machine late initialization, i.e. once guest
memory is fully defined.
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
hw/i386/meson.build | 2 +-
hw/i386/tdvf-hob.c | 166 ++++++++++++++++++++++++++++++++++++++++++
hw/i386/tdvf-hob.h | 20 +++++
target/i386/kvm/tdx.c | 19 +++++
4 files changed, 206 insertions(+), 1 deletion(-)
create mode 100644 hw/i386/tdvf-hob.c
create mode 100644 hw/i386/tdvf-hob.h
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index 945e805525..8175c3c638 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -24,7 +24,7 @@ i386_ss.add(when: 'CONFIG_PC', if_true: files(
'pc_sysfw.c',
'acpi-build.c',
'port92.c'))
-i386_ss.add(when: 'CONFIG_TDX', if_true: files('tdvf.c'))
+i386_ss.add(when: 'CONFIG_TDX', if_true: files('tdvf.c', 'tdvf-hob.c'))
subdir('kvm')
subdir('xen')
diff --git a/hw/i386/tdvf-hob.c b/hw/i386/tdvf-hob.c
new file mode 100644
index 0000000000..5e0bf807f7
--- /dev/null
+++ b/hw/i386/tdvf-hob.c
@@ -0,0 +1,166 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+
+ * Copyright (c) 2020 Intel Corporation
+ * Author: Isaku Yamahata <isaku.yamahata at gmail.com>
+ * <isaku.yamahata at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "e820_memory_layout.h"
+#include "hw/i386/x86.h"
+#include "sysemu/tdx.h"
+#include "tdvf-hob.h"
+#include "uefi.h"
+
+typedef struct TdvfHob {
+ hwaddr hob_addr;
+ void *ptr;
+ int size;
+
+ /* working area */
+ void *current;
+ void *end;
+} TdvfHob;
+
+static uint64_t tdvf_current_guest_addr(const TdvfHob *hob)
+{
+ return hob->hob_addr + (hob->current - hob->ptr);
+}
+
+static void tdvf_align(TdvfHob *hob, size_t align)
+{
+ hob->current = QEMU_ALIGN_PTR_UP(hob->current, align);
+}
+
+static void *tdvf_get_area(TdvfHob *hob, uint64_t size)
+{
+ void *ret;
+
+ if (hob->current + size > hob->end) {
+ error_report("TD_HOB overrun, size = 0x%" PRIx64, size);
+ exit(1);
+ }
+
+ ret = hob->current;
+ hob->current += size;
+ tdvf_align(hob, 8);
+ return ret;
+}
+
+static int tdvf_e820_compare(const void *lhs_, const void* rhs_)
+{
+ const struct e820_entry *lhs = lhs_;
+ const struct e820_entry *rhs = rhs_;
+
+ if (lhs->address == rhs->address) {
+ return 0;
+ }
+ if (le64_to_cpu(lhs->address) > le64_to_cpu(rhs->address)) {
+ return 1;
+ }
+ return -1;
+}
+
+static void tdvf_hob_add_memory_resources(TdvfHob *hob)
+{
+ EFI_HOB_RESOURCE_DESCRIPTOR *region;
+ EFI_RESOURCE_ATTRIBUTE_TYPE attr;
+ EFI_RESOURCE_TYPE resource_type;
+
+ struct e820_entry *e820_entries, *e820_entry;
+ int nr_e820_entries, i;
+
+ nr_e820_entries = e820_get_num_entries();
+ e820_entries = g_new(struct e820_entry, nr_e820_entries);
+
+ /* Copy and sort the e820 tables to add them to the HOB. */
+ memcpy(e820_entries, e820_table,
+ nr_e820_entries * sizeof(struct e820_entry));
+ qsort(e820_entries, nr_e820_entries, sizeof(struct e820_entry),
+ &tdvf_e820_compare);
+
+ for (i = 0; i < nr_e820_entries; i++) {
+ e820_entry = &e820_entries[i];
+
+ if (le32_to_cpu(e820_entry->type) == E820_RAM) {
+ resource_type = EFI_RESOURCE_SYSTEM_MEMORY;
+ attr = EFI_RESOURCE_ATTRIBUTE_TDVF_UNACCEPTED;
+ } else {
+ resource_type = EFI_RESOURCE_MEMORY_RESERVED;
+ attr = EFI_RESOURCE_ATTRIBUTE_TDVF_PRIVATE;
+ }
+
+ region = tdvf_get_area(hob, sizeof(*region));
+ *region = (EFI_HOB_RESOURCE_DESCRIPTOR) {
+ .Header = {
+ .HobType = EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
+ .HobLength = cpu_to_le16(sizeof(*region)),
+ .Reserved = cpu_to_le32(0),
+ },
+ .Owner = EFI_HOB_OWNER_ZERO,
+ .ResourceType = cpu_to_le32(resource_type),
+ .ResourceAttribute = cpu_to_le32(attr),
+ .PhysicalStart = e820_entry->address,
+ .ResourceLength = e820_entry->length,
+ };
+ }
+
+ g_free(e820_entries);
+}
+
+void tdvf_hob_create(TdxGuest *tdx, TdxFirmwareEntry *hob_entry)
+{
+ TdvfHob hob = {
+ .hob_addr = hob_entry->address,
+ .ptr = hob_entry->mem_ptr,
+ .size = hob_entry->size,
+
+ .current = hob_entry->mem_ptr,
+ .end = hob_entry->mem_ptr + hob_entry->size,
+ };
+
+ EFI_HOB_GENERIC_HEADER *last_hob;
+ EFI_HOB_HANDOFF_INFO_TABLE *hit;
+
+ /* Note, Efi{Free}Memory{Bottom,Top} are ignored, leave 'em zeroed. */
+ hit = tdvf_get_area(&hob, sizeof(*hit));
+ *hit = (EFI_HOB_HANDOFF_INFO_TABLE) {
+ .Header = {
+ .HobType = EFI_HOB_TYPE_HANDOFF,
+ .HobLength = cpu_to_le16(sizeof(*hit)),
+ .Reserved = cpu_to_le32(0),
+ },
+ .Version = cpu_to_le32(EFI_HOB_HANDOFF_TABLE_VERSION),
+ .BootMode = cpu_to_le32(0),
+ .EfiMemoryTop = cpu_to_le64(0),
+ .EfiMemoryBottom = cpu_to_le64(0),
+ .EfiFreeMemoryTop = cpu_to_le64(0),
+ .EfiFreeMemoryBottom = cpu_to_le64(0),
+ .EfiEndOfHobList = cpu_to_le64(0), /* initialized later */
+ };
+
+ tdvf_hob_add_memory_resources(&hob);
+
+ last_hob = tdvf_get_area(&hob, sizeof(*last_hob));
+ *last_hob = (EFI_HOB_GENERIC_HEADER) {
+ .HobType = EFI_HOB_TYPE_END_OF_HOB_LIST,
+ .HobLength = cpu_to_le16(sizeof(*last_hob)),
+ .Reserved = cpu_to_le32(0),
+ };
+ hit->EfiEndOfHobList = tdvf_current_guest_addr(&hob);
+}
diff --git a/hw/i386/tdvf-hob.h b/hw/i386/tdvf-hob.h
new file mode 100644
index 0000000000..c6c5c1d564
--- /dev/null
+++ b/hw/i386/tdvf-hob.h
@@ -0,0 +1,20 @@
+#ifndef HW_I386_TD_HOB_H
+#define HW_I386_TD_HOB_H
+
+#include "hw/i386/tdvf.h"
+#include "target/i386/kvm/tdx.h"
+
+void tdvf_hob_create(TdxGuest *tdx, TdxFirmwareEntry *hob_entry);
+
+#define EFI_RESOURCE_ATTRIBUTE_TDVF_PRIVATE \
+ (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_ENCRYPTED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED)
+
+#define EFI_RESOURCE_ATTRIBUTE_TDVF_UNACCEPTED \
+ (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_UNACCEPTED)
+
+#endif
diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c
index 48c04d344d..12b2e02fa2 100644
--- a/target/i386/kvm/tdx.c
+++ b/target/i386/kvm/tdx.c
@@ -19,6 +19,7 @@
#include "cpu.h"
#include "kvm_i386.h"
#include "hw/boards.h"
+#include "hw/i386/tdvf-hob.h"
#include "qapi/error.h"
#include "qom/object_interfaces.h"
#include "standard-headers/asm-x86/kvm_para.h"
@@ -67,8 +68,26 @@ static void __tdx_ioctl(void *state, int ioctl_no, const
char *ioctl_name,
#define tdx_ioctl(ioctl_no, metadata, data) \
_tdx_ioctl(kvm_state, ioctl_no, metadata, data)
+static TdxFirmwareEntry *tdx_get_hob_entry(TdxGuest *tdx)
+{
+ TdxFirmwareEntry *entry;
+
+ for_each_fw_entry(&tdx->fw, entry) {
+ if (entry->type == TDVF_SECTION_TYPE_TD_HOB) {
+ return entry;
+ }
+ }
+ error_report("TDVF metadata doesn't specify TD_HOB location.");
+ exit(1);
+}
+
static void tdx_finalize_vm(Notifier *notifier, void *unused)
{
+ MachineState *ms = MACHINE(qdev_get_machine());
+ TdxGuest *tdx = TDX_GUEST(ms->cgs);
+
+ tdvf_hob_create(tdx, tdx_get_hob_entry(tdx));
+
tdx_ioctl(KVM_TDX_FINALIZE_VM, 0, NULL);
}
--
2.25.1
- Re: [RFC PATCH v2 34/44] target/i386/tdx: set reboot action to shutdown when tdx, (continued)
- [RFC PATCH v2 06/44] hw/i386: Introduce kvm-type for TDX guest, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 05/44] linux-headers: Update headers to pull in TDX API changes, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 15/44] i386/tdx: Add hook to require generic device loader, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 18/44] hw/i386: refactor e820_add_entry(), isaku . yamahata, 2021/07/07
- [RFC PATCH v2 19/44] hw/i386/e820: introduce a helper function to change type of e820, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 41/44] ioapic: add property to disallow INIT/SIPI delivery mode, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 20/44] i386/tdx: Parse tdx metadata and store the result into TdxGuestState, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 22/44] i386/tdx: Add TDVF memory via INIT_MEM_REGION, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 21/44] i386/tdx: Create the TD HOB list upon machine init done,
isaku . yamahata <=
- [RFC PATCH v2 40/44] hw/i386: add a flag to disallow SMI, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 43/44] i386/tdx: disallow level interrupt and SMI/INIT/SIPI delivery mode, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 44/44] i386/tdx: disable S3/S4 unconditionally, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 25/44] q35: Move PCIe BAR check above PAM check in mch_write_config(), isaku . yamahata, 2021/07/07
- [RFC PATCH v2 24/44] i386/tdx: Add MMIO HOB entries, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 42/44] hw/i386: add a flag to disable init/sipi delivery mode of interrupt, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 23/44] i386/tdx: Use KVM_TDX_INIT_VCPU to pass HOB to TDVF, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 27/44] q35: Introduce smm_ranges property for q35-pci-host, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 28/44] i386/tdx: Force x2apic mode and routing for TDs, isaku . yamahata, 2021/07/07
- [RFC PATCH v2 26/44] pci-host/q35: Move PAM initialization above SMRAM initialization, isaku . yamahata, 2021/07/07