From nobody Mon Feb 9 19:08:55 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1625707277463610.2842507415921; Wed, 7 Jul 2021 18:21:17 -0700 (PDT) Received: from localhost ([::1]:34054 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1Ij6-0006UK-1x for importer@patchew.org; Wed, 07 Jul 2021 21:21:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38282) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1ILC-0002ro-RF for qemu-devel@nongnu.org; Wed, 07 Jul 2021 20:56:36 -0400 Received: from mga06.intel.com ([134.134.136.31]:36379) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1IL7-0007L4-Uf for qemu-devel@nongnu.org; Wed, 07 Jul 2021 20:56:33 -0400 Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jul 2021 17:55:56 -0700 Received: from ls.sc.intel.com (HELO localhost) ([143.183.96.54]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jul 2021 17:55:56 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10038"; a="270534904" X-IronPort-AV: E=Sophos;i="5.84,222,1620716400"; d="scan'208";a="270534904" X-IronPort-AV: E=Sophos;i="5.84,222,1620716400"; d="scan'208";a="423770056" From: isaku.yamahata@gmail.com To: qemu-devel@nongnu.org, pbonzini@redhat.com, alistair@alistair23.me, ehabkost@redhat.com, marcel.apfelbaum@gmail.com, mst@redhat.com, cohuck@redhat.com, mtosatti@redhat.com, xiaoyao.li@intel.com, seanjc@google.com, erdemaktas@google.com 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 Message-Id: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=134.134.136.31; envelope-from=isaku.yamahata@intel.com; helo=mga06.intel.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_ADSP_CUSTOM_MED=0.001, FORGED_GMAIL_RCVD=1, FREEMAIL_FORGED_FROMDOMAIN=0.25, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25, NML_ADSP_CUSTOM_MED=0.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: isaku.yamahata@intel.com, Sean Christopherson , isaku.yamahata@gmail.com, kvm@vger.kernel.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZM-MESSAGEID: 1625707279455100001 Content-Type: text/plain; charset="utf-8" From: Isaku Yamahata Build the TD HOB during machine late initialization, i.e. once guest memory is fully defined. Signed-off-by: Isaku Yamahata Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson --- 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')) =20 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 + * + * + * 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 . + */ + +#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 =3D 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 =3D 0x%" PRIx64, size); + exit(1); + } + + ret =3D hob->current; + hob->current +=3D size; + tdvf_align(hob, 8); + return ret; +} + +static int tdvf_e820_compare(const void *lhs_, const void* rhs_) +{ + const struct e820_entry *lhs =3D lhs_; + const struct e820_entry *rhs =3D rhs_; + + if (lhs->address =3D=3D 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 =3D e820_get_num_entries(); + e820_entries =3D 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 =3D 0; i < nr_e820_entries; i++) { + e820_entry =3D &e820_entries[i]; + + if (le32_to_cpu(e820_entry->type) =3D=3D E820_RAM) { + resource_type =3D EFI_RESOURCE_SYSTEM_MEMORY; + attr =3D EFI_RESOURCE_ATTRIBUTE_TDVF_UNACCEPTED; + } else { + resource_type =3D EFI_RESOURCE_MEMORY_RESERVED; + attr =3D EFI_RESOURCE_ATTRIBUTE_TDVF_PRIVATE; + } + + region =3D tdvf_get_area(hob, sizeof(*region)); + *region =3D (EFI_HOB_RESOURCE_DESCRIPTOR) { + .Header =3D { + .HobType =3D EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, + .HobLength =3D cpu_to_le16(sizeof(*region)), + .Reserved =3D cpu_to_le32(0), + }, + .Owner =3D EFI_HOB_OWNER_ZERO, + .ResourceType =3D cpu_to_le32(resource_type), + .ResourceAttribute =3D cpu_to_le32(attr), + .PhysicalStart =3D e820_entry->address, + .ResourceLength =3D e820_entry->length, + }; + } + + g_free(e820_entries); +} + +void tdvf_hob_create(TdxGuest *tdx, TdxFirmwareEntry *hob_entry) +{ + TdvfHob hob =3D { + .hob_addr =3D hob_entry->address, + .ptr =3D hob_entry->mem_ptr, + .size =3D hob_entry->size, + + .current =3D hob_entry->mem_ptr, + .end =3D 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 =3D tdvf_get_area(&hob, sizeof(*hit)); + *hit =3D (EFI_HOB_HANDOFF_INFO_TABLE) { + .Header =3D { + .HobType =3D EFI_HOB_TYPE_HANDOFF, + .HobLength =3D cpu_to_le16(sizeof(*hit)), + .Reserved =3D cpu_to_le32(0), + }, + .Version =3D cpu_to_le32(EFI_HOB_HANDOFF_TABLE_VERSION), + .BootMode =3D cpu_to_le32(0), + .EfiMemoryTop =3D cpu_to_le64(0), + .EfiMemoryBottom =3D cpu_to_le64(0), + .EfiFreeMemoryTop =3D cpu_to_le64(0), + .EfiFreeMemoryBottom =3D cpu_to_le64(0), + .EfiEndOfHobList =3D cpu_to_le64(0), /* initialized later */ + }; + + tdvf_hob_add_memory_resources(&hob); + + last_hob =3D tdvf_get_area(&hob, sizeof(*last_hob)); + *last_hob =3D (EFI_HOB_GENERIC_HEADER) { + .HobType =3D EFI_HOB_TYPE_END_OF_HOB_LIST, + .HobLength =3D cpu_to_le16(sizeof(*last_hob)), + .Reserved =3D cpu_to_le32(0), + }; + hit->EfiEndOfHobList =3D 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) =20 +static TdxFirmwareEntry *tdx_get_hob_entry(TdxGuest *tdx) +{ + TdxFirmwareEntry *entry; + + for_each_fw_entry(&tdx->fw, entry) { + if (entry->type =3D=3D 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 =3D MACHINE(qdev_get_machine()); + TdxGuest *tdx =3D TDX_GUEST(ms->cgs); + + tdvf_hob_create(tdx, tdx_get_hob_entry(tdx)); + tdx_ioctl(KVM_TDX_FINALIZE_VM, 0, NULL); } =20 --=20 2.25.1