From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f199.google.com (mail-pf1-f199.google.com [209.85.210.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA69A53163C for ; Thu, 1 Oct 2026 19:38:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.199 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790883533; cv=none; b=oRLyTes/MVAr2GP0+EcAQlZX0DUgh1s7V8P22yW8BlACplb/naShTnRagkU45wYMv4zEZxpXkctg0PKuLsubW5YrjCen6d/9F5Lb5PluUciyrv7lrJ1kUFRdtzjY3T6uSyGs72klXpMVC8sG6XloZ6KvZ5XMVGa9d1HYh/PuT2o= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790883533; c=relaxed/simple; bh=rZSUlmnklCjSidXt9Wto0VjbnMY1avAw3XwYgF2UZS4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Vcm5AD8YNe4qhKyhhyeBIH48b6ZLVTtNtUlD8fMb+lv2WJnGKle4ts+nOLi77spLLOD9ZftZwHkzaSJNU5RBIOntwXfU+4RgH9xFXUmw+xn2g7iaX5W6MMkgFV2FYpdWHLe5UrHc7MQG/sgZ4YFuZ1s6HuHPc9XcgDZVb36Q8L4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--wyihan.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=R5aEG3TQ; arc=none smtp.client-ip=209.85.210.199 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--wyihan.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="R5aEG3TQ" Received: by mail-pf1-f199.google.com with SMTP id d2e1a72fcca58-8872ada18d7so2065899b3a.1 for ; Thu, 01 Oct 2026 12:38:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1790883530; x=1791488330; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=J/SHN0sSvwheqQ8KGKeFT7YW5j5XFWKj522jCKeXoSE=; b=R5aEG3TQzYmAxiX3NgSwgIg5ixBRa7YYd0Ws2oD1pm+TVe76DAOzxGwBE+Ir2UzcJ6 nMRlb85eXhpkElh/e9pobE9SnFPY61zZBtDPpKkqIzMgpQdgAb0yXCvVfOeZ1t2Zn7NQ ZlU7swZ9DTq66GreOQfa8+doiIqDTNqaARfi1wlYgdsXYo/qH6sIreOvEVCPw3OgyaeY YiPiM/7NOQe3jSaHbp5dxFRHst1ISzhbMmFHJsfIGt24HR/4XO5MSHqu8tKPKdqCiIiw 1lvo5wqUmYKXFOzA1Ra7yE3eIP+oDQbbKG8RuT8ZmihZcoGc3UhzCmxo3TUuOFefApcX D+5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790883530; x=1791488330; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=J/SHN0sSvwheqQ8KGKeFT7YW5j5XFWKj522jCKeXoSE=; b=0/CI4czJAjvaMxlEU0YoPbPv2Own+jKQpMAioQtfjxqkBL17oZKTb+yYGiv7F/qV4Q mb4DZE4TUF7xgz8NzOHhDp/79bnxynB6UwTMun0/HN07OFTSJ4zaijHF9xPFd5mI8v7W x3mC6ztMUH3OW2pScL6p5QDPW4F+5r91krfwgK23Rr92NOxqQth8EBExnQIYvuEpmiaM 6MGytEjpSPpq1SnI1U8u3yR8leoRZwNKehdIveJpalCckzjyl1tdNnspTnXhdfqOz5zT Fy5G4YPVqcJk4QOSSSmSJsQvVlazWDJRbT+lIvOSnEQxnbI5kCc2ZNCPdjUdiFzrCf4K tqMQ== X-Forwarded-Encrypted: i=1; AKwUvBx9jMaWcEuj7zWIAVGyAWtaiesDjrQv7uh6Y5Q9FPpVioVVdG1RCcYdmTCb6+8dOdv/o63H+UBzRVr6kac=@vger.kernel.org X-Gm-Message-State: AFuF++nGc8W/M8NzMYfiOJCcRCI+o49ipifEtnGJvHCfMa0iXAjCtVhT MdbSs7H+a3O7lNtPWfEdrho7G6I7i9MjSq7gxdlGAD9+MvwmsiLwZyHiKCrSBZBxXGUx6VmsJbU VkEMIbQ== X-Received: from pfbdn3.prod.google.com ([2002:a05:6a00:4983:b0:886:c063:eb7]) (user=wyihan job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:4191:b0:886:6722:5304 with SMTP id d2e1a72fcca58-88af5da4797mr440373b3a.34.1790883529931; Thu, 01 Oct 2026 12:38:49 -0700 (PDT) Date: Thu, 01 Oct 2026 19:37:36 +0000 In-Reply-To: <20261001-tdx-selftests-v15-0-7c62a5d8a992@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20261001-tdx-selftests-v15-0-7c62a5d8a992@google.com> X-Developer-Key: i=wyihan@google.com; a=ed25519; pk=cRi0fKzS5BMxlHyHY2pJv3w/1zcgfYKr6EYGYppdMYc= X-Developer-Signature: v=1; a=ed25519-sha256; t=1790883521; l=5394; i=wyihan@google.com; s=20260319; h=from:subject:message-id; bh=Ws6P4tgDetAmZ2/mm6SGsEyyc2B138SatS7RhdOPxLc=; b=P7GVXt2Awr63edHkWTDmNQqdN+eA8ellNEv1lNHinYr7k8YJXrRa4thSH5YtcaM9UWlHuoTSc EiO4ouGwrbKBaIld4BfmxHUKNg3dA193dMARMYwIqQGY43VMaTSuxPv X-Mailer: b4 0.14.3 Message-ID: <20261001-tdx-selftests-v15-9-7c62a5d8a992@google.com> Subject: [PATCH v15 09/23] KVM: selftests: Set up TDX boot code region From: Lisa Wang To: Andrew Jones , Ackerley Tng , Binbin Wu , Chao Gao , Chenyi Qiang , Dave Hansen , Erdem Aktas , Ira Weiny , Isaku Yamahata , Kiryl Shutsemau , linux-kselftest@vger.kernel.org, Paolo Bonzini , "Pratik R. Sampat" , Reinette Chatre , Rick Edgecombe , Roger Wang , Ryan Afranji , Sagi Shahar , Sean Christopherson , Shuah Khan , Xiaoyao Li , Oliver Upton Cc: Jeremiah McReynolds , kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org, x86@kernel.org, Lisa Wang Content-Type: text/plain; charset="utf-8" From: Sagi Shahar Because the reset vector is located just 16 bytes below the 4GB boundary, there is not enough space to fit the entire TDX boot code. To solve this, insert a small trampoline at the reset vector that jumps to the actual boot code. Place the boot code immediately in front of the trampoline. Because they are contiguous, they can be copied and mapped with a single operation. Use virt_map() to create an identity map in this memory region to allow for seamless transition from paging-disabled to paging-enabled code. Suggested-by: Sean Christopherson Co-developed-by: Erdem Aktas Signed-off-by: Erdem Aktas Signed-off-by: Sagi Shahar Signed-off-by: Lisa Wang Reviewed-by: Binbin Wu Reviewed-by: Xiaoyao Li --- .../selftests/kvm/include/x86/tdx/td_boot.h | 2 +- .../selftests/kvm/include/x86/tdx/tdx_util.h | 1 + tools/testing/selftests/kvm/lib/x86/processor.c | 4 ++- tools/testing/selftests/kvm/lib/x86/tdx/td_boot.S | 6 ++++ tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c | 35 ++++++++++++++++++++++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/td_boot.h b/tools/testing/selftests/kvm/include/x86/tdx/td_boot.h index 577e7b23c51c..8f47a3893f59 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/td_boot.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/td_boot.h @@ -72,7 +72,7 @@ struct td_boot_parameters { struct td_per_vcpu_parameters per_vcpu[]; }; -extern u8 td_boot[], td_boot_code_end[]; +extern u8 td_boot[], td_boot_code_end[], td_boot_reset_vector_trampoline[]; #define TD_BOOT_CODE_SIZE (td_boot_code_end - td_boot) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h b/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h index 571f7ce4b8fe..e14566919601 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h @@ -47,5 +47,6 @@ static inline bool is_tdx_vm(struct kvm_vm *vm) }) void tdx_init_vm(struct kvm_vm *vm); +void tdx_vm_setup_boot_code_region(struct kvm_vm *vm); #endif /* SELFTESTS_TDX_TDX_UTIL_H */ diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testing/selftests/kvm/lib/x86/processor.c index 0c3779e7c275..e3cf56c9c852 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -818,8 +818,10 @@ void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigned int nr_vcpus) vm_sev_ioctl(vm, KVM_SEV_INIT2, &init); } - if (is_tdx_vm(vm)) + if (is_tdx_vm(vm)) { tdx_init_vm(vm); + tdx_vm_setup_boot_code_region(vm); + } r = __vm_ioctl(vm, KVM_GET_TSC_KHZ, NULL); TEST_ASSERT(r > 0, "KVM_GET_TSC_KHZ did not provide a valid TSC frequency."); diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/td_boot.S b/tools/testing/selftests/kvm/lib/x86/tdx/td_boot.S index 726ec51e040e..a04011b91ae4 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/td_boot.S +++ b/tools/testing/selftests/kvm/lib/x86/tdx/td_boot.S @@ -56,6 +56,12 @@ td_boot: ljmp $(KERNEL_CS),$1f 1: jmp *TD_PER_VCPU_PARAMETERS_GUEST_CODE(%eax) + int3 + +.globl td_boot_reset_vector_trampoline +td_boot_reset_vector_trampoline: + jmp td_boot + int3 /* Leave marker so size of td_boot code can be computed. */ .globl td_boot_code_end diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c index 3a8900ff2540..6187cfcf6a74 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c @@ -1,8 +1,43 @@ // SPDX-License-Identifier: GPL-2.0-only +#include + #include "processor.h" +#include "tdx/td_boot.h" #include "tdx/tdx_util.h" +/* Arbitrarily selected to avoid overlaps with anything else */ +#define TD_BOOT_CODE_SLOT 20 + +#define X86_RESET_VECTOR 0xfffffff0ul + +void tdx_vm_setup_boot_code_region(struct kvm_vm *vm) +{ + const size_t total_size = td_boot_code_end - td_boot; + const size_t boot_code_size = td_boot_reset_vector_trampoline - td_boot; + const gpa_t boot_code_gpa = X86_RESET_VECTOR - boot_code_size; + gpa_t alloc_gpa = round_down(boot_code_gpa, PAGE_SIZE); + size_t nr_pages = (SZ_4G - alloc_gpa) / PAGE_SIZE; + u64 gmem_flags = 0; + gpa_t gpa; + u8 *hva; + + vm_mem_add(vm, VM_MEM_SRC_SHMEM, alloc_gpa, TD_BOOT_CODE_SLOT, + nr_pages, KVM_MEM_GUEST_MEMFD, -1, 0, gmem_flags); + + gpa = vm_phy_pages_alloc(vm, nr_pages, alloc_gpa, TD_BOOT_CODE_SLOT); + TEST_ASSERT(gpa == alloc_gpa, "Failed vm_phy_pages_alloc\n"); + + virt_map(vm, alloc_gpa, alloc_gpa, nr_pages); + hva = addr_gpa2hva(vm, boot_code_gpa); + memcpy(hva, td_boot, total_size); + + hva += boot_code_size; + TEST_ASSERT(hva == addr_gpa2hva(vm, X86_RESET_VECTOR), + "Expected RESET vector at hva 0x%lx, got %lx", + (unsigned long)addr_gpa2hva(vm, X86_RESET_VECTOR), (unsigned long)hva); +} + static const struct kvm_tdx_capabilities *tdx_read_capabilities(struct kvm_vm *vm) { static struct kvm_tdx_capabilities *tdx_cap; -- 2.56.0.rc1.315.gc6ed9934b7-goog