From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (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 9F589224240 for ; Thu, 7 Aug 2025 20:16:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597801; cv=none; b=jSxCTEX/L3kGSPWirYEZFV7FKB3xR9JdXh9QQ3DsQCZOqd2GmCnwro7P5+l21ReRK9qDIkjlS1XvQsRJPMw3DbYiLcLHh0laxz1FmhBuntXntPtXQpR3XRBTJhqKQYDFwcycZ/h5E620UTqJD6liLyy7izLVvRBy7tN6ubLoYjQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597801; c=relaxed/simple; bh=ZGm78cVu0eE8NMdDtBRB7S6EsWyYptmULKCe3VJEPzw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=K3oI5NIDzmldkh4MCzwoXBgCIpM8YJZwP2HLk8zlgW79ENPx7pOERw+EiGpv6Wwf05jOV/kzSg71ImHn4Gn3twqMgNjNeBqppnrx+WReStxcZSU4HJVXw5VphjOEeN1mttQ2suuKgqirY8zvknEIh89ofwjFoK63DOE7PfDV8Mk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=KUNPzBGX; arc=none smtp.client-ip=209.85.216.74 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="KUNPzBGX" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-31f74a64da9so1615031a91.2 for ; Thu, 07 Aug 2025 13:16:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597799; x=1755202599; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Z4PvKVoMzsbWuS6ZNQkHyRpKtVjC8q7nP9qV4BuVoxE=; b=KUNPzBGXuk1sv+jl+byzxQRbS/vJ9iOIor2YSOXTcPW0eFYZwJmm+2mS8oIwraujsR Qtf59XKVr4Qp29P7lRnQYcTkxlqY/bSmozJoJLKzbrsiGd0CqX+IRdkZdkVzCzneN5pu NcuyVD2TAzr0n715DDJYruVl4kWEiMEV2OOTxqik6+o2nupHnAibL8AobsbaB+hTaWuA 8y2O992f8vYqbBtZDyoGpyVBRy8TpcmSI8wbLDrWllcCrFYlwnMBwobWVfF2rPLEi5ew 4WITXpntEKoNyNntbbN+Bxd07IOdzwCFWrq3ouMTqv+e9i0AIPSWFIeBr0CB0d4LZsZ5 KUow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597799; x=1755202599; h=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; bh=Z4PvKVoMzsbWuS6ZNQkHyRpKtVjC8q7nP9qV4BuVoxE=; b=Ay/16tyyHiUXuUOwE7cFfKypqtlGPQRNmJI4lJMGAj1QwVop43YwbPTnNoqUYYPkoT Qa7JsM+SA0ixhryftYtgFXreKO7g29QyYg+xIL6yn4/wyreL/gLSyjfYe7bXPVQTY9Og EFq18CrpoWREgKrlPTKd2KYkJuylNo+oGwz5qeuoaMcGHXPO68IN/qXZUPzLuF5N0IM+ jW2bYZznAqcNy5iujzviX5ISNAZdiv/OgyUozjHVnTwd9mXrrmOvSr3fvM8FZZkcjaZQ +9eAiAHtDLhRbuOgefvK6i+u6azrlwfFqqEwzxEQkIBWPKbypmEz4w2l0iAX3ANOOPTT drqA== X-Gm-Message-State: AOJu0YxhjNjzpXZMq7Xl3Js6+V1TeqRpavbYeAHJI9MMfIoo8xXkiq8H ZqC5b+y3Ouee8dH1TdqgUnIRRm9HvQkVBdwY/7SZeyP8Yj0F0kZbr46epDthSLJUnd6mRQ4DqmL HqQ== X-Google-Smtp-Source: AGHT+IHlHTUzlI4XwfrvCHdPuSXY+IAAqyr2BEu6Hs2JizbOH4J+KBh8PsRSDzHe1VZ8MTVIYlqnupSA+w== X-Received: from pjx13.prod.google.com ([2002:a17:90b:568d:b0:31e:fe0d:f464]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:28c5:b0:31a:ab75:6e45 with SMTP id 98e67ed59e1d1-32183c42d6dmr439441a91.28.1754597799003; Thu, 07 Aug 2025 13:16:39 -0700 (PDT) Date: Thu, 7 Aug 2025 13:15:57 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-2-sagis@google.com> Subject: [PATCH v8 01/30] KVM: selftests: Add function to allow one-to-one GVA to GPA mappings From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng One-to-one GVA to GPA mappings can be used in the guest to set up boot sequences during which paging is enabled, hence requiring a transition from using physical to virtual addresses in consecutive instructions. Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- .../testing/selftests/kvm/include/kvm_util.h | 3 +++ tools/testing/selftests/kvm/lib/kvm_util.c | 27 +++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index bee65ca08721..9994861d2acb 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -650,6 +650,9 @@ vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t s= z, vm_vaddr_t vaddr_min, vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, enum kvm_mem_region_type type); +vm_vaddr_t vm_vaddr_identity_alloc(struct kvm_vm *vm, size_t sz, + vm_vaddr_t vaddr_min, + enum kvm_mem_region_type type); vm_vaddr_t vm_vaddr_alloc_pages(struct kvm_vm *vm, int nr_pages); vm_vaddr_t __vm_vaddr_alloc_page(struct kvm_vm *vm, enum kvm_mem_region_type type); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index a055343a7bf7..8f3dbf749afa 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1460,15 +1460,14 @@ vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, s= ize_t sz, } =20 static vm_vaddr_t ____vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, - vm_vaddr_t vaddr_min, + vm_vaddr_t vaddr_min, vm_paddr_t paddr_min, enum kvm_mem_region_type type, bool protected) { uint64_t pages =3D (sz >> vm->page_shift) + ((sz % vm->page_size) !=3D 0); =20 virt_pgd_alloc(vm); - vm_paddr_t paddr =3D __vm_phy_pages_alloc(vm, pages, - KVM_UTIL_MIN_PFN * vm->page_size, + vm_paddr_t paddr =3D __vm_phy_pages_alloc(vm, pages, paddr_min, vm->memslots[type], protected); =20 /* @@ -1492,7 +1491,7 @@ static vm_vaddr_t ____vm_vaddr_alloc(struct kvm_vm *v= m, size_t sz, vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr= _min, enum kvm_mem_region_type type) { - return ____vm_vaddr_alloc(vm, sz, vaddr_min, type, + return ____vm_vaddr_alloc(vm, sz, vaddr_min, KVM_UTIL_MIN_PFN * vm->page_= size, type, vm_arch_has_protected_memory(vm)); } =20 @@ -1500,7 +1499,25 @@ vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, = size_t sz, vm_vaddr_t vaddr_min, enum kvm_mem_region_type type) { - return ____vm_vaddr_alloc(vm, sz, vaddr_min, type, false); + return ____vm_vaddr_alloc(vm, sz, vaddr_min, KVM_UTIL_MIN_PFN * vm->page_= size, type, false); +} + +/* + * Allocate memory in @vm of size @sz beginning with the desired virtual a= ddress + * of @vaddr_min and backed by physical address equal to returned virtual + * address. + * + * Return the address where the memory is allocated. + */ +vm_vaddr_t vm_vaddr_identity_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_= t vaddr_min, + enum kvm_mem_region_type type) +{ + vm_vaddr_t gva =3D ____vm_vaddr_alloc(vm, sz, vaddr_min, + (vm_paddr_t)vaddr_min, type, + vm_arch_has_protected_memory(vm)); + TEST_ASSERT_EQ(gva, addr_gva2gpa(vm, gva)); + + return gva; } =20 /* --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 60D642367C4 for ; Thu, 7 Aug 2025 20:16:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597802; cv=none; b=EQjhHZ3LrgxMZx275Oe6UkQwpggRC9FOqf2VornJB3w3CUKnv475++Yh1DpJ5tLVJpxPCffayoy4dfAC7AOsSgsjhE0ZjidKxi/kY/V/RovCkzmmCxJ61vB5F6NXQXDQDch/gXsVGaOJjuVY4MeVIl0BuzgQPZIqzwNmUFZVfhY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597802; c=relaxed/simple; bh=E7TcgZfVGcTLwtlC4VOwdxSg2cQOQ5DOom54BBEpctU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=u5tAmmJt6fZNKZ/RmYzdAHgrHSnRAv/2n6z3PDtFC3BzUMvhpvoeRa05haLusqfO1iTBl7CihEk3CqZmEQWTIMb2U3Hd4cIaW8q/EkxL+n8DUQ3j4+J14xDEcaNrNScC2RSp2i6WX8DOKRV0Mh+pSPxjQNveJaOxi+o1P5f6H6M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=mtX7wLFz; arc=none smtp.client-ip=209.85.216.73 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="mtX7wLFz" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-31f4d0f60caso1435358a91.1 for ; Thu, 07 Aug 2025 13:16:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597800; x=1755202600; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=0Mbc3Ap17+SGeKDAF7BMv5oS325KPPu2sX6X04CM9sg=; b=mtX7wLFzU8+LDljRiejDUWQsRpoPCpACASNoiUA88mtwetuIwcpTJj5ma7JjLYv1C7 lFZIUMe9wf+W6OvUVcvDXMiNOzRuL2X2KhjZSZ36HaSBQ908eDtD4p6swrpVlvC1b3oL odHLjzFftVuknawI9zmXxY5Lq/4/efBIgGez7dXLR23n1M8rLPcnVmbfqsPtrjv4fuje zR749Yvi8yHkoaLPvqLfAF0W9WabaMSJEGIDo8M4K5MFUQBCHfgMQuJWgM5IyDzhqMZ+ eRMYlxUC33pRg4c8R6Ow1Wdp963qGBW03ikD9u49Ct+GIxNAQlq9aJQc9CIVACtycMDd FocQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597800; x=1755202600; h=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; bh=0Mbc3Ap17+SGeKDAF7BMv5oS325KPPu2sX6X04CM9sg=; b=aHBwGBbDOo2ifZFChEDh//EtzXhke7Xu4n6RhgKgUDbhTLVD/03MlwhWgcMqaUTeyx wYDNclGJ6bPJH8HoQgj4KWrDuPG7zbkj5VLWwhWLbo6lbdzE/NzgT5KOt2jzXIY9HJFn oWSbBnLnS2WS14xgnLiQWnYLJ24UB5b1hN9YgreAc3BP9GD3XnquSlcffZMVbIVXE/MT UkRT0WdG2GPkQBTW/Rdj2uVdv5xzgSl/QuZ6xMIm1smQaFpYM6/185v3Jwy2rRZIvOT0 /FbEVLrvbjyMAYR1HRgcl64QzaClqdwoaPDC7v+DCgJrxFRUEadQAmbjRljDf1xMR2Fj aZYA== X-Gm-Message-State: AOJu0Yz4ckIOYTDwr6Q8Q8Lm6a/jeBsHS//RzqA8q2HzMX0yPeVI2Jx8 Cb8aOyfa4kFIwnRo1I1J3VVpK/YHqllgh0SCuG3MzsM2uFYWgrTLoxu8RG90tJ4o1CZc8gTAOM8 wsg== X-Google-Smtp-Source: AGHT+IGWU7OhyJ0pzBHtOYnTYwcGZIHyA770GRe7gIxY2qpTfZC9Od7tXnutcry2JK0QfyTciR3VHzO94A== X-Received: from pjnx5.prod.google.com ([2002:a17:90a:8a85:b0:31f:335d:342d]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4c11:b0:321:265a:e0c2 with SMTP id 98e67ed59e1d1-32183e55b63mr341966a91.32.1754597800513; Thu, 07 Aug 2025 13:16:40 -0700 (PDT) Date: Thu, 7 Aug 2025 13:15:58 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-3-sagis@google.com> Subject: [PATCH v8 02/30] KVM: selftests: Expose function that sets up sregs based on VM's mode From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng This allows initializing sregs without setting vCPU registers in KVM. No functional change intended. Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/processor.h | 1 + .../testing/selftests/kvm/lib/x86/processor.c | 45 ++++++++++--------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index b11b5a53ebd5..f2eb764cbd7c 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -1025,6 +1025,7 @@ static inline struct kvm_cpuid2 *allocate_kvm_cpuid2(= int nr_entries) } =20 void vcpu_init_cpuid(struct kvm_vcpu *vcpu, const struct kvm_cpuid2 *cpuid= ); +void vcpu_setup_mode_sregs(struct kvm_vm *vm, struct kvm_sregs *sregs); =20 static inline void vcpu_get_cpuid(struct kvm_vcpu *vcpu) { diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index a92dc1dad085..002303e2a572 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -488,34 +488,37 @@ static void kvm_seg_set_tss_64bit(vm_vaddr_t base, st= ruct kvm_segment *segp) segp->present =3D 1; } =20 -static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu) +void vcpu_setup_mode_sregs(struct kvm_vm *vm, struct kvm_sregs *sregs) { - struct kvm_sregs sregs; - TEST_ASSERT_EQ(vm->mode, VM_MODE_PXXV48_4K); =20 - /* Set mode specific system register values. */ - vcpu_sregs_get(vcpu, &sregs); - - sregs.idt.base =3D vm->arch.idt; - sregs.idt.limit =3D NUM_INTERRUPTS * sizeof(struct idt_entry) - 1; - sregs.gdt.base =3D vm->arch.gdt; - sregs.gdt.limit =3D getpagesize() - 1; + sregs->idt.base =3D vm->arch.idt; + sregs->idt.limit =3D NUM_INTERRUPTS * sizeof(struct idt_entry) - 1; + sregs->gdt.base =3D vm->arch.gdt; + sregs->gdt.limit =3D getpagesize() - 1; =20 - sregs.cr0 =3D X86_CR0_PE | X86_CR0_NE | X86_CR0_PG; - sregs.cr4 |=3D X86_CR4_PAE | X86_CR4_OSFXSR; + sregs->cr0 =3D X86_CR0_PE | X86_CR0_NE | X86_CR0_PG; + sregs->cr4 |=3D X86_CR4_PAE | X86_CR4_OSFXSR; if (kvm_cpu_has(X86_FEATURE_XSAVE)) - sregs.cr4 |=3D X86_CR4_OSXSAVE; - sregs.efer |=3D (EFER_LME | EFER_LMA | EFER_NX); + sregs->cr4 |=3D X86_CR4_OSXSAVE; + sregs->efer |=3D (EFER_LME | EFER_LMA | EFER_NX); + + kvm_seg_set_unusable(&sregs->ldt); + kvm_seg_set_kernel_code_64bit(&sregs->cs); + kvm_seg_set_kernel_data_64bit(&sregs->ds); + kvm_seg_set_kernel_data_64bit(&sregs->es); + kvm_seg_set_kernel_data_64bit(&sregs->gs); + kvm_seg_set_tss_64bit(vm->arch.tss, &sregs->tr); =20 - kvm_seg_set_unusable(&sregs.ldt); - kvm_seg_set_kernel_code_64bit(&sregs.cs); - kvm_seg_set_kernel_data_64bit(&sregs.ds); - kvm_seg_set_kernel_data_64bit(&sregs.es); - kvm_seg_set_kernel_data_64bit(&sregs.gs); - kvm_seg_set_tss_64bit(vm->arch.tss, &sregs.tr); + sregs->cr3 =3D vm->pgd; +} + +static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu) +{ + struct kvm_sregs sregs; =20 - sregs.cr3 =3D vm->pgd; + vcpu_sregs_get(vcpu, &sregs); + vcpu_setup_mode_sregs(vm, &sregs); vcpu_sregs_set(vcpu, &sregs); } =20 --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pg1-f201.google.com (mail-pg1-f201.google.com [209.85.215.201]) (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 A97C42417C3 for ; Thu, 7 Aug 2025 20:16:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597804; cv=none; b=kBswYOLweX1rVkw6mm6Ri8xpOiwrjTo0qmvFh+i+j1l0onmBJdVgZEo+7/o6HR5XXHUUnUdW9ppqAG9JxEic+LWf/7x+Dw6BQHO14boUabsB25GK2bNqlTeoWLFLSKAfxzRR9nFEia+szrL770azhMIaC47T+RUoUZlDAq48L08= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597804; c=relaxed/simple; bh=KOoCqu20ck1nvt78qXS9AASI1nzd75am6SWO6mncJgo=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=gSOGXyeVYKZtHJj4tzyFRqctMXSwjNiPiDhHAGZOkqTrhV1WaZayuZZxASIRJhPNETmnHNhCBzda2kp7i/0UucPSecV81/45AsVlkxQIximWMMEDCtkBOdeO4aWS+VPDxHihyEoegO1W41NPryGvnmON0R3TiFIgBH9XkET+9xs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=hMmx0oYs; arc=none smtp.client-ip=209.85.215.201 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="hMmx0oYs" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b2c37558eccso1200308a12.1 for ; Thu, 07 Aug 2025 13:16:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597802; x=1755202602; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=SY1063A3eM4jRKn9Lwg/S7WLjF7eZucmIixEhnmKPCk=; b=hMmx0oYsdjn7KlMNcJTZeUkYVJbkfVI5BM4olXFkYdlYoCIyV/n6Wa11ABEHQlKlfO p+cntW22meeHlU9gZriYiRXwVWG3F8J6XFYriehk7rHoe4X8kafK0ATuXWwMbChgczt2 1iCoEjOwiW6qSAxZwb/3xy4Fok3b2HsyjKMNu9c0kvK3pgf3b+9nGNTmJddJZ6+50GGJ uiWn6WWZQINbRSW+VaqU/UI3XYbk3ngh/M5bVSC6VJPEvDhu/q+0ZsYeBPrsRQ9Qtsek pHbQMikiEfZodnP5Q49oOQcZeS282ZyDL5b5JFSRHVa/mts5Jrx24MH11E8n08nzJCvR 2m0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597802; x=1755202602; h=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; bh=SY1063A3eM4jRKn9Lwg/S7WLjF7eZucmIixEhnmKPCk=; b=pnJI8uJRjpjrGuu+s1LRfyAhjgpGx/A4rkv+MQM+sQXhO7ge1k1Ac/mJ+xJZStstGQ 4fofHsGn4+IkI2swmt441Qs3M3dtzVHG0kRXfWQRQ0Fec60/WIugqlE2TG9mv2PRhNvh Zd4FQE6s7f0GSTZvnOCOuC00GuJcdfoaa1XnnMR86qDgpPnTsdSb/6Pm8DapPClscFyN HR1VOn9CHUpotg0FwbtlGEgEyjPp8LR42mfNKgbflyf3p/ad2snNonKCcQyf6kEV5GNm /DcibiCPt+LuPwfmVsx7KwZMmh4RFq7PThFqt9XFU6I9ikh9FR1NIy1Asen3APCPuIoP QCdg== X-Gm-Message-State: AOJu0YxmD6ij+yZHaT2rfFi6J8tjtOpxFa2EA3Nm8EVeMISsdC1FfQHl C4wpRv08iZszEYg0K85mrfP8MPHNhEwrpqgckTl/TjOj91ZRh62N980KfIUuISdUETcWaEtOpLk 6yA== X-Google-Smtp-Source: AGHT+IHr+KQP67F9tu5jX/oDeI0DglRUP8n3J9QXbxBj/BZFmCvo1Gke3fbBZ35nerS00VBumho8cM4uag== X-Received: from pldy12.prod.google.com ([2002:a17:902:cacc:b0:240:2d28:e064]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:1b26:b0:240:41a3:8e0d with SMTP id d9443c01a7336-242c221775bmr4503185ad.36.1754597801923; Thu, 07 Aug 2025 13:16:41 -0700 (PDT) Date: Thu, 7 Aug 2025 13:15:59 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-4-sagis@google.com> Subject: [PATCH v8 03/30] KVM: selftests: Store initial stack address in struct kvm_vcpu From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng TDX guests' registers cannot be initialized directly using vcpu_regs_set(), hence the stack pointer needs to be initialized by the guest itself, running boot code beginning at the reset vector. Store the stack address as part of struct kvm_vcpu so that it can be accessible later to be passed to the boot code for rsp initialization. Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/include/kvm_util.h | 1 + tools/testing/selftests/kvm/lib/x86/processor.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index 9994861d2acb..5c4ca25803ac 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -58,6 +58,7 @@ struct kvm_vcpu { int fd; struct kvm_vm *vm; struct kvm_run *run; + vm_vaddr_t initial_stack_addr; #ifdef __x86_64__ struct kvm_cpuid2 *cpuid; #endif diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index 002303e2a572..da6e9315ebe2 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -694,6 +694,8 @@ struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, ui= nt32_t vcpu_id) vcpu_init_sregs(vm, vcpu); vcpu_init_xcrs(vm, vcpu); =20 + vcpu->initial_stack_addr =3D stack_vaddr; + /* Setup guest general purpose registers */ vcpu_regs_get(vcpu, ®s); regs.rflags =3D regs.rflags | 0x2; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 252482737EC for ; Thu, 7 Aug 2025 20:16:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597805; cv=none; b=Q6EgnnXpRzuDca2I+IDNJz/lf/VOIBbGxG8LW3X5s/Xj0irrNMNdfAIUVm/1HQw5ixpIJ9bsB7+Y3lMXMLEtL8jheL5FemQhAp5lVY1TtfGYlUWTRjs6ZMfXDGqfdF1upFBC58B04qV0PhGpLbJkE+6w97U6XEtLBaclY126aPA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597805; c=relaxed/simple; bh=vvoyDwfrz40cXS2E/qfKw0KPWURpKZQSXbiY0G7zSzI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=gaZ9O5UeOzltq9kphLYOU+MRtSnQXqhkCT4GIzD2a86r4U/d9PNCoZEHsP3pUhxxG13fw5v3GmHqaCeyx+7TBIiiiaLga8G37kPCqp3G5s6dYsOt4W8qq9feqSJSAG1vNFW68Vr8TG3sABrrK4HDDhUfiPR6GlPPhFrrjehLVxM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=k68Pe9QS; arc=none smtp.client-ip=209.85.216.73 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="k68Pe9QS" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-315af08594fso1755885a91.2 for ; Thu, 07 Aug 2025 13:16:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597803; x=1755202603; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=4ZhMhm+oGoXjR1ZKMvnfqRkH9sxXvmJdgGAeHzetkDQ=; b=k68Pe9QSBBrKDbEBN5dUL1XNCnuokeOQkA0CnjBPEAkuCVl3X4m2aErekq/HEpm2vJ a4i2Z94Rz6n6CM2LYx/wYFRFNtbixIoYi1GuJh+lw7K/py6pvAtfPFlqN0ccCduLITbe v7b94KAmE2h2kT4p8NhdW3gBltVXJiipGbwjcG7dHJwpkKxlq36/kbg3jqsjG6a5sa37 5mACZv9JfwpLcDN4z3DSEmXRoNiovdyUfH2gtSeJDzDs1F4YdgAUW61cGjU5RQCWzXtz Y83LaCpfzYbbw3nNKXJmJbh6MeENE58TU7XyyOmbwyiz1+j37ap3EQY3oQiEfcam+zjQ p1fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597803; x=1755202603; h=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; bh=4ZhMhm+oGoXjR1ZKMvnfqRkH9sxXvmJdgGAeHzetkDQ=; b=RsrZTv7H429ctd7CNjQTcMtLQAOyE7nJZMUJ9lOF8HTm8z33mimqlBZ3d0sNAZx8W5 kEj6dgbojWCw8fZ0UVglBcbb5OEaTY/m7TNCWnllkGnrTiEZvQ7DKGr3rviqpsDE1Y1o ahezknKBIJ0qPxS6yEiaO2pxgd2w+abHBiWGBlP+ykq8PuCQeThqy7c6nrbM9EWPNXvb 9/6Q3u7YlzCAc0sYR1RNx2YOZweah6o4Gg7cSs9ztOsBIsun8Ybys95H2kO8I6xrS8hu S7QUDi3lcv4XZ3Ql0qFPIjgSOjOgzbuBeVrk1ZPPhljZLZHVoXDoKqypPCDMXaFaGyjj wyrw== X-Gm-Message-State: AOJu0YySA2A8vIGwZA9oOJgiY5k7C01wkQ15bzi56gyWPS7YeghfvNZd XukGJ9Dpj2xypDHdewLkwbbGYGt2/U41QNMdCcpSq4pqLkcD7XcNQV0GsBbeDl5Zr2ZijfsdFqQ qgw== X-Google-Smtp-Source: AGHT+IHjDcLQX1WhIoIZLM1WoaOz3EieXlE18GHV1p955qAC5wr4S8qpo4H4d6sFinEdYcxFY537Ys6L5w== X-Received: from pjbqb13.prod.google.com ([2002:a17:90b:280d:b0:31f:61fc:b283]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:1f90:b0:31e:c8fc:e630 with SMTP id 98e67ed59e1d1-32183c46068mr418295a91.26.1754597803497; Thu, 07 Aug 2025 13:16:43 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:00 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-5-sagis@google.com> Subject: [PATCH v8 04/30] KVM: selftests: Add vCPU descriptor table initialization utility From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng Turn vCPU descriptor table initialization into a utility for use by tests needing finer control, for example for TDX TD creation. Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/include/x86/processor.h | 1 + tools/testing/selftests/kvm/lib/x86/processor.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index f2eb764cbd7c..37ad1e4d86ba 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -1178,6 +1178,7 @@ struct idt_entry { uint32_t offset2; uint32_t reserved; }; =20 +void sync_exception_handlers_to_guest(struct kvm_vm *vm); void vm_install_exception_handler(struct kvm_vm *vm, int vector, void (*handler)(struct ex_regs *)); =20 diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index da6e9315ebe2..d082d429e127 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -585,6 +585,11 @@ void route_exception(struct ex_regs *regs) regs->vector, regs->rip); } =20 +void sync_exception_handlers_to_guest(struct kvm_vm *vm) +{ + *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) =3D vm= ->handlers; +} + static void vm_init_descriptor_tables(struct kvm_vm *vm) { extern void *idt_handlers; @@ -600,7 +605,7 @@ static void vm_init_descriptor_tables(struct kvm_vm *vm) for (i =3D 0; i < NUM_INTERRUPTS; i++) set_idt_entry(vm, i, (unsigned long)(&idt_handlers)[i], 0, KERNEL_CS); =20 - *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) =3D vm= ->handlers; + sync_exception_handlers_to_guest(vm); =20 kvm_seg_set_kernel_code_64bit(&seg); kvm_seg_fill_gdt_64bit(vm, &seg); --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 AA1E12741D0 for ; Thu, 7 Aug 2025 20:16:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597807; cv=none; b=ulgU0SzlO/PFQ+3bZ3uw80s3Va5p3+HHAbMM0AJLGUzsJD1UakIB1ljfgnEhZrkNHA05DVMkbp2MuKrKuz9Y3IpgiMjC9uzuvCgwo36fg5zYMgqCAReaNld0giXZTIV2mByrPoAf2F3bwUtnDBj7ir/a1lDhVQRfs2K+UX/yBGc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597807; c=relaxed/simple; bh=PjccjVZAkRo3Xaj2t4Gs6E0VQOqy8N8IPb4hRIjeToc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=UG/FrFvhPBOb87k/Mbm07D/67XBv6IEbSEJ3RjlYomT54EhKIOL026v7fWez1frRyAiPkePnOG8Wjy8aXwETdnZoABb4yfTt0UYkDgOKAsaGywXTpENdTOGYqtROkZNtJpWXBeeUxEqAQUODHclFB5ZRbvKXtb0rZwBXfbpt9pE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ODLv0IeJ; arc=none smtp.client-ip=209.85.216.73 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ODLv0IeJ" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-315af08594fso1755909a91.2 for ; Thu, 07 Aug 2025 13:16:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597805; x=1755202605; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=6CCwqPAnoUPSp9AFnzO+u9qSxg+vLNhYcEQUdXsIl0A=; b=ODLv0IeJlzv+ykKM2JlI8sgCvpsyEBU82LrrYCfgJtoWLd5JjXMCp8vrHtHzwMSwRQ pHPdEdujWdMidBsByJsMCEqIx5MJq60mv3Wwxf1ri2+oqmPYC7kZpWBicRANEvLx0E60 dp50QgElcCAB1Z8ub2INLLhBPuxR/EIlwwJ6JXREti9DUYDuSjdShmo9NJLfrohwZ3DC br1f78L1n7L3Jlq8wAZykqZOiijZnO5Y+iOUi9w/9wRJ/jZWvYYsCNNL2+UfGhf73Bzv xduGF+s9BO7GG7ZQkJCHo91zpGJPIJ7QKT476GhAxy0LsW7XntBGlUQM8RtaKpmkCYSU uwiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597805; x=1755202605; h=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; bh=6CCwqPAnoUPSp9AFnzO+u9qSxg+vLNhYcEQUdXsIl0A=; b=EDXglbt38mZR47yjmrmFiMK5dRWNjcG7wN+onEiA5hR1Zew/Rx7mSMh3edn3C4nX2i /Vhw67b5YQYjhQEo/0z/TKqLW3SxlC3lrIPdYy9bAScboiATcM3MDqhD3CYpa+1vCIIY c5uWrQWkQPSAvfzFrdvNWf7xV3lNg/nC5ZCqfweCvB0AVV0LxjHgGCGciocmP0Hd5lTp LPfkOXymp4xE9CbZMo0eepYgwR2yiE3N2p5JZyNS0YMt5Uw49k+NtMA3ldMJOdKcra+C Agenj4ct2CBy/wnkufUCuNW/39ETmeD2y04iT7db6R6Opdxi7ANTKpoV/Elr2XSEYGWu rEdQ== X-Gm-Message-State: AOJu0YwvtjjSdpXabgL8nJ5WBrIMGFT0h9TxXcRSgGCsCbgvVxArJH/R tSfi6dnK9OPKYzHl3faiTMmbzgYy4QOtArQAJNKAT5TrUqpy9Byth/1uJICr0mGqkDmZwBpbha8 00g== X-Google-Smtp-Source: AGHT+IFrTj53N5DZXacA6l1rqtKAvbn+AVo773jcURpzGEwI4lTM8ssPebkro7Dg+daTfE66YB9jLp4D9w== X-Received: from pjpo16.prod.google.com ([2002:a17:90a:9f90:b0:311:ff32:a85d]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:1fc3:b0:31f:1757:f9f8 with SMTP id 98e67ed59e1d1-32183b3f0d7mr395879a91.22.1754597804855; Thu, 07 Aug 2025 13:16:44 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:01 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-6-sagis@google.com> Subject: [PATCH v8 05/30] KVM: selftests: Update kvm_init_vm_address_properties() for TDX From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Adrian Hunter Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Isaku Yamahata Let kvm_init_vm_address_properties() initialize vm->arch.{s_bit, tag_mask} similar to SEV. Set shared bit position based on guest maximum physical address width instead of maximum physical address width, because that is what KVM uses, refer to setup_tdparams_eptp_controls(), and because maximum physical address width can be different. In the case of SRF, guest maximum physical address width is 48 because SRF does not support 5-level EPT, even though the maximum physical address width is 52. Co-developed-by: Adrian Hunter Signed-off-by: Adrian Hunter Signed-off-by: Isaku Yamahata Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/lib/x86/processor.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index d082d429e127..5718b5911b0a 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -1166,10 +1166,19 @@ void kvm_get_cpu_address_width(unsigned int *pa_bit= s, unsigned int *va_bits) =20 void kvm_init_vm_address_properties(struct kvm_vm *vm) { + uint32_t gpa_bits =3D kvm_cpu_property(X86_PROPERTY_GUEST_MAX_PHY_ADDR); + if (is_sev_vm(vm)) { vm->arch.sev_fd =3D open_sev_dev_path_or_exit(); vm->arch.c_bit =3D BIT_ULL(this_cpu_property(X86_PROPERTY_SEV_C_BIT)); vm->gpa_tag_mask =3D vm->arch.c_bit; + } else if (vm->type =3D=3D KVM_X86_TDX_VM) { + TEST_ASSERT(gpa_bits =3D=3D 48 || gpa_bits =3D=3D 52, + "TDX: bad X86_PROPERTY_GUEST_MAX_PHY_ADDR value: %u", gpa_bits); + vm->arch.sev_fd =3D -1; + vm->arch.s_bit =3D 1ULL << (gpa_bits - 1); + vm->arch.c_bit =3D 0; + vm->gpa_tag_mask =3D vm->arch.s_bit; } else { vm->arch.sev_fd =3D -1; } --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 EBD162367C4 for ; Thu, 7 Aug 2025 20:16:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597810; cv=none; b=p3dDcUBMYVarI9phL7SccCSnsrnJy7Ob98WvLQMcE9mfE6j8HHm0zhj/S9tXOgEI/4AaaQInOzOWFK0G8TYz4bhP+dkkVtX1nLdLYI/sO7xGfnURi0wfjmYCE6sb5dYk1k2crjhxw7CzOtClnoN1B6A5reBuHCJUZEgP9dwMpXA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597810; c=relaxed/simple; bh=BD12gaU3dxtScvZAPVTCtwL954h3gic93joSGaG9vLE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ZYGE3XjvY6w1CVYzbnu6E6v/FLX3wzc8GMWazkLoW+xAhyeh3dRv/LuEgAIgx2vuPcHvgZHcM0U2P3o3vVUyUni5i5zDO6uLNT37sDACvKpw2JP00Sy1dl2gYUgQHVwfA/W/BxaJTxT4f+lnMdfaPKcztKMMznBVCi59weFI16Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=FvYzb3Eu; arc=none smtp.client-ip=209.85.216.73 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="FvYzb3Eu" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-31edd69d754so1401260a91.1 for ; Thu, 07 Aug 2025 13:16:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597806; x=1755202606; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=MH/b6p9+tJZ055brc6aLdIAK/iqjGk6quu9IB5zELKs=; b=FvYzb3EuKrDHTGgixMi2W7sQS+5QFn9VhmlJeGtnhrbjAYyJMXnQ/VHqsrB7p2Nxnd RpUS/TbqsFxX+XaIyBwBlaA/lcHLDnzpKamBWlEwEO8xllquwak/QXfgekEZWgzTiT2v l2XMem71kzzqv0sbyH5zpONa6Z9uk13rTKvPPGjBScwE6q++gfA23D0/B1sfTT6zLXW6 SFaEPtpiY6baIGcDOdP4rp1aSTdgUAhXBzB4wmJ+7ISluu5Z8JBtkF5HUk/epRsxxTTa ZdcLc+xSgQRCCKBfNxuoCtN6jus9z34lnZFWDnNEGWOdr/ap+HwyFdXpHbwDkmvykWZC fBAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597806; x=1755202606; h=content-transfer-encoding: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; bh=MH/b6p9+tJZ055brc6aLdIAK/iqjGk6quu9IB5zELKs=; b=N0UfM97HGwQ6J/gdgmVRqHgYIDmNPZCX2ehrw8NGWuQ2xVDg2MDFWvPs2BUlmnFW3w KoJVScjXFdSYUkPj/5HVZ/Gi/6ZfZqaWFtw7dxmlPg/tcoh3biMAJLmxqtviT9DAZWNj QYjMwkdAcOQWV5RmKPnbW8ackFaH7Zmpvhxpb1exK0bbGqHCk8oM1XdhGOL2Sb52AXtF ytrx7TVPLhhQbHPxFCwig1enUC9XBHqmZU9OC4A5Wub/YA790lZNjZs70N76cj2mhueN tr4x6Bssxf8uaZisvLNPUN9w/ZUOvwjpA1JqDSNAA+WkzH0PiZ65RJA+v/maJof+p8jz CWgA== X-Gm-Message-State: AOJu0YzWCJ7V0FkL4r4+pgjnzrS+4s0QZhkh147hRPlnm3E6/HATOWCy xMr0PbNhafXxHmkm3S9c04NFlHDDJHxrFfBav3n9OjnwsfiPYZGDdAd/wI6FWHG/NWPUAgc8loh R8Q== X-Google-Smtp-Source: AGHT+IHwJ0/Y+cIBn1GMiKfMvO5BnzBjMbCEQfYfExT/C4ZAOncWhryPXk/1cb/zqKYqXZ98kB/G2DbLSQ== X-Received: from pjzd8.prod.google.com ([2002:a17:90a:e288:b0:311:f309:e314]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90a:dfc4:b0:312:1c83:58e9 with SMTP id 98e67ed59e1d1-321839e9fedmr483906a91.5.1754597806352; Thu, 07 Aug 2025 13:16:46 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:02 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-7-sagis@google.com> Subject: [PATCH v8 06/30] KVM: selftests: Add helper functions to create TDX VMs From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Erdem Aktas TDX requires additional IOCTLs to initialize VM and vCPUs to add private memory and to finalize the VM memory. Also additional utility functions are provided to manipulate a TD, similar to those that manipulate a VM in the current selftest framework. A TD's initial register state cannot be manipulated directly by setting the VM's memory, hence boot code is provided at the TD's reset vector. This boot code takes boot parameters loaded in the TD's memory and sets up the TD for the selftest. Userspace needs to ensure consistency between KVM's CPUID and the TDX Module's view. Obtain the CPUID supported by KVM and make adjustments to reflect features of interest and the limited KVM PV features supported for TD guest. This involves masking the feature bits from CPUID entries and filtering CPUID entries of features not supported by TDX before initializing the TD. Suggested-by: Isaku Yamahata Co-developed-by: Sagi Shahar Signed-off-by: Sagi Shahar Co-developed-by: Ackerley Tng Signed-off-by: Ackerley Tng Co-developed-by: Isaku Yamahata Signed-off-by: Isaku Yamahata Co-developed-by: Rick Edgecombe Signed-off-by: Rick Edgecombe Signed-off-by: Erdem Aktas Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/Makefile.kvm | 2 + .../testing/selftests/kvm/include/kvm_util.h | 6 + .../selftests/kvm/include/x86/kvm_util_arch.h | 1 + .../selftests/kvm/include/x86/tdx/td_boot.h | 83 +++ .../kvm/include/x86/tdx/td_boot_asm.h | 16 + .../selftests/kvm/include/x86/tdx/tdx_util.h | 19 + tools/testing/selftests/kvm/lib/kvm_util.c | 6 +- .../testing/selftests/kvm/lib/x86/processor.c | 19 +- .../selftests/kvm/lib/x86/tdx/td_boot.S | 100 ++++ .../selftests/kvm/lib/x86/tdx/tdx_util.c | 566 ++++++++++++++++++ 10 files changed, 807 insertions(+), 11 deletions(-) create mode 100644 tools/testing/selftests/kvm/include/x86/tdx/td_boot.h create mode 100644 tools/testing/selftests/kvm/include/x86/tdx/td_boot_asm= .h create mode 100644 tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h create mode 100644 tools/testing/selftests/kvm/lib/x86/tdx/td_boot.S create mode 100644 tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 38b95998e1e6..b429c92e07d8 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -29,6 +29,8 @@ LIBKVM_x86 +=3D lib/x86/sev.c LIBKVM_x86 +=3D lib/x86/svm.c LIBKVM_x86 +=3D lib/x86/ucall.c LIBKVM_x86 +=3D lib/x86/vmx.c +LIBKVM_x86 +=3D lib/x86/tdx/tdx_util.c +LIBKVM_x86 +=3D lib/x86/tdx/td_boot.S =20 LIBKVM_arm64 +=3D lib/arm64/gic.c LIBKVM_arm64 +=3D lib/arm64/gic_v3.c diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index 5c4ca25803ac..0d1f24c9f7c7 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -79,6 +79,7 @@ enum kvm_mem_region_type { MEM_REGION_DATA, MEM_REGION_PT, MEM_REGION_TEST_DATA, + MEM_REGION_TDX_BOOT_PARAMS, NR_MEM_REGIONS, }; =20 @@ -1026,6 +1027,9 @@ unsigned long vm_compute_max_gfn(struct kvm_vm *vm); unsigned int vm_calc_num_guest_pages(enum vm_guest_mode mode, size_t size); unsigned int vm_num_host_pages(enum vm_guest_mode mode, unsigned int num_g= uest_pages); unsigned int vm_num_guest_pages(enum vm_guest_mode mode, unsigned int num_= host_pages); +uint64_t vm_nr_pages_required(enum vm_guest_mode mode, + uint32_t nr_runnable_vcpus, + uint64_t extra_mem_pages); static inline unsigned int vm_adjust_num_guest_pages(enum vm_guest_mode mode, unsigned int num_guest_= pages) { @@ -1191,6 +1195,8 @@ static inline int __vm_disable_nx_huge_pages(struct k= vm_vm *vm) */ void kvm_selftest_arch_init(void); =20 +void vm_init_descriptor_tables(struct kvm_vm *vm); + void kvm_arch_vm_post_create(struct kvm_vm *vm); =20 bool vm_is_gpa_protected(struct kvm_vm *vm, vm_paddr_t paddr); diff --git a/tools/testing/selftests/kvm/include/x86/kvm_util_arch.h b/tool= s/testing/selftests/kvm/include/x86/kvm_util_arch.h index 972bb1c4ab4c..80db1e4c38ba 100644 --- a/tools/testing/selftests/kvm/include/x86/kvm_util_arch.h +++ b/tools/testing/selftests/kvm/include/x86/kvm_util_arch.h @@ -19,6 +19,7 @@ struct kvm_vm_arch { uint64_t s_bit; int sev_fd; bool is_pt_protected; + bool has_protected_regs; }; =20 static inline bool __vm_arch_has_protected_memory(struct kvm_vm_arch *arch) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/td_boot.h b/tools/= testing/selftests/kvm/include/x86/tdx/td_boot.h new file mode 100644 index 000000000000..94a50295f953 --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86/tdx/td_boot.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_TDX_TD_BOOT_H +#define SELFTEST_TDX_TD_BOOT_H + +#include + +#include "tdx/td_boot_asm.h" + +/* + * Layout for boot section (not to scale) + * + * GPA + * _________________________________ 0x1_0000_0000 (4GB) + * | Boot code trampoline | + * |___________________________|____ 0x0_ffff_fff0: Reset vector (16B belo= w 4GB) + * | Boot code | + * |___________________________|____ td_boot will be copied here, so that = the + * | | jmp to td_boot is exactly at the rese= t vector + * | Empty space | + * | | + * |=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80| + * | | + * | | + * | Boot parameters | + * | | + * | | + * |___________________________|____ 0x0_ffff_0000: TD_BOOT_PARAMETERS_GPA + */ +#define FOUR_GIGABYTES_GPA (4ULL << 30) + +/* + * The exact memory layout for LGDT or LIDT instructions. + */ +struct __packed td_boot_parameters_dtr { + uint16_t limit; + uint32_t base; +}; + +/* + * The exact layout in memory required for a ljmp, including the selector = for + * changing code segment. + */ +struct __packed td_boot_parameters_ljmp_target { + uint32_t eip_gva; + uint16_t code64_sel; +}; + +/* + * Allows each vCPU to be initialized with different eip and esp. + */ +struct __packed td_per_vcpu_parameters { + uint32_t esp_gva; + struct td_boot_parameters_ljmp_target ljmp_target; +}; + +/* + * Boot parameters for the TD. + * + * Unlike a regular VM, KVM cannot set registers such as esp, eip, etc + * before boot, so to run selftests, these registers' values have to be + * initialized by the TD. + * + * This struct is loaded in TD private memory at TD_BOOT_PARAMETERS_GPA. + * + * The TD boot code will read off parameters from this struct and set up t= he + * vCPU for executing selftests. + */ +struct __packed td_boot_parameters { + uint32_t cr0; + uint32_t cr3; + uint32_t cr4; + struct td_boot_parameters_dtr gdtr; + struct td_boot_parameters_dtr idtr; + struct td_per_vcpu_parameters per_vcpu[]; +}; + +void td_boot(void); +void reset_vector(void); +void td_boot_code_end(void); + +#define TD_BOOT_CODE_SIZE (td_boot_code_end - td_boot) + +#endif /* SELFTEST_TDX_TD_BOOT_H */ diff --git a/tools/testing/selftests/kvm/include/x86/tdx/td_boot_asm.h b/to= ols/testing/selftests/kvm/include/x86/tdx/td_boot_asm.h new file mode 100644 index 000000000000..10b4b527595c --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86/tdx/td_boot_asm.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_TDX_TD_BOOT_ASM_H +#define SELFTEST_TDX_TD_BOOT_ASM_H + +/* + * GPA where TD boot parameters will be loaded. + * + * TD_BOOT_PARAMETERS_GPA is arbitrarily chosen to + * + * + be within the 4GB address space + * + provide enough contiguous memory for the struct td_boot_parameters su= ch + * that there is one struct td_per_vcpu_parameters for KVM_MAX_VCPUS + */ +#define TD_BOOT_PARAMETERS_GPA 0xffff0000 + +#endif // SELFTEST_TDX_TD_BOOT_ASM_H diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h b/tools= /testing/selftests/kvm/include/x86/tdx/tdx_util.h new file mode 100644 index 000000000000..57a2f5893ffe --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTESTS_TDX_KVM_UTIL_H +#define SELFTESTS_TDX_KVM_UTIL_H + +#include + +#include "kvm_util.h" + +void tdx_filter_cpuid(struct kvm_vm *vm, struct kvm_cpuid2 *cpuid_data); +void __tdx_mask_cpuid_features(struct kvm_cpuid_entry2 *entry); + +struct kvm_vcpu *td_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id, void *gu= est_code); + +struct kvm_vm *td_create(void); +void td_initialize(struct kvm_vm *vm, enum vm_mem_backing_src_type src_typ= e, + uint64_t attributes); +void td_finalize(struct kvm_vm *vm); + +#endif // SELFTESTS_TDX_KVM_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 8f3dbf749afa..f7e00ea0b211 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -376,9 +376,9 @@ struct kvm_vm *____vm_create(struct vm_shape shape) return vm; } =20 -static uint64_t vm_nr_pages_required(enum vm_guest_mode mode, - uint32_t nr_runnable_vcpus, - uint64_t extra_mem_pages) +uint64_t vm_nr_pages_required(enum vm_guest_mode mode, + uint32_t nr_runnable_vcpus, + uint64_t extra_mem_pages) { uint64_t page_size =3D vm_guest_mode_params[mode].page_size; uint64_t nr_pages; diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index 5718b5911b0a..3977719c7893 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -590,7 +590,7 @@ void sync_exception_handlers_to_guest(struct kvm_vm *vm) *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) =3D vm= ->handlers; } =20 -static void vm_init_descriptor_tables(struct kvm_vm *vm) +void vm_init_descriptor_tables(struct kvm_vm *vm) { extern void *idt_handlers; struct kvm_segment seg; @@ -696,16 +696,19 @@ struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, = uint32_t vcpu_id) =20 vcpu =3D __vm_vcpu_add(vm, vcpu_id); vcpu_init_cpuid(vcpu, kvm_get_supported_cpuid()); - vcpu_init_sregs(vm, vcpu); - vcpu_init_xcrs(vm, vcpu); =20 vcpu->initial_stack_addr =3D stack_vaddr; =20 - /* Setup guest general purpose registers */ - vcpu_regs_get(vcpu, ®s); - regs.rflags =3D regs.rflags | 0x2; - regs.rsp =3D stack_vaddr; - vcpu_regs_set(vcpu, ®s); + if (!vm->arch.has_protected_regs) { + vcpu_init_sregs(vm, vcpu); + vcpu_init_xcrs(vm, vcpu); + + /* Setup guest general purpose registers */ + vcpu_regs_get(vcpu, ®s); + regs.rflags =3D regs.rflags | 0x2; + regs.rsp =3D stack_vaddr; + vcpu_regs_set(vcpu, ®s); + } =20 /* Setup the MP state */ mp_state.mp_state =3D 0; diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/td_boot.S b/tools/test= ing/selftests/kvm/lib/x86/tdx/td_boot.S new file mode 100644 index 000000000000..c8cbe214bba9 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86/tdx/td_boot.S @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "tdx/td_boot_asm.h" + +/* Offsets for reading struct td_boot_parameters. */ +#define TD_BOOT_PARAMETERS_CR0 0 +#define TD_BOOT_PARAMETERS_CR3 4 +#define TD_BOOT_PARAMETERS_CR4 8 +#define TD_BOOT_PARAMETERS_GDT 12 +#define TD_BOOT_PARAMETERS_IDT 18 +#define TD_BOOT_PARAMETERS_PER_VCPU 24 + +/* Offsets for reading struct td_per_vcpu_parameters. */ +#define TD_PER_VCPU_PARAMETERS_ESP_GVA 0 +#define TD_PER_VCPU_PARAMETERS_LJMP_TARGET 4 + +#define SIZEOF_TD_PER_VCPU_PARAMETERS 10 + +.code32 + +.globl td_boot +td_boot: + /* In this procedure, edi is used as a temporary register. */ + cli + + /* Paging is off. */ + + movl $TD_BOOT_PARAMETERS_GPA, %ebx + + /* + * Find the address of struct td_per_vcpu_parameters for this + * vCPU based on esi (TDX spec: initialized with vCPU id). Put + * struct address into register for indirect addressing. + */ + movl $SIZEOF_TD_PER_VCPU_PARAMETERS, %eax + mul %esi + leal TD_BOOT_PARAMETERS_PER_VCPU(%ebx), %edi + addl %edi, %eax + + /* Setup stack. */ + movl TD_PER_VCPU_PARAMETERS_ESP_GVA(%eax), %esp + + /* Setup GDT. */ + leal TD_BOOT_PARAMETERS_GDT(%ebx), %edi + lgdt (%edi) + + /* Setup IDT. */ + leal TD_BOOT_PARAMETERS_IDT(%ebx), %edi + lidt (%edi) + + /* + * Set up control registers (There are no instructions to mov from + * memory to control registers, hence use ebx as a scratch register). + */ + movl TD_BOOT_PARAMETERS_CR4(%ebx), %edi + movl %edi, %cr4 + movl TD_BOOT_PARAMETERS_CR3(%ebx), %edi + movl %edi, %cr3 + movl TD_BOOT_PARAMETERS_CR0(%ebx), %edi + movl %edi, %cr0 + + /* Paging is on after setting the most significant bit on cr0. */ + + /* + * Jump to selftest guest code. Far jumps read from . This location has + * already been set up in boot parameters, and boot parameters can + * be read because boot code and boot parameters are loaded so + * that GVA and GPA are mapped 1:1. + */ + ljmp *TD_PER_VCPU_PARAMETERS_LJMP_TARGET(%eax) + +.globl reset_vector +reset_vector: + jmp td_boot + /* + * Pad reset_vector to its full size of 16 bytes so that this + * can be loaded with the end of reset_vector aligned to GPA=3D4G. + */ + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + +/* Leave marker so size of td_boot code can be computed. */ +.globl td_boot_code_end +td_boot_code_end: + +/* Disable executable stack. */ +.section .note.GNU-stack,"",%progbits diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/tes= ting/selftests/kvm/lib/x86/tdx/tdx_util.c new file mode 100644 index 000000000000..392d6272d17e --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c @@ -0,0 +1,566 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "processor.h" +#include "tdx/td_boot.h" +#include "test_util.h" + +uint64_t tdx_s_bit; + +/* + * TDX ioctls + */ + +static char *tdx_cmd_str[] =3D { + "KVM_TDX_CAPABILITIES", + "KVM_TDX_INIT_VM", + "KVM_TDX_INIT_VCPU", + "KVM_TDX_INIT_MEM_REGION", + "KVM_TDX_FINALIZE_VM", + "KVM_TDX_GET_CPUID" +}; + +#define TDX_MAX_CMD_STR (ARRAY_SIZE(tdx_cmd_str)) + +static int _tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data) +{ + struct kvm_tdx_cmd tdx_cmd; + + TEST_ASSERT(ioctl_no < TDX_MAX_CMD_STR, "Unknown TDX CMD : %d\n", + ioctl_no); + + memset(&tdx_cmd, 0x0, sizeof(tdx_cmd)); + tdx_cmd.id =3D ioctl_no; + tdx_cmd.flags =3D flags; + tdx_cmd.data =3D (uint64_t)data; + + return ioctl(fd, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd); +} + +static void tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data) +{ + int r; + + r =3D _tdx_ioctl(fd, ioctl_no, flags, data); + TEST_ASSERT(r =3D=3D 0, "%s failed: %d %d", tdx_cmd_str[ioctl_no], r, + errno); +} + +static struct kvm_tdx_capabilities *tdx_read_capabilities(struct kvm_vm *v= m) +{ + struct kvm_tdx_capabilities *tdx_cap =3D NULL; + int nr_cpuid_configs =3D 4; + int rc =3D -1; + int i; + + do { + nr_cpuid_configs *=3D 2; + + tdx_cap =3D realloc(tdx_cap, sizeof(*tdx_cap) + + sizeof(tdx_cap->cpuid) + + (sizeof(struct kvm_cpuid_entry2) * nr_cpuid_configs)); + TEST_ASSERT(tdx_cap, + "Could not allocate memory for tdx capability nr_cpuid_configs %d\n= ", + nr_cpuid_configs); + + tdx_cap->cpuid.nent =3D nr_cpuid_configs; + rc =3D _tdx_ioctl(vm->fd, KVM_TDX_CAPABILITIES, 0, tdx_cap); + } while (rc < 0 && errno =3D=3D E2BIG); + + TEST_ASSERT(rc =3D=3D 0, "KVM_TDX_CAPABILITIES failed: %d %d", + rc, errno); + + pr_debug("tdx_cap: supported_attrs: 0x%016llx\n" + "tdx_cap: supported_xfam 0x%016llx\n", + tdx_cap->supported_attrs, tdx_cap->supported_xfam); + + for (i =3D 0; i < tdx_cap->cpuid.nent; i++) { + const struct kvm_cpuid_entry2 *config =3D &tdx_cap->cpuid.entries[i]; + + pr_debug("cpuid config[%d]: leaf 0x%x sub_leaf 0x%x eax 0x%08x ebx 0x%08= x ecx 0x%08x edx 0x%08x\n", + i, config->function, config->index, + config->eax, config->ebx, config->ecx, config->edx); + } + + return tdx_cap; +} + +static struct kvm_cpuid_entry2 *tdx_find_cpuid_config(struct kvm_tdx_capab= ilities *cap, + uint32_t leaf, uint32_t sub_leaf) +{ + struct kvm_cpuid_entry2 *config; + uint32_t i; + + for (i =3D 0; i < cap->cpuid.nent; i++) { + config =3D &cap->cpuid.entries[i]; + + if (config->function =3D=3D leaf && config->index =3D=3D sub_leaf) + return config; + } + + return NULL; +} + +#define XFEATURE_MASK_CET (XFEATURE_MASK_CET_USER | XFEATURE_MASK_CET_KERN= EL) + +static void tdx_apply_cpuid_restrictions(struct kvm_cpuid2 *cpuid_data) +{ + for (int i =3D 0; i < cpuid_data->nent; i++) { + struct kvm_cpuid_entry2 *e =3D &cpuid_data->entries[i]; + + if (e->function =3D=3D 0xd && e->index =3D=3D 0) { + /* + * TDX module requires both XTILE_{CFG, DATA} to be set. + * Both bits are required for AMX to be functional. + */ + if ((e->eax & XFEATURE_MASK_XTILE) !=3D + XFEATURE_MASK_XTILE) { + e->eax &=3D ~XFEATURE_MASK_XTILE; + } + } + if (e->function =3D=3D 0xd && e->index =3D=3D 1) { + /* + * TDX doesn't support LBR yet. + * Disable bits from the XCR0 register. + */ + e->ecx &=3D ~XFEATURE_MASK_LBR; + /* + * TDX modules requires both CET_{U, S} to be set even + * if only one is supported. + */ + if (e->ecx & XFEATURE_MASK_CET) + e->ecx |=3D XFEATURE_MASK_CET; + } + } +} + +#define KVM_MAX_CPUID_ENTRIES 256 + +#define CPUID_EXT_VMX BIT(5) +#define CPUID_EXT_SMX BIT(6) +#define CPUID_PSE36 BIT(17) +#define CPUID_7_0_EBX_TSC_ADJUST BIT(1) +#define CPUID_7_0_EBX_SGX BIT(2) +#define CPUID_7_0_EBX_INTEL_PT BIT(25) +#define CPUID_7_0_ECX_SGX_LC BIT(30) +#define CPUID_APM_INVTSC BIT(8) +#define CPUID_8000_0008_EBX_WBNOINVD BIT(9) +#define CPUID_EXT_PDCM BIT(15) + +#define TDX_SUPPORTED_KVM_FEATURES ((1U << KVM_FEATURE_NOP_IO_DELAY) | \ + (1U << KVM_FEATURE_PV_UNHALT) | \ + (1U << KVM_FEATURE_PV_TLB_FLUSH) | \ + (1U << KVM_FEATURE_PV_SEND_IPI) | \ + (1U << KVM_FEATURE_POLL_CONTROL) | \ + (1U << KVM_FEATURE_PV_SCHED_YIELD) | \ + (1U << KVM_FEATURE_MSI_EXT_DEST_ID)) + +void __tdx_mask_cpuid_features(struct kvm_cpuid_entry2 *entry) +{ + /* + * Only entries with sub-leaf zero need to be masked, but some of these + * leaves have other sub-leaves defined. Bail on any non-zero sub-leaf, + * so they don't get unintentionally modified. + */ + if (entry->index) + return; + + switch (entry->function) { + case 0x1: + entry->ecx &=3D ~(CPUID_EXT_VMX | CPUID_EXT_SMX); + entry->edx &=3D ~CPUID_PSE36; + break; + case 0x7: + entry->ebx &=3D ~(CPUID_7_0_EBX_TSC_ADJUST | CPUID_7_0_EBX_SGX); + entry->ebx &=3D ~CPUID_7_0_EBX_INTEL_PT; + entry->ecx &=3D ~CPUID_7_0_ECX_SGX_LC; + break; + case 0x40000001: + entry->eax &=3D TDX_SUPPORTED_KVM_FEATURES; + break; + case 0x80000007: + entry->edx |=3D CPUID_APM_INVTSC; + break; + case 0x80000008: + entry->ebx &=3D CPUID_8000_0008_EBX_WBNOINVD; + break; + default: + break; + } +} + +static void tdx_mask_cpuid_features(struct kvm_cpuid2 *cpuid_data) +{ + for (int i =3D 0; i < cpuid_data->nent; i++) + __tdx_mask_cpuid_features(&cpuid_data->entries[i]); +} + +void tdx_filter_cpuid(struct kvm_vm *vm, struct kvm_cpuid2 *cpuid_data) +{ + struct kvm_tdx_capabilities *tdx_cap; + struct kvm_cpuid_entry2 *config; + struct kvm_cpuid_entry2 *e; + int i; + + tdx_cap =3D tdx_read_capabilities(vm); + + i =3D 0; + while (i < cpuid_data->nent) { + e =3D cpuid_data->entries + i; + config =3D tdx_find_cpuid_config(tdx_cap, e->function, e->index); + + if (!config) { + int left =3D cpuid_data->nent - i - 1; + + if (left > 0) + memmove(cpuid_data->entries + i, + cpuid_data->entries + i + 1, + sizeof(*cpuid_data->entries) * left); + cpuid_data->nent--; + continue; + } + + e->eax &=3D config->eax; + e->ebx &=3D config->ebx; + e->ecx &=3D config->ecx; + e->edx &=3D config->edx; + + i++; + } + + free(tdx_cap); +} + +static void tdx_td_init(struct kvm_vm *vm, uint64_t attributes) +{ + struct kvm_tdx_init_vm *init_vm; + const struct kvm_cpuid2 *tmp; + struct kvm_cpuid2 *cpuid; + + tmp =3D kvm_get_supported_cpuid(); + + cpuid =3D allocate_kvm_cpuid2(KVM_MAX_CPUID_ENTRIES); + memcpy(cpuid, tmp, kvm_cpuid2_size(tmp->nent)); + tdx_mask_cpuid_features(cpuid); + + init_vm =3D calloc(1, sizeof(*init_vm) + + sizeof(init_vm->cpuid.entries[0]) * cpuid->nent); + TEST_ASSERT(init_vm, "vm allocation failed"); + + memcpy(&init_vm->cpuid, cpuid, kvm_cpuid2_size(cpuid->nent)); + free(cpuid); + + init_vm->attributes =3D attributes; + + tdx_apply_cpuid_restrictions(&init_vm->cpuid); + tdx_filter_cpuid(vm, &init_vm->cpuid); + + tdx_ioctl(vm->fd, KVM_TDX_INIT_VM, 0, init_vm); + free(init_vm); +} + +static void tdx_td_vcpu_init(struct kvm_vcpu *vcpu) +{ + struct kvm_cpuid2 *cpuid; + + cpuid =3D allocate_kvm_cpuid2(KVM_MAX_CPUID_ENTRIES); + tdx_ioctl(vcpu->fd, KVM_TDX_GET_CPUID, 0, cpuid); + vcpu_init_cpuid(vcpu, cpuid); + free(cpuid); + tdx_ioctl(vcpu->fd, KVM_TDX_INIT_VCPU, 0, NULL); + /* + * Refresh CPUID to get KVM's "runtime" updates which are done by + * KVM_TDX_INIT_VCPU. + */ + vcpu_get_cpuid(vcpu); +} + +static void tdx_init_mem_region(struct kvm_vm *vm, void *source_pages, + uint64_t gpa, uint64_t size) +{ + uint32_t metadata =3D KVM_TDX_MEASURE_MEMORY_REGION; + struct kvm_tdx_init_mem_region mem_region =3D { + .source_addr =3D (uint64_t)source_pages, + .gpa =3D gpa, + .nr_pages =3D size / PAGE_SIZE, + }; + struct kvm_vcpu *vcpu; + + vcpu =3D list_first_entry_or_null(&vm->vcpus, struct kvm_vcpu, list); + + TEST_ASSERT((mem_region.nr_pages > 0) && + ((mem_region.nr_pages * PAGE_SIZE) =3D=3D size), + "Cannot add partial pages to the guest memory.\n"); + TEST_ASSERT(((uint64_t)source_pages & (PAGE_SIZE - 1)) =3D=3D 0, + "Source memory buffer is not page aligned\n"); + tdx_ioctl(vcpu->fd, KVM_TDX_INIT_MEM_REGION, metadata, &mem_region); +} + +static void tdx_td_finalize_mr(struct kvm_vm *vm) +{ + tdx_ioctl(vm->fd, KVM_TDX_FINALIZE_VM, 0, NULL); +} + +/* + * TD creation/setup/finalization + */ + +static void tdx_enable_capabilities(struct kvm_vm *vm) +{ + int rc; + + rc =3D kvm_check_cap(KVM_CAP_X2APIC_API); + TEST_ASSERT(rc, "TDX: KVM_CAP_X2APIC_API is not supported!"); + rc =3D kvm_check_cap(KVM_CAP_SPLIT_IRQCHIP); + TEST_ASSERT(rc, "TDX: KVM_CAP_SPLIT_IRQCHIP is not supported!"); + + vm_enable_cap(vm, KVM_CAP_X2APIC_API, + KVM_X2APIC_API_USE_32BIT_IDS | + KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK); + vm_enable_cap(vm, KVM_CAP_SPLIT_IRQCHIP, 24); +} + +static void tdx_apply_cr4_restrictions(struct kvm_sregs *sregs) +{ + /* TDX spec 11.6.2: CR4 bit MCE is fixed to 1 */ + sregs->cr4 |=3D X86_CR4_MCE; + + /* Set this because UEFI also sets this up, to handle XMM exceptions */ + sregs->cr4 |=3D X86_CR4_OSXMMEXCPT; + + /* TDX spec 11.6.2: CR4 bit VMXE and SMXE are fixed to 0 */ + sregs->cr4 &=3D ~(X86_CR4_VMXE | X86_CR4_SMXE); +} + +static void load_td_boot_code(struct kvm_vm *vm) +{ + void *boot_code_hva =3D addr_gpa2hva(vm, FOUR_GIGABYTES_GPA - TD_BOOT_COD= E_SIZE); + + TEST_ASSERT(td_boot_code_end - reset_vector =3D=3D 16, + "The reset vector must be 16 bytes in size."); + memcpy(boot_code_hva, td_boot, TD_BOOT_CODE_SIZE); +} + +static void load_td_per_vcpu_parameters(struct td_boot_parameters *params, + struct kvm_sregs *sregs, + struct kvm_vcpu *vcpu, + void *guest_code) +{ + struct td_per_vcpu_parameters *vcpu_params =3D ¶ms->per_vcpu[vcpu->id= ]; + + TEST_ASSERT(vcpu->initial_stack_addr !=3D 0, + "initial stack address should not be 0"); + TEST_ASSERT(vcpu->initial_stack_addr <=3D 0xffffffff, + "initial stack address must fit in 32 bits"); + TEST_ASSERT((uint64_t)guest_code <=3D 0xffffffff, + "guest_code must fit in 32 bits"); + TEST_ASSERT(sregs->cs.selector !=3D 0, "cs.selector should not be 0"); + + vcpu_params->esp_gva =3D (uint32_t)(uint64_t)vcpu->initial_stack_addr; + vcpu_params->ljmp_target.eip_gva =3D (uint32_t)(uint64_t)guest_code; + vcpu_params->ljmp_target.code64_sel =3D sregs->cs.selector; +} + +static void load_td_common_parameters(struct td_boot_parameters *params, + struct kvm_sregs *sregs) +{ + /* Set parameters! */ + params->cr0 =3D sregs->cr0; + params->cr3 =3D sregs->cr3; + params->cr4 =3D sregs->cr4; + params->gdtr.limit =3D sregs->gdt.limit; + params->gdtr.base =3D sregs->gdt.base; + params->idtr.limit =3D sregs->idt.limit; + params->idtr.base =3D sregs->idt.base; + + TEST_ASSERT(params->cr0 !=3D 0, "cr0 should not be 0"); + TEST_ASSERT(params->cr3 !=3D 0, "cr3 should not be 0"); + TEST_ASSERT(params->cr4 !=3D 0, "cr4 should not be 0"); + TEST_ASSERT(params->gdtr.base !=3D 0, "gdt base address should not be 0"); + TEST_ASSERT(params->idtr.base !=3D 0, "idt base address should not be 0"); +} + +static void load_td_boot_parameters(struct td_boot_parameters *params, + struct kvm_vcpu *vcpu, void *guest_code) +{ + struct kvm_sregs sregs; + + /* Assemble parameters in sregs */ + memset(&sregs, 0, sizeof(struct kvm_sregs)); + vcpu_setup_mode_sregs(vcpu->vm, &sregs); + tdx_apply_cr4_restrictions(&sregs); + + if (!params->cr0) + load_td_common_parameters(params, &sregs); + + load_td_per_vcpu_parameters(params, &sregs, vcpu, guest_code); +} + +/* + * Adds a vCPU to a TD (Trusted Domain) with minimum defaults. It will not= set + * up any general purpose registers as they will be initialized by the TDX= . In + * TDX, vCPUs RIP is set to 0xFFFFFFF0. See Intel TDX EAS Section "Initial= State + * of Guest GPRs" for more information on vCPUs initial register values wh= en + * entering the TD first time. + * + * Input Args: + * vm - Virtual Machine + * vcpuid - The id of the vCPU to add to the VM. + */ +struct kvm_vcpu *td_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id, void *gu= est_code) +{ + struct kvm_vcpu *vcpu; + + vm->arch.has_protected_regs =3D true; + vcpu =3D vm_arch_vcpu_add(vm, vcpu_id); + + tdx_td_vcpu_init(vcpu); + + load_td_boot_parameters(addr_gpa2hva(vm, TD_BOOT_PARAMETERS_GPA), + vcpu, guest_code); + + return vcpu; +} + +static void load_td_memory_region(struct kvm_vm *vm, + struct userspace_mem_region *region) +{ + const struct sparsebit *pages =3D region->protected_phy_pages; + const vm_paddr_t gpa_base =3D region->region.guest_phys_addr; + const uint64_t hva_base =3D region->region.userspace_addr; + const sparsebit_idx_t lowest_page_in_region =3D gpa_base >> vm->page_shif= t; + + sparsebit_idx_t i; + sparsebit_idx_t j; + + if (!sparsebit_any_set(pages)) + return; + + sparsebit_for_each_set_range(pages, i, j) { + const uint64_t size_to_load =3D (j - i + 1) * vm->page_size; + const uint64_t offset =3D + (i - lowest_page_in_region) * vm->page_size; + const uint64_t hva =3D hva_base + offset; + const uint64_t gpa =3D gpa_base + offset; + void *source_addr; + + /* + * KVM_TDX_INIT_MEM_REGION ioctl cannot encrypt memory in place. + * Make a copy if there's only one backing memory source. + */ + source_addr =3D mmap(NULL, size_to_load, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + TEST_ASSERT(source_addr, + "Could not allocate memory for loading memory region"); + + memcpy(source_addr, (void *)hva, size_to_load); + + tdx_init_mem_region(vm, source_addr, gpa, size_to_load); + + munmap(source_addr, size_to_load); + } +} + +static void load_td_private_memory(struct kvm_vm *vm) +{ + struct userspace_mem_region *region; + int ctr; + + hash_for_each(vm->regions.slot_hash, ctr, region, slot_node) { + load_td_memory_region(vm, region); + } +} + +struct kvm_vm *td_create(void) +{ + const struct vm_shape shape =3D { + .mode =3D VM_MODE_DEFAULT, + .type =3D KVM_X86_TDX_VM, + }; + + return ____vm_create(shape); +} + +static void td_setup_boot_code(struct kvm_vm *vm, enum vm_mem_backing_src_= type src_type) +{ + size_t boot_code_allocation =3D round_up(TD_BOOT_CODE_SIZE, PAGE_SIZE); + vm_paddr_t boot_code_base_gpa =3D FOUR_GIGABYTES_GPA - boot_code_allocati= on; + size_t npages =3D DIV_ROUND_UP(boot_code_allocation, PAGE_SIZE); + vm_vaddr_t addr; + + vm_userspace_mem_region_add(vm, src_type, boot_code_base_gpa, 1, npages, + KVM_MEM_GUEST_MEMFD); + vm->memslots[MEM_REGION_CODE] =3D 1; + addr =3D vm_vaddr_identity_alloc(vm, boot_code_allocation, + boot_code_base_gpa, MEM_REGION_CODE); + TEST_ASSERT_EQ(addr, boot_code_base_gpa); + + load_td_boot_code(vm); +} + +static size_t td_boot_parameters_size(void) +{ + int max_vcpus =3D kvm_check_cap(KVM_CAP_MAX_VCPUS); + size_t total_per_vcpu_parameters_size =3D + max_vcpus * sizeof(struct td_per_vcpu_parameters); + + return sizeof(struct td_boot_parameters) + total_per_vcpu_parameters_size; +} + +static void td_setup_boot_parameters(struct kvm_vm *vm, enum vm_mem_backin= g_src_type src_type) +{ + size_t boot_params_size =3D td_boot_parameters_size(); + int npages =3D DIV_ROUND_UP(boot_params_size, PAGE_SIZE); + size_t total_size =3D npages * PAGE_SIZE; + vm_vaddr_t addr; + + vm_userspace_mem_region_add(vm, src_type, TD_BOOT_PARAMETERS_GPA, 2, + npages, KVM_MEM_GUEST_MEMFD); + vm->memslots[MEM_REGION_TDX_BOOT_PARAMS] =3D 2; + addr =3D vm_vaddr_identity_alloc(vm, total_size, TD_BOOT_PARAMETERS_GPA, + MEM_REGION_TDX_BOOT_PARAMS); + TEST_ASSERT_EQ(addr, TD_BOOT_PARAMETERS_GPA); +} + +void td_initialize(struct kvm_vm *vm, enum vm_mem_backing_src_type src_typ= e, + uint64_t attributes) +{ + uint64_t nr_pages_required; + + tdx_enable_capabilities(vm); + + tdx_td_init(vm, attributes); + + nr_pages_required =3D vm_nr_pages_required(VM_MODE_DEFAULT, 1, 0); + + /* + * Add memory (add 0th memslot) for TD. This will be used to setup the + * CPU (provide stack space for the CPU) and to load the elf file. + */ + vm_userspace_mem_region_add(vm, src_type, 0, 0, nr_pages_required, + KVM_MEM_GUEST_MEMFD); + + kvm_vm_elf_load(vm, program_invocation_name); + tdx_s_bit =3D vm->arch.s_bit; + sync_global_to_guest(vm, tdx_s_bit); + + vm_init_descriptor_tables(vm); + + td_setup_boot_code(vm, src_type); + td_setup_boot_parameters(vm, src_type); +} + +void td_finalize(struct kvm_vm *vm) +{ + sync_exception_handlers_to_guest(vm); + + load_td_private_memory(vm); + + tdx_td_finalize_mr(vm); +} --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 876642741C3 for ; Thu, 7 Aug 2025 20:16:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597811; cv=none; b=HisWXjyjx0YZQHcEMbE8QaAhkYwZKL3aAUplGjevPjE5mdOZefT53sxDvyOg2JhjMTLVs4G3NORU1xH+Mg42eiPOfJGWC0kdEo0vBfbgM057xy5G+eHB7bumi2PcQZZLnU0ttH7WT724/gm78aO0o9jBSXNuCe2EfXy3O9KYpK0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597811; c=relaxed/simple; bh=qZKtRz7nLG2KF7a1TIq9CkaKwIyQfE7M1cz+YMT0C3k=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=j/OtrrihLF/F0oxkrDakOpmPtZxWu2LV43ETKgcXJq2sskavYEpf5nGjW3Z+R97UCGWT/Xa/koUTShjSL6e4fiTrscvvsMkWeJm25LjVSgCWLeiN7TplG/cTicdEhtK0KLieeJ0AWyh6tnLO4XQxuKd2FGpzTJbv5bmpEfrx3Wc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ZmFzrer6; arc=none smtp.client-ip=209.85.216.73 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ZmFzrer6" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-31f65d519d3so2850373a91.2 for ; Thu, 07 Aug 2025 13:16:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597808; x=1755202608; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=ok7xE/zvSsxm3sMvm91OXvNKe4HIqd8wijh5DP/BfeQ=; b=ZmFzrer6tnf89eTHTYtDDmcOlwC7JhRsg5azmqe4vedhD8IK8/8xH8c0LpvUyRz2FP Px+K7U0iwI+S6WRFc/QpANy4QUbrsEzv6B7O+0RW+Uq/B5LOH+BHY80oxhwWtlSmi8VU sZKvt8OHddPO7glc0yzKco2t3IyQAsC7/3ZemZ2uWFRc6PXIhXF7NbIKNX+T+7bBtqWL hQkLTWD51D5726zXEfrOPw4wdNlIUX69hH7MeZ9XzUo74n0sPoueRnlLeFtoisDGK/aC 105Z+YEmorV9kn+DuV1+CfrnjJqHc3NcnG7QPhkIDBQeytX6mYePVjUaF2YE26mTXqEQ vsJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597808; x=1755202608; h=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; bh=ok7xE/zvSsxm3sMvm91OXvNKe4HIqd8wijh5DP/BfeQ=; b=aIe3Vf0EvZY8FjMnc5GwmEPZ3pAMM2G4/4gedm0i2Yhd9stmDhRgOS3Iyvfa1encM4 OAlhy7ccZOQqWpfJpukh71dgmYbqgS7oFcijoEOarQjW+cb4wKs0+ocoo+X/oBusn8vH 0VienZR5/HHG1MvdSXy81/uLos/IPNf8zFo/NPHL6kcawtbO3moDa0FMYZ/Z7CZmFIgX ZLanhmoxtvxYBwU6eeJeJY15GzANXz2EpDRuovBXoA/lKGPtx1ddExf+ywxH5IjS+qot 3EM3T1lBvGK/xVJaFk4j4JL0RtsY4NId2Mm7aflDno+cY19cgD+BzOoWgvQKyhmsqpjR FD5w== X-Gm-Message-State: AOJu0Yy+wHOeJ5fopxg7RORb8qRtqIDDrcVaB8Wmblmi4kdvO8wJEtMG nz67gMmjhWPJMr7GOMoD0lSoy37tnOXRsePMcLbUVHtSFRr418CDZu6cL9DMjZZazRHz9+k1mYb mCg== X-Google-Smtp-Source: AGHT+IEOPFXTvjzpu+YcxLn8CBY9Lmh8oefZR6eapvpl0ypNZ8CQQQCwseoJbEg4jHcPbgbjKqwF/k3k4w== X-Received: from pjnx5.prod.google.com ([2002:a17:90a:8a85:b0:31f:335d:342d]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4d89:b0:321:2160:bf76 with SMTP id 98e67ed59e1d1-32183e6d8b9mr392794a91.25.1754597808002; Thu, 07 Aug 2025 13:16:48 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:03 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-8-sagis@google.com> Subject: [PATCH v8 07/30] KVM: selftests: TDX: Use KVM_TDX_CAPABILITIES to validate TDs' attribute configuration From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng This also exercises the KVM_TDX_CAPABILITIES ioctl. Suggested-by: Isaku Yamahata Co-developed-by: Isaku Yamahata Signed-off-by: Isaku Yamahata Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- .../selftests/kvm/lib/x86/tdx/tdx_util.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/tes= ting/selftests/kvm/lib/x86/tdx/tdx_util.c index 392d6272d17e..bb074af4a476 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c @@ -140,6 +140,21 @@ static void tdx_apply_cpuid_restrictions(struct kvm_cp= uid2 *cpuid_data) } } =20 +static void tdx_check_attributes(struct kvm_vm *vm, uint64_t attributes) +{ + struct kvm_tdx_capabilities *tdx_cap; + + tdx_cap =3D tdx_read_capabilities(vm); + + /* TDX spec: any bits 0 in supported_attrs must be 0 in attributes */ + TEST_ASSERT_EQ(attributes & ~tdx_cap->supported_attrs, 0); + + /* TDX spec: any bits 1 in attributes must be 1 in supported_attrs */ + TEST_ASSERT_EQ(attributes & tdx_cap->supported_attrs, attributes); + + free(tdx_cap); +} + #define KVM_MAX_CPUID_ENTRIES 256 =20 #define CPUID_EXT_VMX BIT(5) @@ -256,6 +271,8 @@ static void tdx_td_init(struct kvm_vm *vm, uint64_t att= ributes) memcpy(&init_vm->cpuid, cpuid, kvm_cpuid2_size(cpuid->nent)); free(cpuid); =20 + tdx_check_attributes(vm, attributes); + init_vm->attributes =3D attributes; =20 tdx_apply_cpuid_restrictions(&init_vm->cpuid); --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 1B1C1274B4F for ; Thu, 7 Aug 2025 20:16:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597811; cv=none; b=BIB3IZiIBY3ua9Sqsk6zyv9xBp0/O41AN2zMRBf2WDI2F78XLgMLKUwY/AwjzhAHRdr8u94hYrtFqlBy8b+beQ/eTyqFFx8CjBeR/dY1zdunAWRGBArwZdyC0j8wOLA4nnjOUbJHGCDWBJ/gPhETNqMRYRhzbomhDKSxA0RAAqo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597811; c=relaxed/simple; bh=puYw+DEIdp6ykwAZy5OOEpeoIJJ7PtsStnf4pcAGRJw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=hSf5ZsmDGmVF2TXqKMULIw4gttiV8usPCUAciW8yRg3GXu8Y9FqsNVAsi9QKnorOgvcM/k3NZsnbGVEQ5wj7v5tyPLxOqGnv0To/x9e1rjVMRIBtk6TirA1Q7zm85GsrjoIuGQ6DEmbQ7wjjNcm7Lw52uGsfZ/G4ze85+tFLe60= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ALyL3qfZ; arc=none smtp.client-ip=209.85.216.73 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ALyL3qfZ" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-3211b736a11so2947737a91.0 for ; Thu, 07 Aug 2025 13:16:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597809; x=1755202609; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=US9j6ZWNrs7ioksHVAQpJEm6nvGXIAewRRt1GeZbRi8=; b=ALyL3qfZGKDIBtj1bES14Z9JHq/OB3UIZrlKVTFmgGlfiUbyteknxP3mtmGAPQh5c3 Yif0lWJEmdJlYOOFa4qjnYJBsPW4KF68z9qOMJ55221wKSPNIxOo1eGlx1sXDUR4F+Qz JECzrvg2jzho3AKaMjK3ZPRZ/IcLAqvhb1CMoF9WmUFeqLcKti3HPpTYAL4CCHITNrwv lbQF7F4ty5Y8powt3/4Wwk3r6YuGhr/1DI+iKyQEOShPHzwmtJSfHVJi59guZq6UgQs7 HXMwUkmfSf4boX/lNwmxq8UG5gP3kwyQBlVwjXeUdt5dnXvz2DUTdhVeuV74zfypW08y 4PTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597809; x=1755202609; h=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; bh=US9j6ZWNrs7ioksHVAQpJEm6nvGXIAewRRt1GeZbRi8=; b=B6VlhJTq8ygwQHgih9xhrzRdDJLF16DNwu3AEhQkyDN7JIGcbAr876OWPb99RFP5x0 vJzmEsEhT2XtwP70GhkUdHnWi20J84jrxdGA6E35EnYmybcfqax702fT1GLkCF0gK0yx s5etYF1yhnkZ0lj1mPG7P+mk6RPGOdmYgv8iK9lmiG8FvbKwVzZGIGd7jrcaYshed40B cCdOjdg8k/HGShZBCYlFYWxJddN8+8Zhj9m5eI6hhoZfCGxikBAON/IlhJMtkHFAH6N3 KXox/1+Uy78ZM5UQwwSoHmrh8uPkI8B9C8GtdCl1gIgwVqVHtlpcm4TXLNGsxReUg3J6 hW3A== X-Gm-Message-State: AOJu0YxrgyRHTp6luDFiTunE9iToTUZN/cRImxhA2D8sC+btfX2A0gTF 5Ng4x1oEyp+BRK8FYM5zMOAJ+czWeNykpWJC4LwxsKvjQorOcWIrfW7Duuff7h718utpxznjISP BkA== X-Google-Smtp-Source: AGHT+IFyMZB6DpVtHi3kL/x2IK8tM54yw75AkkxHEHT74p5qROfChvdgkD5MZdZL++lkM7KX+XcCTQn/Ow== X-Received: from pjbns14.prod.google.com ([2002:a17:90b:250e:b0:31e:a865:8b32]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:268b:b0:312:1ae9:152b with SMTP id 98e67ed59e1d1-32183c48d07mr385969a91.23.1754597809647; Thu, 07 Aug 2025 13:16:49 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:04 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-9-sagis@google.com> Subject: [PATCH v8 08/30] KVM: selftests: TDX: Update load_td_memory_region() for VM memory backed by guest memfd From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng If guest memory is backed by restricted memfd + UPM is being used, hence encrypted memory region has to be registered + Can avoid making a copy of guest memory before getting TDX to initialize the memory region Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- .../selftests/kvm/lib/x86/tdx/tdx_util.c | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/tes= ting/selftests/kvm/lib/x86/tdx/tdx_util.c index bb074af4a476..e2bf9766dc03 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c @@ -324,6 +324,21 @@ static void tdx_td_finalize_mr(struct kvm_vm *vm) tdx_ioctl(vm->fd, KVM_TDX_FINALIZE_VM, 0, NULL); } =20 +/* + * Other ioctls + */ + +/* + * Register a memory region that may contain encrypted data in KVM. + */ +static void register_encrypted_memory_region(struct kvm_vm *vm, + struct userspace_mem_region *region) +{ + vm_set_memory_attributes(vm, region->region.guest_phys_addr, + region->region.memory_size, + KVM_MEMORY_ATTRIBUTE_PRIVATE); +} + /* * TD creation/setup/finalization */ @@ -459,28 +474,35 @@ static void load_td_memory_region(struct kvm_vm *vm, if (!sparsebit_any_set(pages)) return; =20 + if (region->region.guest_memfd !=3D -1) + register_encrypted_memory_region(vm, region); + sparsebit_for_each_set_range(pages, i, j) { const uint64_t size_to_load =3D (j - i + 1) * vm->page_size; const uint64_t offset =3D (i - lowest_page_in_region) * vm->page_size; const uint64_t hva =3D hva_base + offset; const uint64_t gpa =3D gpa_base + offset; - void *source_addr; + void *source_addr =3D (void *)hva; =20 /* * KVM_TDX_INIT_MEM_REGION ioctl cannot encrypt memory in place. * Make a copy if there's only one backing memory source. */ - source_addr =3D mmap(NULL, size_to_load, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - TEST_ASSERT(source_addr, - "Could not allocate memory for loading memory region"); - - memcpy(source_addr, (void *)hva, size_to_load); + if (region->region.guest_memfd =3D=3D -1) { + source_addr =3D mmap(NULL, size_to_load, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + TEST_ASSERT(source_addr, + "Could not allocate memory for loading memory region"); + + memcpy(source_addr, (void *)hva, size_to_load); + memset((void *)hva, 0, size_to_load); + } =20 tdx_init_mem_region(vm, source_addr, gpa, size_to_load); =20 - munmap(source_addr, size_to_load); + if (region->region.guest_memfd =3D=3D -1) + munmap(source_addr, size_to_load); } } =20 --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (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 A93C9274FE5 for ; Thu, 7 Aug 2025 20:16:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597813; cv=none; b=BH70ljQmkeh2A0h43PxUX6iCPIU7fKg8xQwgqS6XjsX9Qk9RX8jMPQmlG1U/tMACTuy4Npr+ItYONebd7QPSnLdFcR6AQGHhBM2CEATN+mi6rxgohtDrGC7zwyuSJqyCDJbDrMiGXfcCHnC+PkCyTmHUtwjHDpcdiq7Nsr+dxPg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597813; c=relaxed/simple; bh=FHT+pXo/w1BnDb59W4bAlOeiGiGRAKxMbBbVeaVxqjg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=DrichbXWWIvWs1rMI5Ban8C3XLYk+/gTbsrVvBYwoOiE25+8AUJJ/mA+naqC/kxzEBxmbVj8/fxiMjCFVrX3eLXCbsICoudoHZq0tmNzkiqxO9tKJNDy79q4IGMhwrdVkyqGlNVQbY/dpUPbaaGf3tLraOg231l2as+ewWokFAU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=L9Qjkdsf; arc=none smtp.client-ip=209.85.216.74 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="L9Qjkdsf" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-31f74a64da9so1615206a91.2 for ; Thu, 07 Aug 2025 13:16:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597811; x=1755202611; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=mQ+l4qlwm2sAkDGxiWIkckLBupdWGtIgKLArWKCiyJk=; b=L9Qjkdsfq5Ec/myRRZy4awsuj2jBa+GQ2QXfQfb1WZgiUU93XICU1Q6qkEt6r4MeLh fir9+xXeszZh6WNSmoHAcQ2iRYfoVNYYdO8GppTzewgacljUv+k/EPFzczD6GxHMlFyW CToixE9HxC70v7Obap/YTJz6xrLddaooNjPsPciWQE/Cpoew0LeS5y480bu+lqn+UHGr hqFeeRUacrSx3hhvl5JsPBXMfOduUatag1vdCorze2aI0MJmIJ/k3Pamjwvdn3PnHts8 bJWczY3G+fT1L8bQOZMehTIlWihCZ+kPDRcTLv8iniPokUqxOIxL8dMryeJiGhVu6JmO xWhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597811; x=1755202611; h=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; bh=mQ+l4qlwm2sAkDGxiWIkckLBupdWGtIgKLArWKCiyJk=; b=NO3POAxqVxux3gDLxdIM7eq0JEmyx49T1bPiqHJLIqlZL+groJI+Yt8SEzj+OsKgJs By4E37tMajNbURWTiX7mxb1QOYOzUcdxHZn+jrTKWhhLBFbSymO2nt3RMyG4iYf3fQc1 twME11e7wUASeO6llvwxqnRTIABEwRp4yole1+TWKy27sg1SlfUa/AJ1+BPgMkhstmcQ usRcKKBh05rd5ZiUU7LzEpX8ccDcEtaDuMtsqOCbtATt1zr/JTPUcdcGzdi5plSyw78q 5B3CiN4LQT5RA2u0gfrgUQYjW1++cHQesOYEvMauy+88ozdYJa3eZ2g80A+1JjP+rEV+ n9/g== X-Gm-Message-State: AOJu0YyzlYRoVOYAFvWkpS2M4gCE8Expv1jGh4w3TnnrUlJ6yxOlybEW Eh2rgnLc16rJuuj28QNUWhRSt1f9UIu8edQYXqKio9q80h3wdh7GniIN6MW6D0GjIiAQXKM7Tg3 cJw== X-Google-Smtp-Source: AGHT+IHBjfutK9n0MpWfkTivlKzn8C8zxUM9AT7/hPMs3/kEGbTffQD+0X1OdZb2CTCxoCpo9fxUxveM7Q== X-Received: from pjbsk13.prod.google.com ([2002:a17:90b:2dcd:b0:321:78e7:57fb]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:39c7:b0:313:b78:dc14 with SMTP id 98e67ed59e1d1-32183899518mr543389a91.0.1754597811066; Thu, 07 Aug 2025 13:16:51 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:05 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-10-sagis@google.com> Subject: [PATCH v8 09/30] KVM: selftests: TDX: Add TDX lifecycle test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Erdem Aktas Adding a test to verify TDX lifecycle by creating a TD and running a dummy TDG.VP.VMCALL inside it. Co-developed-by: Sagi Shahar Signed-off-by: Sagi Shahar Co-developed-by: Ackerley Tng Signed-off-by: Ackerley Tng Co-developed-by: Reinette Chatre Signed-off-by: Reinette Chatre Signed-off-by: Erdem Aktas Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/Makefile.kvm | 4 + .../selftests/kvm/include/x86/tdx/tdcall.h | 32 +++++++ .../selftests/kvm/include/x86/tdx/tdx.h | 12 +++ .../selftests/kvm/include/x86/tdx/test_util.h | 41 ++++++++ .../selftests/kvm/lib/x86/tdx/tdcall.S | 95 +++++++++++++++++++ tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 27 ++++++ .../selftests/kvm/lib/x86/tdx/test_util.c | 61 ++++++++++++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 47 +++++++++ 8 files changed, 319 insertions(+) create mode 100644 tools/testing/selftests/kvm/include/x86/tdx/tdcall.h create mode 100644 tools/testing/selftests/kvm/include/x86/tdx/tdx.h create mode 100644 tools/testing/selftests/kvm/include/x86/tdx/test_util.h create mode 100644 tools/testing/selftests/kvm/lib/x86/tdx/tdcall.S create mode 100644 tools/testing/selftests/kvm/lib/x86/tdx/tdx.c create mode 100644 tools/testing/selftests/kvm/lib/x86/tdx/test_util.c create mode 100644 tools/testing/selftests/kvm/x86/tdx_vm_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index b429c92e07d8..4a147d498bd2 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -31,6 +31,9 @@ LIBKVM_x86 +=3D lib/x86/ucall.c LIBKVM_x86 +=3D lib/x86/vmx.c LIBKVM_x86 +=3D lib/x86/tdx/tdx_util.c LIBKVM_x86 +=3D lib/x86/tdx/td_boot.S +LIBKVM_x86 +=3D lib/x86/tdx/tdcall.S +LIBKVM_x86 +=3D lib/x86/tdx/tdx.c +LIBKVM_x86 +=3D lib/x86/tdx/test_util.c =20 LIBKVM_arm64 +=3D lib/arm64/gic.c LIBKVM_arm64 +=3D lib/arm64/gic_v3.c @@ -148,6 +151,7 @@ TEST_GEN_PROGS_x86 +=3D rseq_test TEST_GEN_PROGS_x86 +=3D steal_time TEST_GEN_PROGS_x86 +=3D system_counter_offset_test TEST_GEN_PROGS_x86 +=3D pre_fault_memory_test +TEST_GEN_PROGS_x86 +=3D x86/tdx_vm_test =20 # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86 +=3D x86/nx_huge_pages_test diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdcall.h b/tools/t= esting/selftests/kvm/include/x86/tdx/tdcall.h new file mode 100644 index 000000000000..a6c966e93486 --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdcall.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Adapted from arch/x86/include/asm/shared/tdx.h */ + +#ifndef SELFTESTS_TDX_TDCALL_H +#define SELFTESTS_TDX_TDCALL_H + +#include +#include + +#define TDX_HCALL_HAS_OUTPUT BIT(0) + +#define TDX_HYPERCALL_STANDARD 0 + +/* + * Used in __tdx_hypercall() to pass down and get back registers' values of + * the TDCALL instruction when requesting services from the VMM. + * + * This is a software only structure and not part of the TDX module/VMM AB= I. + */ +struct tdx_hypercall_args { + u64 r10; + u64 r11; + u64 r12; + u64 r13; + u64 r14; + u64 r15; +}; + +/* Used to request services from the VMM */ +u64 __tdx_hypercall(struct tdx_hypercall_args *args, unsigned long flags); + +#endif // SELFTESTS_TDX_TDCALL_H diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h new file mode 100644 index 000000000000..a7161efe4ee2 --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_TDX_TDX_H +#define SELFTEST_TDX_TDX_H + +#include + +#define TDG_VP_VMCALL_INSTRUCTION_IO 30 + +uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, + uint64_t write, uint64_t *data); + +#endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h b/tool= s/testing/selftests/kvm/include/x86/tdx/test_util.h new file mode 100644 index 000000000000..07d63bf1ffe1 --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86/tdx/test_util.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_TDX_TEST_UTIL_H +#define SELFTEST_TDX_TEST_UTIL_H + +#include + +#include "tdcall.h" + +#define TDX_TEST_SUCCESS_PORT 0x30 +#define TDX_TEST_SUCCESS_SIZE 4 + +/* Port I/O direction */ +#define PORT_READ 0 +#define PORT_WRITE 1 + +/* + * Run a test in a new process. + * + * There might be multiple tests running and if one test fails, it will + * prevent the subsequent tests to run due to how tests are failing with + * TEST_ASSERT function. run_in_new_process() will run a test in a new pro= cess + * context and wait for it to finish or fail to prevent TEST_ASSERT to kil= l the + * main testing process. + */ +int run_in_new_process(void (*func)(void)); + +/* + * Verify that the TDX is supported by KVM. + */ +bool is_tdx_enabled(void); + +/* + * Report test success to userspace. + * + * Use tdx_test_assert_success() to assert that this function was called i= n the + * guest. + */ +void tdx_test_success(void); +void tdx_test_assert_success(struct kvm_vcpu *vcpu); + +#endif // SELFTEST_TDX_TEST_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdcall.S b/tools/testi= ng/selftests/kvm/lib/x86/tdx/tdcall.S new file mode 100644 index 000000000000..b10769d1d557 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdcall.S @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Adapted from arch/x86/coco/tdx/tdcall.S */ + +/* + * TDCALL is supported in Binutils >=3D 2.36, add it for older version. + */ +#define tdcall .byte 0x66,0x0f,0x01,0xcc + +#define TDX_HYPERCALL_r10 0 /* offsetof(struct tdx_hypercall_args, r10) */ +#define TDX_HYPERCALL_r11 8 /* offsetof(struct tdx_hypercall_args, r11) */ +#define TDX_HYPERCALL_r12 16 /* offsetof(struct tdx_hypercall_args, r12) */ +#define TDX_HYPERCALL_r13 24 /* offsetof(struct tdx_hypercall_args, r13) */ +#define TDX_HYPERCALL_r14 32 /* offsetof(struct tdx_hypercall_args, r14) */ +#define TDX_HYPERCALL_r15 40 /* offsetof(struct tdx_hypercall_args, r15) */ + +/* + * Bitmasks of exposed registers (with VMM). + */ +#define TDX_R10 0x400 +#define TDX_R11 0x800 +#define TDX_R12 0x1000 +#define TDX_R13 0x2000 +#define TDX_R14 0x4000 +#define TDX_R15 0x8000 + +#define TDX_HCALL_HAS_OUTPUT 0x1 + +/* + * These registers are clobbered to hold arguments for each + * TDVMCALL. They are safe to expose to the VMM. + * Each bit in this mask represents a register ID. Bit field + * details can be found in TDX GHCI specification, section + * titled "TDCALL [TDG.VP.VMCALL] leaf". + */ +#define TDVMCALL_EXPOSE_REGS_MASK ( TDX_R10 | TDX_R11 | \ + TDX_R12 | TDX_R13 | \ + TDX_R14 | TDX_R15 ) + +.code64 +.section .text + +.globl __tdx_hypercall +.type __tdx_hypercall, @function +__tdx_hypercall: + /* Set up stack frame */ + push %rbp + movq %rsp, %rbp + + /* Save callee-saved GPRs as mandated by the x86_64 ABI */ + push %r15 + push %r14 + push %r13 + push %r12 + + /* Mangle function call ABI into TDCALL ABI: */ + /* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */ + xor %eax, %eax + + /* Copy hypercall registers from arg struct: */ + movq TDX_HYPERCALL_r10(%rdi), %r10 + movq TDX_HYPERCALL_r11(%rdi), %r11 + movq TDX_HYPERCALL_r12(%rdi), %r12 + movq TDX_HYPERCALL_r13(%rdi), %r13 + movq TDX_HYPERCALL_r14(%rdi), %r14 + movq TDX_HYPERCALL_r15(%rdi), %r15 + + movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx + + tdcall + + /* TDVMCALL leaf return code is in R10 */ + movq %r10, %rax + + /* Copy hypercall result registers to arg struct if needed */ + testq $TDX_HCALL_HAS_OUTPUT, %rsi + jz .Lout + + movq %r10, TDX_HYPERCALL_r10(%rdi) + movq %r11, TDX_HYPERCALL_r11(%rdi) + movq %r12, TDX_HYPERCALL_r12(%rdi) + movq %r13, TDX_HYPERCALL_r13(%rdi) + movq %r14, TDX_HYPERCALL_r14(%rdi) + movq %r15, TDX_HYPERCALL_r15(%rdi) +.Lout: + /* Restore callee-saved GPRs as mandated by the x86_64 ABI */ + pop %r12 + pop %r13 + pop %r14 + pop %r15 + + pop %rbp + ret + +/* Disable executable stack */ +.section .note.GNU-stack,"",%progbits diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c new file mode 100644 index 000000000000..f417ee75bee2 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "tdx/tdcall.h" +#include "tdx/tdx.h" + +uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, + uint64_t write, uint64_t *data) +{ + struct tdx_hypercall_args args =3D { + .r10 =3D TDX_HYPERCALL_STANDARD, + .r11 =3D TDG_VP_VMCALL_INSTRUCTION_IO, + .r12 =3D size, + .r13 =3D write, + .r14 =3D port, + }; + uint64_t ret; + + if (write) + args.r15 =3D *data; + + ret =3D __tdx_hypercall(&args, write ? 0 : TDX_HCALL_HAS_OUTPUT); + + if (!write) + *data =3D args.r11; + + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c b/tools/te= sting/selftests/kvm/lib/x86/tdx/test_util.c new file mode 100644 index 000000000000..7355b213c344 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "tdx/tdx.h" +#include "tdx/test_util.h" + +int run_in_new_process(void (*func)(void)) +{ + int wstatus; + pid_t ret; + + if (fork() =3D=3D 0) { + func(); + exit(0); + } + ret =3D wait(&wstatus); + if (ret =3D=3D -1) + return -1; + + if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus)) + return -1; + else if (WIFSIGNALED(wstatus)) + return -1; + + return 0; +} + +bool is_tdx_enabled(void) +{ + return !!(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_TDX_VM)); +} + +void tdx_test_success(void) +{ + uint64_t code =3D 0; + + tdg_vp_vmcall_instruction_io(TDX_TEST_SUCCESS_PORT, TDX_TEST_SUCCESS_SIZE, + PORT_WRITE, &code); +} + +/* + * Assert that tdx_test_success() was called in the guest. + */ +void tdx_test_assert_success(struct kvm_vcpu *vcpu) +{ + TEST_ASSERT((vcpu->run->exit_reason =3D=3D KVM_EXIT_IO) && + (vcpu->run->io.port =3D=3D TDX_TEST_SUCCESS_PORT) && + (vcpu->run->io.size =3D=3D TDX_TEST_SUCCESS_SIZE) && + (vcpu->run->io.direction =3D=3D PORT_WRITE), + "Unexpected exit values while waiting for test completion: %u (%s) %= d %d %d\n", + vcpu->run->exit_reason, + exit_reason_str(vcpu->run->exit_reason), + vcpu->run->io.port, vcpu->run->io.size, + vcpu->run->io.direction); +} diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c new file mode 100644 index 000000000000..fdb7c40065a6 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include + +#include "kvm_util.h" +#include "tdx/tdx_util.h" +#include "tdx/test_util.h" +#include "test_util.h" + +static void guest_code_lifecycle(void) +{ + tdx_test_success(); +} + +static void verify_td_lifecycle(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_code_lifecycle); + td_finalize(vm); + + printf("Verifying TD lifecycle:\n"); + + vcpu_run(vcpu); + tdx_test_assert_success(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + +int main(int argc, char **argv) +{ + ksft_print_header(); + + if (!is_tdx_enabled()) + ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); + + ksft_set_plan(1); + ksft_test_result(!run_in_new_process(&verify_td_lifecycle), + "verify_td_lifecycle\n"); + + ksft_finished(); + return 0; +} --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (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 92044275110 for ; Thu, 7 Aug 2025 20:16:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597815; cv=none; b=Ojh8r614u98qY4twK0luuBTMnDjGrDG3J+oYClYx/LGc/TobRaLZmxDzyzagJconEdjV97I+kxraEX0oG/Ir9BMaSAzxSGqD74Jx1NZo3GFFNRVuC2ezNRzMB4U23ZSnSp0MlsyHSHB709HcldevteoFMiuFvGLECm7ZkBgLQBU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597815; c=relaxed/simple; bh=z+7gLlyWxfDul6oet1RXQIJyLgetpcrN7AHbzIzqphA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=NABZ1xRNiV314dI4050lcyt5P7nLHngHzV2twKIgDLpjTTT9b2FpXdqdbyL/0so5W2Rx8oOo6I+WFCvveNfvWgHBFbC0CkM39k2VkH1IeQiJHJ+rJ8Y+E6Whk/0k3Sa9Z3qWaOW1I//QyBB2orplKbfmY9Qh98mg5uRjwbfIjV8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=h/6jO7qh; arc=none smtp.client-ip=209.85.216.74 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="h/6jO7qh" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-31f5f70a07bso2032965a91.3 for ; Thu, 07 Aug 2025 13:16:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597813; x=1755202613; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=QyNlNlLPqLW2teTGCuUaRtpJSFI4nGCnRDvpuq+iYmU=; b=h/6jO7qhg+DYLtwKq8bHfN4opyFYwcJfoSMVQkYnk8ILkayKBOMwAcg/aYkFWwwe7M BZCSvsOUkH567hH1ZMwrsYBqV20QWSO84FXjymms+vDIUIvj8p9nMR1hynWzlwVd1x1H ujLMtdEv6gVMEo1iTaUv5iuhHbI5A580Gxn5kK/DSFRHg/b2AkuvEm1dZc1Iyq0HExO3 RyU3gpkdIcwJf4Ga/djS8HWPMAV4TvGwjItjQzTKg8wzC7WXtboIWtbXew0+wZK9VTOY qgdlLWVZJ/zoQAZEIft+ERBradW4clBNPxYzEb0jD5/mhLRuzCehbHrz4CSPFOU7TDFk kjqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597813; x=1755202613; h=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; bh=QyNlNlLPqLW2teTGCuUaRtpJSFI4nGCnRDvpuq+iYmU=; b=NcUQF+Mcua8sMetKmiOddk9WseYDZfRzhXIEs1iQl18tTQLD+nuIix9TvDHpSJPWwo QGQX3YAI2FSyuBKN1WkPQ91utWv5RqCxNP3RgfUjXkLrt+7K/7Lw/6N6+lj2dHNQOiP1 +JXQ94ZkIpMsGkwNPlDbaNjCpjpwlQKlm8IR7CjQllTj9fz7Ovy9bpnlkXNiVedmegPT dTFXnAy9R/TR5GfrSTmaqKN3nLOkbL7viuquGTNws75V2qWol5+pTYn7R8kB8/leNP2u SZNX5gRWSMicR+8LAdD3wo5zENh3sCXUmPhREkP8zRAy68zwzqD6lYIa8BuA4KBEhGfD aT0w== X-Gm-Message-State: AOJu0Yw2JScRgFXgmZl038q9qg8feii7c6dQ+bs6OR4JTJjSIjjBqGO4 xz4rlGzsON5bMZrlQnPczuAmhGY0KrIlvNmnyXgQRboapkbRWMUo2Jp8kj5FWPcjH925VQPcM4y deQ== X-Google-Smtp-Source: AGHT+IFbjTzekAW0h8elEcH8qUjQZXjaXe1tt597Yy/VuMojgGTibZDORFJjs7AVlVU/OY02NfmLuCUR6Q== X-Received: from pjx15.prod.google.com ([2002:a17:90b:568f:b0:31c:32f8:3f88]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:48c4:b0:312:1ac5:c7c7 with SMTP id 98e67ed59e1d1-321839d5845mr539026a91.2.1754597812731; Thu, 07 Aug 2025 13:16:52 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:06 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-11-sagis@google.com> Subject: [PATCH v8 10/30] KVM: selftests: TDX: Add report_fatal_error test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The test checks report_fatal_error functionality. TD guest can use TDG.VP.VMCALL to report the fatal error it has experienced. TD guest is requesting a termination with the error information that include 16 general-purpose registers. Co-developed-by: Binbin Wu Signed-off-by: Binbin Wu Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/tdx.h | 6 ++- .../selftests/kvm/include/x86/tdx/tdx_util.h | 1 + .../selftests/kvm/include/x86/tdx/test_util.h | 19 +++++++ tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 18 +++++++ .../selftests/kvm/lib/x86/tdx/tdx_util.c | 6 +++ .../selftests/kvm/lib/x86/tdx/test_util.c | 10 ++++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 51 ++++++++++++++++++- 7 files changed, 108 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index a7161efe4ee2..2acccc9dccf9 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -4,9 +4,13 @@ =20 #include =20 +#include "kvm_util.h" + +#define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 + #define TDG_VP_VMCALL_INSTRUCTION_IO 30 =20 uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, uint64_t write, uint64_t *data); - +void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_g= pa); #endif // SELFTEST_TDX_TDX_H 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 57a2f5893ffe..d66cf17f03ea 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h @@ -15,5 +15,6 @@ struct kvm_vm *td_create(void); void td_initialize(struct kvm_vm *vm, enum vm_mem_backing_src_type src_typ= e, uint64_t attributes); void td_finalize(struct kvm_vm *vm); +void td_vcpu_run(struct kvm_vcpu *vcpu); =20 #endif // SELFTESTS_TDX_KVM_UTIL_H diff --git a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h b/tool= s/testing/selftests/kvm/include/x86/tdx/test_util.h index 07d63bf1ffe1..dafeee9af1dc 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/test_util.h @@ -38,4 +38,23 @@ bool is_tdx_enabled(void); void tdx_test_success(void); void tdx_test_assert_success(struct kvm_vcpu *vcpu); =20 +/* + * Report an error with @error_code to userspace. + * + * Return value from tdg_vp_vmcall_report_fatal_error() is ignored since + * execution is not expected to continue beyond this point. + */ +void tdx_test_fatal(uint64_t error_code); + +/* + * Report an error with @error_code to userspace. + * + * @data_gpa may point to an optional shared guest memory holding the error + * string. + * + * Return value from tdg_vp_vmcall_report_fatal_error() is ignored since + * execution is not expected to continue beyond this point. + */ +void tdx_test_fatal_with_data(uint64_t error_code, uint64_t data_gpa); + #endif // SELFTEST_TDX_TEST_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index f417ee75bee2..ba088bfc1e62 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only =20 +#include + #include "tdx/tdcall.h" #include "tdx/tdx.h" =20 @@ -25,3 +27,19 @@ uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uin= t64_t size, =20 return ret; } + +void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_g= pa) +{ + struct tdx_hypercall_args args; + + memset(&args, 0, sizeof(struct tdx_hypercall_args)); + + if (data_gpa) + error_code |=3D 0x8000000000000000; + + args.r11 =3D TDG_VP_VMCALL_REPORT_FATAL_ERROR; + args.r12 =3D error_code; + args.r13 =3D data_gpa; + + __tdx_hypercall(&args, 0); +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/tes= ting/selftests/kvm/lib/x86/tdx/tdx_util.c index e2bf9766dc03..5e4455be828a 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c @@ -9,6 +9,7 @@ #include "kvm_util.h" #include "processor.h" #include "tdx/td_boot.h" +#include "tdx/tdx.h" #include "test_util.h" =20 uint64_t tdx_s_bit; @@ -603,3 +604,8 @@ void td_finalize(struct kvm_vm *vm) =20 tdx_td_finalize_mr(vm); } + +void td_vcpu_run(struct kvm_vcpu *vcpu) +{ + vcpu_run(vcpu); +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c b/tools/te= sting/selftests/kvm/lib/x86/tdx/test_util.c index 7355b213c344..6c82a0c3bd37 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c @@ -59,3 +59,13 @@ void tdx_test_assert_success(struct kvm_vcpu *vcpu) vcpu->run->io.port, vcpu->run->io.size, vcpu->run->io.direction); } + +void tdx_test_fatal_with_data(uint64_t error_code, uint64_t data_gpa) +{ + tdg_vp_vmcall_report_fatal_error(error_code, data_gpa); +} + +void tdx_test_fatal(uint64_t error_code) +{ + tdx_test_fatal_with_data(error_code, 0); +} diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index fdb7c40065a6..7d6d71602761 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -3,6 +3,7 @@ #include =20 #include "kvm_util.h" +#include "tdx/tdx.h" #include "tdx/tdx_util.h" #include "tdx/test_util.h" #include "test_util.h" @@ -24,7 +25,51 @@ static void verify_td_lifecycle(void) =20 printf("Verifying TD lifecycle:\n"); =20 - vcpu_run(vcpu); + td_vcpu_run(vcpu); + tdx_test_assert_success(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + +void guest_code_report_fatal_error(void) +{ + uint64_t err; + + /* + * Note: err should follow the GHCI spec definition: + * bits 31:0 should be set to 0. + * bits 62:32 are used for TD-specific extended error code. + * bit 63 is used to mark additional information in shared memory. + */ + err =3D 0x0BAAAAAD00000000; + tdx_test_fatal(err); + + tdx_test_success(); +} + +void verify_report_fatal_error(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_code_report_fatal_error); + td_finalize(vm); + + printf("Verifying report_fatal_error:\n"); + + td_vcpu_run(vcpu); + + TEST_ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYSTEM_EVENT); + TEST_ASSERT_EQ(vcpu->run->system_event.type, KVM_SYSTEM_EVENT_TDX_FATAL); + TEST_ASSERT_EQ(vcpu->run->system_event.ndata, 16); + + TEST_ASSERT_EQ(vcpu->run->system_event.data[12], 0x0BAAAAAD00000000); + TEST_ASSERT_EQ(vcpu->run->system_event.data[13], 0); + + td_vcpu_run(vcpu); tdx_test_assert_success(vcpu); =20 kvm_vm_free(vm); @@ -38,9 +83,11 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(1); + ksft_set_plan(2); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); + ksft_test_result(!run_in_new_process(&verify_report_fatal_error), + "verify_report_fatal_error\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (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 4762D275AED for ; Thu, 7 Aug 2025 20:16:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597817; cv=none; b=JMFc9FsyGsqVqAs7vMR1xMSlF4guQkz9x5C54V1338W+siMksjrJrvDKzjilCu8mz+1NhIXa0cJHId16sKCIbFVKVKsxF+4esCJPR3hI0IndFrqb16On0RuzkxIdOc2ST7psQBqtVw0Fyw/0E47K97Jb14JuUiOJpGK05UTcSdY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597817; c=relaxed/simple; bh=8/991SaqhfbOuXxYGVBkbjKMlNrrAbPc+jQ8DkNet6Y=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=hyO0wCxlr745WlbRHx+oDpnJZeBRZJRCR3bMa5mx4REWjaskY/w6p8tff5iCCCS7oWFZfSaQ90s8qiN7CQxGaeP0hSIpSsY/8W+6r/13sj7Bu/7kRnMZfqpe11Cf+8ZoiFClq+MBL4xWbAahCymFMnNYkchqx96J5zcb7XHnxpE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ktw5nj8h; arc=none smtp.client-ip=209.85.210.201 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ktw5nj8h" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-76bb73b63d2so1555239b3a.1 for ; Thu, 07 Aug 2025 13:16:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597815; x=1755202615; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Qod859ACwAJ9KJXJ66Pu3+9/i9Fm4EF7ZGslehKFgPA=; b=ktw5nj8hoBYBZya6tgjKW1e0edgY0Gyc4rjJmkPbKOJaXe16ikMFwbfC3zw7xxMgDe SAH9GcOYDGpLrmFS+X8UdaR2lJwRR4v+F1+ZqZYHx+mo2oaQs4q3nrXzRQmHrTeFDeJQ Yd6RJ2zMcetkFhH3hI2/ots2HHTDqJR3My27eVB8pzlrboIH8AWujf/iRwQHIldV/KyT 5RcGiWL3lMRo4YuLqX/YLJI9UdM6mvc3PsgV9uGccM4l1On9bpXawLx4GBeUEwSxwzdp hjKRBWxSGdOLtnp8Y/oVp2xGfRVv4sz36oYLFCEHaobnojnc7dcJgbYtpfpehf1JSkIT Xxwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597815; x=1755202615; h=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; bh=Qod859ACwAJ9KJXJ66Pu3+9/i9Fm4EF7ZGslehKFgPA=; b=ctWP3uWVwgeNSKq0Mfcu+MmObH6g4j8l2FWXFgsG8ok8zxIvd/ty4FXRoKEIlVW9wR OEfIgpxUS7P/+LoXmv7g5gP/mNmP+Y0nGMRaJbfy954VBmSJsiys2OtYXrXfWuqaJqs0 R9ZxBreHAx9IVBnNRK+toG3iZp9oGPZlQcT1F9d8rCZZYYJX1pjTBMywLi/h7jlc9PBd LqZr1UVRN7dWF6u9ZWwW0WXl4viaiJ2H8t20rZhw5elckNlwtITRJ/dwLfp7KBxJ2EGI qSKvLfLxWM8gMiV0fbo6WTpSBGIvINsHLyFtBqOiQMPuFgUy771FeAl4nXc0dTw+PG3O H/dw== X-Gm-Message-State: AOJu0Yxy+7a9doF6bjUsLVxdBn1MlCyREsELUK7Ng5uPpL2ThqJ2lP6T b2tMDsYxGs5RjCrl+AP/aNQieiUVyIitnnAdbIt94yBiyI3Rv8VOkdDRWz0g6v6jpgeO8ikFlsH gFQ== X-Google-Smtp-Source: AGHT+IElhGKAW5wN//qmv94pEi0jFcwaYTH9QkghkSjAapFDDJMVQZjNYUu6DUB+rXi8WiqKmyIVXaKSpQ== X-Received: from pftb22.prod.google.com ([2002:a05:6a00:2d6:b0:76b:fe87:6051]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:1389:b0:736:54c9:df2c with SMTP id d2e1a72fcca58-76c46111288mr619107b3a.15.1754597814594; Thu, 07 Aug 2025 13:16:54 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:07 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-12-sagis@google.com> Subject: [PATCH v8 11/30] KVM: selftests: TDX: Adding test case for TDX port IO From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Verifies TDVMCALL READ and WRITE operations. Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/test_util.h | 20 +++++ .../selftests/kvm/lib/x86/tdx/test_util.c | 35 +++++++++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 78 ++++++++++++++++++- 3 files changed, 130 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h b/tool= s/testing/selftests/kvm/include/x86/tdx/test_util.h index dafeee9af1dc..cf11955d56d6 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/test_util.h @@ -13,6 +13,19 @@ #define PORT_READ 0 #define PORT_WRITE 1 =20 +/* + * Assert that some IO operation involving tdg_vp_vmcall_instruction_io() = was + * called in the guest. + */ +void tdx_test_assert_io(struct kvm_vcpu *vcpu, uint16_t port, uint8_t size, + uint8_t direction); + +/* + * Run the tdx vcpu and check if there was some failure in the guest, eith= er + * an exception like a triple fault, or if a tdx_test_fatal() was hit. + */ +void tdx_run(struct kvm_vcpu *vcpu); + /* * Run a test in a new process. * @@ -57,4 +70,11 @@ void tdx_test_fatal(uint64_t error_code); */ void tdx_test_fatal_with_data(uint64_t error_code, uint64_t data_gpa); =20 +/* + * Assert on @error and report the @error to userspace. + * Return value from tdg_vp_vmcall_report_fatal_error() is ignored since e= xecution + * is not expected to continue beyond this point. + */ +void tdx_assert_error(uint64_t error); + #endif // SELFTEST_TDX_TEST_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c b/tools/te= sting/selftests/kvm/lib/x86/tdx/test_util.c index 6c82a0c3bd37..4ccc5298ba25 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c @@ -8,8 +8,37 @@ =20 #include "kvm_util.h" #include "tdx/tdx.h" +#include "tdx/tdx_util.h" #include "tdx/test_util.h" =20 +void tdx_test_assert_io(struct kvm_vcpu *vcpu, uint16_t port, uint8_t size, + uint8_t direction) +{ + TEST_ASSERT(vcpu->run->exit_reason =3D=3D KVM_EXIT_IO, + "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", + vcpu->run->exit_reason, + exit_reason_str(vcpu->run->exit_reason)); + + TEST_ASSERT(vcpu->run->exit_reason =3D=3D KVM_EXIT_IO && + vcpu->run->io.port =3D=3D port && + vcpu->run->io.size =3D=3D size && + vcpu->run->io.direction =3D=3D direction, + "Got unexpected IO exit values: %u (%s) %u %u %u\n", + vcpu->run->exit_reason, + exit_reason_str(vcpu->run->exit_reason), + vcpu->run->io.port, vcpu->run->io.size, + vcpu->run->io.direction); +} + +void tdx_run(struct kvm_vcpu *vcpu) +{ + td_vcpu_run(vcpu); + if (vcpu->run->exit_reason =3D=3D KVM_EXIT_SYSTEM_EVENT) + TEST_FAIL("Guest reported error. error code: %lld (0x%llx)\n", + vcpu->run->system_event.data[12], + vcpu->run->system_event.data[13]); +} + int run_in_new_process(void (*func)(void)) { int wstatus; @@ -69,3 +98,9 @@ void tdx_test_fatal(uint64_t error_code) { tdx_test_fatal_with_data(error_code, 0); } + +void tdx_assert_error(uint64_t error) +{ + if (error) + tdx_test_fatal(error); +} diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index 7d6d71602761..97330e28f236 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -3,6 +3,7 @@ #include =20 #include "kvm_util.h" +#include "tdx/tdcall.h" #include "tdx/tdx.h" #include "tdx/tdx_util.h" #include "tdx/test_util.h" @@ -25,7 +26,7 @@ static void verify_td_lifecycle(void) =20 printf("Verifying TD lifecycle:\n"); =20 - td_vcpu_run(vcpu); + tdx_run(vcpu); tdx_test_assert_success(vcpu); =20 kvm_vm_free(vm); @@ -69,9 +70,78 @@ void verify_report_fatal_error(void) TEST_ASSERT_EQ(vcpu->run->system_event.data[12], 0x0BAAAAAD00000000); TEST_ASSERT_EQ(vcpu->run->system_event.data[13], 0); =20 - td_vcpu_run(vcpu); + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + +#define TDX_IOEXIT_TEST_PORT 0x50 + +/* + * Verifies IO functionality by writing a |value| to a predefined port. + * Verifies that the read value is |value| + 1 from the same port. + * If all the tests are passed then write a value to port TDX_TEST_PORT + */ +void guest_ioexit(void) +{ + uint64_t data_out, data_in; + uint64_t ret; + + data_out =3D 0xAB; + ret =3D tdg_vp_vmcall_instruction_io(TDX_IOEXIT_TEST_PORT, 1, + PORT_WRITE, &data_out); + tdx_assert_error(ret); + + ret =3D tdg_vp_vmcall_instruction_io(TDX_IOEXIT_TEST_PORT, 1, + PORT_READ, &data_in); + tdx_assert_error(ret); + + if (data_in !=3D 0xAC) + tdx_test_fatal(data_in); + + tdx_test_success(); +} + +void verify_td_ioexit(void) +{ + struct kvm_vcpu *vcpu; + uint32_t port_data; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_ioexit); + td_finalize(vm); + + printf("Verifying TD IO Exit:\n"); + + /* Wait for guest to do a IO write */ + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_IOEXIT_TEST_PORT, 1, PORT_WRITE); + port_data =3D *(uint8_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + printf("\t ... IO WRITE: DONE\n"); + + /* + * Wait for the guest to do a IO read. Provide the previous written data + * + 1 back to the guest + */ + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_IOEXIT_TEST_PORT, 1, PORT_READ); + *(uint8_t *)((void *)vcpu->run + vcpu->run->io.data_offset) =3D port_data= + 1; + + printf("\t ... IO READ: DONE\n"); + + /* + * Wait for the guest to complete execution successfully. The read + * value is checked within the guest. + */ + tdx_run(vcpu); tdx_test_assert_success(vcpu); =20 + printf("\t ... IO verify read/write values: OK\n"); kvm_vm_free(vm); printf("\t ... PASSED\n"); } @@ -83,11 +153,13 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(2); + ksft_set_plan(3); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), "verify_report_fatal_error\n"); + ksft_test_result(!run_in_new_process(&verify_td_ioexit), + "verify_td_ioexit\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (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 BD892276025 for ; Thu, 7 Aug 2025 20:16:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597818; cv=none; b=Kg6E2EBXbli4KkAjRkuJnwrw0QtSDDz/YH/eqhT0K/nmhpgPyM6zGFi6q+EHuZ9CRC0O1Wmd0d5Wc2Up+6Vgolj0hWRflCT3gxno4YGMwzAMdOCNXNbqTeyqvnnRj949xjzUwopnPFYBuMjIk2ZWZ4mi2bGYRmvx2FHb5fYV9a4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597818; c=relaxed/simple; bh=zz03QvQy9BhkUcCbKhB8ZYqpdO348eIqrosxGGKxtEk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=nZ58+3KBurlORa0DH4gfs5OmnAAn5YsmkpHa+GEd4EESR4yU1bXGRltKH7/9vkX5kfM/ukWs7E9Hq6ZPYOVn7y2rNXFJtiE1F5VOx1+IcaOHvbi6G9a0/YNTFftFM7jNAafwxxXfSlAxdAkZBIe8NzK1XdbrlsQl69LwwOWjeks= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Cop8wzbn; arc=none smtp.client-ip=209.85.216.74 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Cop8wzbn" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-32129c65bf8so1608182a91.1 for ; Thu, 07 Aug 2025 13:16:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597816; x=1755202616; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=H02GupghP06Pl6XppekrAspyM14zQhrZcjITLukp9sM=; b=Cop8wzbnRhGpzT/R202f6zeU7XyUTNjJcQLqVKvMu9NvBum9X8NewZFAICHbe+dTw6 uTCWRm/FO+ZiqcfpbfybgGdv/waGmxzOLOXBTyAwYkxdiPHSIxn7DMklz5vDLBwVlTw2 nCXXPktrnUG449/Mw4xLu7SDR9X+RC8fWDVVT2JymxyxOGKQGVfhDqS4bScFQfZVpFEI PHbdw4LoeeksWJUEdpzSR8QvnVc4MhvBC8sw5koAU6hOjmgibSstKa7VSqfH2GZlYolp Q86gbLqT9kxMj5A/p3QkErm8LiCpCB3isoqDXoMvhdZNQ7jaWQGliM9ZLhQgzd3KO6cr +I+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597816; x=1755202616; h=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; bh=H02GupghP06Pl6XppekrAspyM14zQhrZcjITLukp9sM=; b=JWUG6yq8Qc+vENzCslwemuNLvqKxSu615qWkgKfDr2lx3tJMm5WemoScb3kgHSAzm7 uR46N27veNUpYNDzmERgjazsswPfjqnXnYvltOFHQqFXkqYuBgkDrTWh5ldGg6NHWw7V KJ4J5YcIIOXkvHAfCWOyV+glvT2JCFITHQ4D85/Jt8q6ZDZ7M+4M6RCrrPvkYgHu8yIe gS87uw4xaxuRSH0cZQ1MfaYQHGgoA0CkWB+DtCNYfX7M3/5fwzfkjByTw0b1gC0DzxC5 gWGOaXv8ApkXcb8EV9KOTdBUmV5vahAgeM7MQtS/XFp1nvSQSjuVzqnWinIzarmsupri BLXQ== X-Gm-Message-State: AOJu0YxyWsZ5+SIcXAi8isTiPTLvQZKFthC2dcyaleRf8vBJ4WFSxQ6p 7m70Ig9MJkiGPXTYnosetrXt7INbK/Aq7tPJM6tlrMd4r3P5T8yZxDo8VumYN/sjcTO7g5/fsuC tQw== X-Google-Smtp-Source: AGHT+IFq754CbVPzWNL/LbseHEnbC9S06XClR4AL5Cvqv0z6d0U8bvMt5QEaurr631DddNOY7Hce1DrpyQ== X-Received: from pjbns14.prod.google.com ([2002:a17:90b:250e:b0:31e:a865:8b32]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:3c49:b0:321:475e:e0b0 with SMTP id 98e67ed59e1d1-321839e1643mr539454a91.11.1754597816103; Thu, 07 Aug 2025 13:16:56 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:08 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-13-sagis@google.com> Subject: [PATCH v8 12/30] KVM: selftests: TDX: Add basic TDX CPUID test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The test reads CPUID values from inside a TD VM and compare them to expected values. The test targets CPUID values which are virtualized as "As Configured", "As Configured (if Native)", "Calculated", "Fixed" and "Native" according to the TDX spec. Co-developed-by: Isaku Yamahata Signed-off-by: Isaku Yamahata Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/test_util.h | 15 +++ .../selftests/kvm/lib/x86/tdx/test_util.c | 20 ++++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 98 ++++++++++++++++++- 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h b/tool= s/testing/selftests/kvm/include/x86/tdx/test_util.h index cf11955d56d6..2af6e810ef78 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/test_util.h @@ -9,6 +9,9 @@ #define TDX_TEST_SUCCESS_PORT 0x30 #define TDX_TEST_SUCCESS_SIZE 4 =20 +#define TDX_TEST_REPORT_PORT 0x31 +#define TDX_TEST_REPORT_SIZE 4 + /* Port I/O direction */ #define PORT_READ 0 #define PORT_WRITE 1 @@ -77,4 +80,16 @@ void tdx_test_fatal_with_data(uint64_t error_code, uint6= 4_t data_gpa); */ void tdx_assert_error(uint64_t error); =20 +/* + * Report a 32 bit value from the guest to user space using TDG.VP.VMCALL + * call. Data is reported on port TDX_TEST_REPORT_PORT. + */ +uint64_t tdx_test_report_to_user_space(uint32_t data); + +/* + * Read a 32 bit value from the guest in user space, sent using + * tdx_test_report_to_user_space(). + */ +uint32_t tdx_test_read_report_from_guest(struct kvm_vcpu *vcpu); + #endif // SELFTEST_TDX_TEST_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c b/tools/te= sting/selftests/kvm/lib/x86/tdx/test_util.c index 4ccc5298ba25..f9bde114a8bc 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c @@ -104,3 +104,23 @@ void tdx_assert_error(uint64_t error) if (error) tdx_test_fatal(error); } + +uint64_t tdx_test_report_to_user_space(uint32_t data) +{ + /* Upcast data to match tdg_vp_vmcall_instruction_io() signature */ + uint64_t data_64 =3D data; + + return tdg_vp_vmcall_instruction_io(TDX_TEST_REPORT_PORT, + TDX_TEST_REPORT_SIZE, PORT_WRITE, + &data_64); +} + +uint32_t tdx_test_read_report_from_guest(struct kvm_vcpu *vcpu) +{ + uint32_t res; + + tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, 4, PORT_WRITE); + res =3D *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + return res; +} diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index 97330e28f236..bbdcca358d71 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -3,6 +3,7 @@ #include =20 #include "kvm_util.h" +#include "processor.h" #include "tdx/tdcall.h" #include "tdx/tdx.h" #include "tdx/tdx_util.h" @@ -146,6 +147,99 @@ void verify_td_ioexit(void) printf("\t ... PASSED\n"); } =20 +/* + * Verifies CPUID functionality by reading CPUID values in guest. The guest + * will then send the values to userspace using an IO write to be checked + * against the expected values. + */ +void guest_code_cpuid(void) +{ + uint32_t ebx, ecx; + uint64_t err; + + /* Read CPUID leaf 0x1 */ + asm volatile ("cpuid" + : "=3Db" (ebx), "=3Dc" (ecx) + : "a" (0x1) + : "edx"); + + err =3D tdx_test_report_to_user_space(ebx); + tdx_assert_error(err); + + err =3D tdx_test_report_to_user_space(ecx); + tdx_assert_error(err); + + tdx_test_success(); +} + +void verify_td_cpuid(void) +{ + uint32_t guest_max_addressable_ids, host_max_addressable_ids; + const struct kvm_cpuid_entry2 *cpuid_entry; + uint32_t guest_clflush_line_size; + uint32_t guest_initial_apic_id; + uint32_t guest_sse3_enabled; + uint32_t guest_fma_enabled; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + uint32_t ebx, ecx; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_code_cpuid); + td_finalize(vm); + + printf("Verifying TD CPUID:\n"); + + /* Wait for guest to report ebx value */ + tdx_run(vcpu); + ebx =3D tdx_test_read_report_from_guest(vcpu); + + /* Wait for guest to report either ecx value or error */ + tdx_run(vcpu); + ecx =3D tdx_test_read_report_from_guest(vcpu); + + /* Wait for guest to complete execution */ + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + /* Verify the CPUID values received from the guest. */ + printf("\t ... Verifying CPUID values from guest\n"); + + /* Get KVM CPUIDs for reference */ + cpuid_entry =3D vcpu_get_cpuid_entry(vcpu, 1); + TEST_ASSERT(cpuid_entry, "CPUID entry missing\n"); + + host_max_addressable_ids =3D (cpuid_entry->ebx >> 16) & 0xFF; + + guest_sse3_enabled =3D ecx & 0x1; // Native + guest_clflush_line_size =3D (ebx >> 8) & 0xFF; // Fixed + guest_max_addressable_ids =3D (ebx >> 16) & 0xFF; // As Configured + guest_fma_enabled =3D (ecx >> 12) & 0x1; // As Configured (if Native) + guest_initial_apic_id =3D (ebx >> 24) & 0xFF; // Calculated + + TEST_ASSERT_EQ(guest_sse3_enabled, 1); + TEST_ASSERT_EQ(guest_clflush_line_size, 8); + TEST_ASSERT_EQ(guest_max_addressable_ids, host_max_addressable_ids); + + /* TODO: This only tests the native value. To properly test + * "As Configured (if Native)" this value needs override in the + * TD params. + */ + TEST_ASSERT_EQ(guest_fma_enabled, (cpuid_entry->ecx >> 12) & 0x1); + + /* TODO: guest_initial_apic_id is calculated based on the number of + * vCPUs in the TD. From the spec: "Virtual CPU index, starting from 0 + * and allocated sequentially on each successful TDH.VP.INIT" + * To test non-trivial values either use a TD with multiple vCPUs + * or pick a different calculated value. + */ + TEST_ASSERT_EQ(guest_initial_apic_id, 0); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -153,13 +247,15 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(3); + ksft_set_plan(4); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), "verify_report_fatal_error\n"); ksft_test_result(!run_in_new_process(&verify_td_ioexit), "verify_td_ioexit\n"); + ksft_test_result(!run_in_new_process(&verify_td_cpuid), + "verify_td_cpuid\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (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 B3CB5277023 for ; Thu, 7 Aug 2025 20:16:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597820; cv=none; b=n22YC8QkQtD5o7WZj+qSD4V9SHv3X9/Gny67RTTQlUaZtXBWFTORUsP1hcHv1mO2T6ldqG/vIjK7rEh4faUaaG6xFUEse8cQRx5IXsjqZjv8T4pKEf17FmuZM/RVFjcMrmytjg19WfgUDFXFmJ0iK6WyB09JTsXtYI5oM6gF6y4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597820; c=relaxed/simple; bh=mGbx7ziQJOwyU5DksuV+htsFBGLstu5vkoVMf0ClHvc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=c9yRrrDA/JCb8MO7kSC1UtZGziHgvjANI3yzNcdADhsLwuMKeefSCjMFOQwSrzeuUe3pAu8kkTjonaKZdYOjWOnc+gzYc/KwxQvtWsAkAuCco5yyvutUqAIccix1YDZfq6ynCZCJM66pBm32/85IsDhcJfUQG3eBWBMBkQGFXZI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=fB76iWGx; arc=none smtp.client-ip=209.85.214.202 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="fB76iWGx" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-242a1390e9eso27734345ad.2 for ; Thu, 07 Aug 2025 13:16:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597818; x=1755202618; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=d1nyrOuLk05O6GNAKLishkQlt5G5F0xL/CtyJP3+mTQ=; b=fB76iWGxmnzp4SmjGZMVNDvDExux5Dg4hxcg5irVRZVeMfFzGkZ6soXW9t4I6h93b3 fvI8KTNSmzNzsG/2ObbMA60ZEfEB0n3z2iG6NkbwqlX5iNhgyK5+4zBvngqycTvyNCZX RWaCz9BeBGo4dCUSQ/tM/K6N6ZyDkD59rYQ7wb0mBqQIThAniwfBfmn5QWBcGQr0RgPn pQNgWuduvuHCiDYPTzW4EHiIukrlwGrCu3nlGmjedXJ39b95Ib8s30HLsCY+YrENCYQf 8mS5yyZMx8otRAo/1gcCgBx6Z0ZeTxaZdy84B2EmqhOrsmhxZEcN7bRBgvPIMCH9JuwN /cLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597818; x=1755202618; h=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; bh=d1nyrOuLk05O6GNAKLishkQlt5G5F0xL/CtyJP3+mTQ=; b=GcFwDhvA7oIzHttxeVyK9MO+fuRUPvvPbUkS+zYozhgCMgGIXQBh9ZAOrc0Ki1xUjc M8AIAlq1mfznGkg7SywS32qMoPakg5WSAh/lBT/FpGJELehJCRAvRtrD6q7Kqw+unc7Q G2VMgLK0b84ofZpuOxnsP9ipDyHxrt+RvePPn/5BRQItZz6akmMwVBLubF/CR17dEMnp Qu7aztiS+P4LsemeIcwRwPCaWnrxFb3Q3aU9nkUqwR2sJZR7dVVoVp5pj1EnD52cs5k2 fYecKXDWi0yVYW8H+nxbmVxJONmq6gnjTbMZbXDwn26w7udrg+QuPrlv+wT9ylq07wAK svNA== X-Gm-Message-State: AOJu0YyP9rDArBh+9Ph+39EzT9J7tzv2Bzd4tvZCjGimmN7myJkoNBhZ mQxezv9LzFg7dNaVea74LlPJK6TT1uTsarjIbfsOXNDMToSbvD1oLf+w7mirNAoMRraH1cNJ5Qe a8w== X-Google-Smtp-Source: AGHT+IFkx9VRn9WrtpwgFH8Korjpu/Pc/cbeI94UMhnq4S2UnuNwb22nTJrWWM/C0AG5MD6MlcRS0NYoFQ== X-Received: from pjbpw8.prod.google.com ([2002:a17:90b:2788:b0:31e:a49a:f4dd]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:f605:b0:240:38f8:ed05 with SMTP id d9443c01a7336-242c21dce69mr4372965ad.36.1754597817513; Thu, 07 Aug 2025 13:16:57 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:09 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-14-sagis@google.com> Subject: [PATCH v8 13/30] KVM: selftests: TDX: Add basic TDG.VP.VMCALL test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The test calls TDG.VP.VMCALL hypercall from the guest and verifies the expected returned values. TDG.VP.VMCALL hypercall is a subleaf of TDG.VP.VMCALL to enumerate which TDG.VP.VMCALL sub leaves are supported. This hypercall is for future enhancement of the Guest-Host-Communication Interface (GHCI) specification. The GHCI version of 344426-001US defines it to require input R12 to be zero and to return zero in output registers, R11, R12, R13, and R14 so that guest TD enumerates no enhancement. Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/tdx.h | 3 + .../selftests/kvm/include/x86/tdx/test_util.h | 27 +++++++ tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 23 ++++++ .../selftests/kvm/lib/x86/tdx/test_util.c | 42 +++++++++++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 72 ++++++++++++++++++- 5 files changed, 166 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index 2acccc9dccf9..97ceb90c8792 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -6,6 +6,7 @@ =20 #include "kvm_util.h" =20 +#define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 =20 #define TDG_VP_VMCALL_INSTRUCTION_IO 30 @@ -13,4 +14,6 @@ uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, uint64_t write, uint64_t *data); void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_g= pa); +uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12, + uint64_t *r13, uint64_t *r14); #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h b/tool= s/testing/selftests/kvm/include/x86/tdx/test_util.h index 2af6e810ef78..91031e956462 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/test_util.h @@ -4,6 +4,7 @@ =20 #include =20 +#include "kvm_util.h" #include "tdcall.h" =20 #define TDX_TEST_SUCCESS_PORT 0x30 @@ -92,4 +93,30 @@ uint64_t tdx_test_report_to_user_space(uint32_t data); */ uint32_t tdx_test_read_report_from_guest(struct kvm_vcpu *vcpu); =20 +/* + * Report a 64 bit value from the guest to user space using TDG.VP.VMCALL + * call. + * + * Data is sent to host in 2 calls. LSB is sent (and needs to be read) fir= st. + */ +uint64_t tdx_test_send_64bit(uint64_t port, uint64_t data); + +/* + * Report a 64 bit value from the guest to user space using TDG.VP.VMCALL + * call. Data is reported on port TDX_TEST_REPORT_PORT. + */ +uint64_t tdx_test_report_64bit_to_user_space(uint64_t data); + +/* + * Read a 64 bit value from the guest in user space, sent using + * tdx_test_send_64bit(). + */ +uint64_t tdx_test_read_64bit(struct kvm_vcpu *vcpu, uint64_t port); + +/* + * Read a 64 bit value from the guest in user space, sent using + * tdx_test_report_64bit_to_user_space(). + */ +uint64_t tdx_test_read_64bit_report_from_guest(struct kvm_vcpu *vcpu); + #endif // SELFTEST_TDX_TEST_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index ba088bfc1e62..5105dfae0e9e 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -43,3 +43,26 @@ void tdg_vp_vmcall_report_fatal_error(uint64_t error_cod= e, uint64_t data_gpa) =20 __tdx_hypercall(&args, 0); } + +uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12, + uint64_t *r13, uint64_t *r14) +{ + struct tdx_hypercall_args args =3D { + .r11 =3D TDG_VP_VMCALL_GET_TD_VM_CALL_INFO, + .r12 =3D 0, + }; + uint64_t ret; + + ret =3D __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (r11) + *r11 =3D args.r11; + if (r12) + *r12 =3D args.r12; + if (r13) + *r13 =3D args.r13; + if (r14) + *r14 =3D args.r14; + + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c b/tools/te= sting/selftests/kvm/lib/x86/tdx/test_util.c index f9bde114a8bc..8c3b6802c37e 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c @@ -7,6 +7,7 @@ #include =20 #include "kvm_util.h" +#include "tdx/tdcall.h" #include "tdx/tdx.h" #include "tdx/tdx_util.h" #include "tdx/test_util.h" @@ -124,3 +125,44 @@ uint32_t tdx_test_read_report_from_guest(struct kvm_vc= pu *vcpu) =20 return res; } + +uint64_t tdx_test_send_64bit(uint64_t port, uint64_t data) +{ + uint64_t data_hi =3D (data >> 32) & 0xFFFFFFFF; + uint64_t data_lo =3D data & 0xFFFFFFFF; + uint64_t err; + + err =3D tdg_vp_vmcall_instruction_io(port, 4, PORT_WRITE, &data_lo); + if (err) + return err; + + return tdg_vp_vmcall_instruction_io(port, 4, PORT_WRITE, &data_hi); +} + +uint64_t tdx_test_report_64bit_to_user_space(uint64_t data) +{ + return tdx_test_send_64bit(TDX_TEST_REPORT_PORT, data); +} + +uint64_t tdx_test_read_64bit(struct kvm_vcpu *vcpu, uint64_t port) +{ + uint32_t lo, hi; + uint64_t res; + + tdx_test_assert_io(vcpu, port, 4, PORT_WRITE); + lo =3D *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + vcpu_run(vcpu); + + tdx_test_assert_io(vcpu, port, 4, PORT_WRITE); + hi =3D *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + res =3D hi; + res =3D (res << 32) | lo; + return res; +} + +uint64_t tdx_test_read_64bit_report_from_guest(struct kvm_vcpu *vcpu) +{ + return tdx_test_read_64bit(vcpu, TDX_TEST_REPORT_PORT); +} diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index bbdcca358d71..22143d16e0d1 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -240,6 +240,74 @@ void verify_td_cpuid(void) printf("\t ... PASSED\n"); } =20 +/* + * Verifies TDG.VP.VMCALL hypercall functionality. + */ +void guest_code_get_td_vmcall_info(void) +{ + uint64_t r11, r12, r13, r14; + uint64_t err; + + err =3D tdg_vp_vmcall_get_td_vmcall_info(&r11, &r12, &r13, &r14); + tdx_assert_error(err); + + err =3D tdx_test_report_64bit_to_user_space(r11); + tdx_assert_error(err); + + err =3D tdx_test_report_64bit_to_user_space(r12); + tdx_assert_error(err); + + err =3D tdx_test_report_64bit_to_user_space(r13); + tdx_assert_error(err); + + err =3D tdx_test_report_64bit_to_user_space(r14); + tdx_assert_error(err); + + tdx_test_success(); +} + +void verify_get_td_vmcall_info(void) +{ + uint64_t r11, r12, r13, r14; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_code_get_td_vmcall_info); + td_finalize(vm); + + printf("Verifying TD get vmcall info:\n"); + + /* Wait for guest to report r11 value */ + tdx_run(vcpu); + r11 =3D tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r12 value */ + tdx_run(vcpu); + r12 =3D tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r13 value */ + tdx_run(vcpu); + r13 =3D tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r14 value */ + tdx_run(vcpu); + r14 =3D tdx_test_read_64bit_report_from_guest(vcpu); + + TEST_ASSERT_EQ(r11, 0); + TEST_ASSERT_EQ(r12, 0); + TEST_ASSERT_EQ(r13, 0); + TEST_ASSERT_EQ(r14, 0); + + /* Wait for guest to complete execution */ + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -247,7 +315,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(4); + ksft_set_plan(5); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -256,6 +324,8 @@ int main(int argc, char **argv) "verify_td_ioexit\n"); ksft_test_result(!run_in_new_process(&verify_td_cpuid), "verify_td_cpuid\n"); + ksft_test_result(!run_in_new_process(&verify_get_td_vmcall_info), + "verify_get_td_vmcall_info\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pg1-f202.google.com (mail-pg1-f202.google.com [209.85.215.202]) (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 C4260274FE5 for ; Thu, 7 Aug 2025 20:16:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597821; cv=none; b=BZ8woMCxhBYs9h5akD6aSFqLmmmwXqCYkxlqj1j3L5XzgnNfG5KsUKM5HeVdPGIR0W9Td86zirkSuHcLm1N4ye9CCzIRZFoI7GJouiXGltnxLfszsFHHO3PIU55qE2CS66BMLYyP5sjs1oWT/hVDshnpQVVcCEE8zlq5R5j5Y44= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597821; c=relaxed/simple; bh=FXDAADzMusIlbN7uUCnCYkOeFjIxbEHc+vE0DIROQ/Y=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=AOjLazwV0GpQwAMyZ2nn8JDmwn+5/e7Ss8geON1dQ+F60H8DrcQmg5h7Yaz78uI4f9XBeJ5KC6J7zADF5ZihFchVwoh+V80egFdt2V+QTQnHHtoCrgyQO3biI4tDavvH4wx05RSwp9IJHGNpAMGRWdZx3ayPrn4HnS4EhLPwH+0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=efOLIOlV; arc=none smtp.client-ip=209.85.215.202 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="efOLIOlV" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b4253124e77so1197706a12.2 for ; Thu, 07 Aug 2025 13:16:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597819; x=1755202619; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=opBjGbCpw5awd4Cotp1/0PR79/5V/O1FhnxLn+p7yqU=; b=efOLIOlVCj7m+gGYL+R9nGG03NoXaJjiqKoKeHv/3yk4A8n0PGIhs7Kc0GaEMj4lU1 nLFhOYiZ3H8Ekhg3Phggqjtr8ismctvuaYJ+W8sMpLCkKQWOR2KGgaefPXKQ2i9ABFrm k9BhV04ePEUENoo0+dxctVI+XqG7E7m8fRpfCuce5nZz83CoD42Z8EA4e9EZ1gnriRyd G1BxU8zR8H++fwGu9fChwoGq+y01Mjki1de+783LnfI1CMwzm1GQ9rCne75bZBAl+/Fd lX7xsaulKaWt3xbX4Bqt3xLMRsUjKJFbHviK5E1KfsbCA1hNJ7IlaccmKo6ndTHEvrdj mzIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597819; x=1755202619; h=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; bh=opBjGbCpw5awd4Cotp1/0PR79/5V/O1FhnxLn+p7yqU=; b=SmCuKqBmFpdX5y204Ui5dNBr8Cr47Hvx0bK6MeLMhl5q60l1EFRzZmP08R7U9iP+9u XwHpTEqPFB7MhOQYZOxZqpg7/RVJZP2nYtWjaYxnu5WK99mPbCTZQJJdQSiXNiLo8KJz Ss71qj6NUUfPG4DmD88ouAyyXdNB1/bmf4F/t0WlPYD2ujkNUnvtiXuRQCnQNNT9o4VU O7zo/9QTZJsxDIHRwgRlTx6XhCWdN01v3+Cv0YTPU/yKxNRFW7hvq8wKFoJ+xyOigT4n /w44r7dK8ZFskHpQt5FCaY9S3DJN8Y3RLqVHiwTJkZ+pIZKzStgy0cdQfM6APca4XXEo 5l0A== X-Gm-Message-State: AOJu0Yy4IiUOiIfLC9NhSoFeJmeLWXQ/rG00XCAdXS+qSzp14TlHN3tN +FeLFnx+6jSMia9+WqwLVUA3woq0kEtURiYRf3e4/Yozs5ZVWJjkt89j2qnIvgvTlCNzTK683Lq 42g== X-Google-Smtp-Source: AGHT+IFg9IMl11uY0VA/UeYt/Ymn5WDhQiYfRt4ouUB8jhAWey7rdPY7dxuMJ50BLvXQ8lFPaeBoEOoCiA== X-Received: from pgbdp12.prod.google.com ([2002:a05:6a02:f0c:b0:b42:306b:d8b]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:a121:b0:240:1a3a:d7ed with SMTP id adf61e73a8af0-24055200eb1mr348212637.41.1754597819059; Thu, 07 Aug 2025 13:16:59 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:10 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-15-sagis@google.com> Subject: [PATCH v8 14/30] KVM: selftests: TDX: Add TDX IO writes test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The test verifies IO writes of various sizes from the guest to the host. Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/tdcall.h | 3 + tools/testing/selftests/kvm/x86/tdx_vm_test.c | 79 ++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdcall.h b/tools/t= esting/selftests/kvm/include/x86/tdx/tdcall.h index a6c966e93486..e7440f7fe259 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdcall.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdcall.h @@ -7,6 +7,9 @@ #include #include =20 +#define TDG_VP_VMCALL_SUCCESS 0x0000000000000000 +#define TDG_VP_VMCALL_INVALID_OPERAND 0x8000000000000000 + #define TDX_HCALL_HAS_OUTPUT BIT(0) =20 #define TDX_HYPERCALL_STANDARD 0 diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index 22143d16e0d1..f646da032004 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -308,6 +308,81 @@ void verify_get_td_vmcall_info(void) printf("\t ... PASSED\n"); } =20 +#define TDX_IO_WRITES_TEST_PORT 0x51 + +/* + * Verifies IO functionality by writing values of different sizes + * to the host. + */ +void guest_io_writes(void) +{ + uint64_t byte_4 =3D 0xFFABCDEF; + uint64_t byte_2 =3D 0xABCD; + uint64_t byte_1 =3D 0xAB; + uint64_t ret; + + ret =3D tdg_vp_vmcall_instruction_io(TDX_IO_WRITES_TEST_PORT, 1, + PORT_WRITE, &byte_1); + tdx_assert_error(ret); + + ret =3D tdg_vp_vmcall_instruction_io(TDX_IO_WRITES_TEST_PORT, 2, + PORT_WRITE, &byte_2); + tdx_assert_error(ret); + + ret =3D tdg_vp_vmcall_instruction_io(TDX_IO_WRITES_TEST_PORT, 4, + PORT_WRITE, &byte_4); + tdx_assert_error(ret); + + /* Write an invalid number of bytes. */ + ret =3D tdg_vp_vmcall_instruction_io(TDX_IO_WRITES_TEST_PORT, 5, + PORT_WRITE, &byte_4); + tdx_assert_error(ret); + + tdx_test_success(); +} + +void verify_guest_writes(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + uint32_t byte_4; + uint16_t byte_2; + uint8_t byte_1; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_io_writes); + td_finalize(vm); + + printf("Verifying guest writes:\n"); + + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_IO_WRITES_TEST_PORT, 1, PORT_WRITE); + byte_1 =3D *(uint8_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_IO_WRITES_TEST_PORT, 2, PORT_WRITE); + byte_2 =3D *(uint16_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_IO_WRITES_TEST_PORT, 4, PORT_WRITE); + byte_4 =3D *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + TEST_ASSERT_EQ(byte_1, 0xAB); + TEST_ASSERT_EQ(byte_2, 0xABCD); + TEST_ASSERT_EQ(byte_4, 0xFFABCDEF); + + td_vcpu_run(vcpu); + TEST_ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYSTEM_EVENT); + TEST_ASSERT_EQ(vcpu->run->system_event.data[12], TDG_VP_VMCALL_INVALID_OP= ERAND); + + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -315,7 +390,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(5); + ksft_set_plan(6); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -326,6 +401,8 @@ int main(int argc, char **argv) "verify_td_cpuid\n"); ksft_test_result(!run_in_new_process(&verify_get_td_vmcall_info), "verify_get_td_vmcall_info\n"); + ksft_test_result(!run_in_new_process(&verify_guest_writes), + "verify_guest_writes\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 2B4F6277815 for ; Thu, 7 Aug 2025 20:17:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597823; cv=none; b=VApZ5+dYs7HRu8g4ITMGr0YD7Y8zBDJqjENpcO0yGzwe1Vx/+LR34D8e/S2lM8Ut0gVuznGSJ5SYBsW4ky2yxFlW6VZWW2at2LjezzSu9HDJOBAZcPdnzAjdbaEL1r+NQBi3zSqwqFvz4+LxD6puNKCNlravT8WmomNl1wvuYlU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597823; c=relaxed/simple; bh=7uQDUuX2od2zF/xx4v0GXRq5KY5yDJtCLQKM9+Jz1zM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=KaBNRZEZ8G3nSsORInQPXZae2X7LUIeP1rLRx27Ch6dtPFz374+IVHZhA4i06SytZmBB5/ke+KD63ed6RoNqBhdMpl3CPC+Xy9Wl6aqERkL1J03LY2gG4eNhNFTjeDXrPM2igtxUd2rOoxOmctI4nM7LcWVBEC1CVNWpAO2f5kc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=WvWzZ3fx; arc=none smtp.client-ip=209.85.216.73 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="WvWzZ3fx" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-3217aae3f90so959455a91.0 for ; Thu, 07 Aug 2025 13:17:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597820; x=1755202620; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=1xRcgcnY/7ITEoTgDsYsxXeksg15Fub5z9He1VHjXy8=; b=WvWzZ3fx96zkGt3NZFlJB1BOc9sBeOsJPeEaZzpjNrX3Oi7E7Dt50dVu4ohP1bjHjY SoIxRieAXD+oV0JIHrW0GTEFboKzfELPFd+evpgF/Cu6sU2RmYv03Y/95G4oyT5lwpYP wwh8YiE/sL6u7C4YxiEIHmlFVHCfVaHPeIJlSC/7Vp8i0nfssyqFhlxoCSxRaTlTuINU QlxTfntasNyIP4kPqBRXMlDn5S2xvLZJHyh72Uon5sy9qAPC8CjqqRNe2L6OFHlEL5V1 kOi38zeVJQ+TMa5thJcPkuQPoEQgHLJ3lKXF0bLlHRUWE95X8d7c8I2TodChJqrmaSPu KQ3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597820; x=1755202620; h=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; bh=1xRcgcnY/7ITEoTgDsYsxXeksg15Fub5z9He1VHjXy8=; b=q65WOVWvtB0J3xw11sKA1NcmlR1PWUYfpS+GJx0EfzawB5+BwlTi0lgACHqZusYHTD TKbL8dzctrQ6W0dDV+3HWHak1j3mgvZeKKEawQeC5VyOsqeX043M/+Qdf3qqkF/P1//q nwAEEc+n48BlbAhNILMyLZDMt7qZwk4lIvkFkGaO+Hm4jGibIiKi/eglWGkSSOxSKXBy cT7QJVp63/B8v7xtLExu311tGrp8ySM4j98cBEPU5AYIMNan8wDEUYg6wAdXX0EYr3Ds X3mDt3U11anPxtBfEITV9vfQUUxLFpT2d3FvZcwWIGZ2b1/Y4n4/py+BtunUzZT46wCa V0TA== X-Gm-Message-State: AOJu0YxHep+hKfli7oda+99OjYflJlA0hUbcNpXQyBuaUv0oTb3t/aZl nIbcyguAF0rXdolbcC7jXdC1Ef9DGKzC710iOwoLj0zlZ6D+vtityIuOPrZn/S8kKjFbXLinQdc Pug== X-Google-Smtp-Source: AGHT+IFCoZqmW5N9rtBu+azrFQx6VUYV75fQ2l8R4X8A051t1ZBw4o2UVRrTaky4Z8dlTuR8Yh4CSFgT4Q== X-Received: from pjbpx16.prod.google.com ([2002:a17:90b:2710:b0:2e0:915d:d594]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4b12:b0:315:aa28:9501 with SMTP id 98e67ed59e1d1-32183c467b7mr474796a91.24.1754597820397; Thu, 07 Aug 2025 13:17:00 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:11 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-16-sagis@google.com> Subject: [PATCH v8 15/30] KVM: selftests: TDX: Add TDX IO reads test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The test verifies IO reads of various sizes from the host to the guest. Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/x86/tdx_vm_test.c | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index f646da032004..ae5749e5c605 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -383,6 +383,78 @@ void verify_guest_writes(void) printf("\t ... PASSED\n"); } =20 +#define TDX_IO_READS_TEST_PORT 0x52 + +/* + * Verifies IO functionality by reading values of different sizes + * from the host. + */ +void guest_io_reads(void) +{ + uint64_t data; + uint64_t ret; + + ret =3D tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 1, + PORT_READ, &data); + tdx_assert_error(ret); + if (data !=3D 0xAB) + tdx_test_fatal(1); + + ret =3D tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 2, + PORT_READ, &data); + tdx_assert_error(ret); + if (data !=3D 0xABCD) + tdx_test_fatal(2); + + ret =3D tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 4, + PORT_READ, &data); + tdx_assert_error(ret); + if (data !=3D 0xFFABCDEF) + tdx_test_fatal(4); + + /* Read an invalid number of bytes. */ + ret =3D tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 5, + PORT_READ, &data); + tdx_assert_error(ret); + + tdx_test_success(); +} + +void verify_guest_reads(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_io_reads); + td_finalize(vm); + + printf("Verifying guest reads:\n"); + + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_IO_READS_TEST_PORT, 1, PORT_READ); + *(uint8_t *)((void *)vcpu->run + vcpu->run->io.data_offset) =3D 0xAB; + + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_IO_READS_TEST_PORT, 2, PORT_READ); + *(uint16_t *)((void *)vcpu->run + vcpu->run->io.data_offset) =3D 0xABCD; + + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_IO_READS_TEST_PORT, 4, PORT_READ); + *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset) =3D 0xFFABCD= EF; + + td_vcpu_run(vcpu); + TEST_ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYSTEM_EVENT); + TEST_ASSERT_EQ(vcpu->run->system_event.data[12], TDG_VP_VMCALL_INVALID_OP= ERAND); + + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -390,7 +462,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(6); + ksft_set_plan(7); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -403,6 +475,8 @@ int main(int argc, char **argv) "verify_get_td_vmcall_info\n"); ksft_test_result(!run_in_new_process(&verify_guest_writes), "verify_guest_writes\n"); + ksft_test_result(!run_in_new_process(&verify_guest_reads), + "verify_guest_reads\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (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 7CB99278E7C for ; Thu, 7 Aug 2025 20:17:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597824; cv=none; b=OgIu3TkWBUsAu7PfeKNw4LD7fqjhA5z03OZzYNRefZjOTckTLyGDdTAnhEHlMU7IxVOCesTg0fWv/z0501ARhJDAvWaGr0iaXrkB+37qVcvUOncBIynSalMaxxxdp42RVaTOht7AMFOvON5cKwIm+XvtNIwAKkghSZJ9L3poEjk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597824; c=relaxed/simple; bh=mgieOFUSYa7cCcBHiMCkot7ZE759Q2zKk6cM14CkOtw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Sq1avWFwKiviiDPfrNtw670+UT3i5+SV3lJ/jUpqUSctHG1zUfkaBNjrdXrCyUSMtPGpPylj6mYJMumQu2hp3URMpDSErmvtdzOhNYQ4RVrtpfZDJCNCgaryYGhah+MD/owy/0Yz4v89MRFFzRxxDNOEjLdXOu4WC+OgknFM0lw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=X4EdfTbp; arc=none smtp.client-ip=209.85.210.201 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="X4EdfTbp" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-76be6f0bbfdso843169b3a.2 for ; Thu, 07 Aug 2025 13:17:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597822; x=1755202622; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=j0LkjNICrNMaEHIQPUz5pGQXMjCUxxwu1qIsBHlM+qg=; b=X4EdfTbpsIi96/MmD/xD1I030tMsf7MR1KP+TKLsa1HXNYVPSTB5RkF94bmlzdHPbR MAlPYa1ot11XRT/pOnRtDFavH5lcqva5k7OXuZtOj21i+PYFPJgrNl/ImSlripD/cSJZ jsU1NiOLkVasxjMnYmdDUrFVvtfKwKNF4rBlnNdhtMs+vbViAaoSY4Y7DIun2K7HYhTw wj66G8qPI8SmJxKRgQ2Rkexu6UFYKyHel6OR/HQ71xr/GXZCInY6xm6rP0nrI/jxjSbE MfqYT9chA4TFwTxXQiJ5k67+kRw0P+er+RbK3Q7xONEdNfs14kbzSS2q/gI5iXDEyKAF cWYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597822; x=1755202622; h=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; bh=j0LkjNICrNMaEHIQPUz5pGQXMjCUxxwu1qIsBHlM+qg=; b=e5k4apBmjpwWZ863pAhTuKeKIpfTZDTh1wW2d03SpMTMbC61es37NB5CuN90VISw4s TJguM3pc+a+y0QVyqTlzpdNe513zoVGuWbwKJ+H0PmR+7oRZxAFBXAExwSpJlF+OSHo5 Za13HnHAvmzp+t9gJWIq3tSyFCq0k1hNsFdEHFg6Vkh2Gg62ZGvlJU4cE6+pet1Waswa kEndPLoDKTuC13nJCk6pBGrLM9wN+RDCTE1PXQy/HIDz/cooUprt49ZAKka3P9HbAxwk RgrUrRng/8WJPfefdE64qzUfBOczpu47QXTk/+fvTQUMIsFl9oaMpixiGjQTrhO0Qxzt 0jeg== X-Gm-Message-State: AOJu0YzXc+jX6OHYwvX2lC1txl8VWV/0qeHjOTBMPJf7bz+n+nenUe9J S3oHHcdZOcGOyTBlyPvPsKufiMc+GIQYTuho6UkwWH+CJNmTz0Pwpyk3gHomV6d2NFH3tzJ+xVp Csg== X-Google-Smtp-Source: AGHT+IHhxS2zq041/Rym1xe07wJU9Lm4/VTiXhKQTNb2lDWMIb1B0MXF3TLhCG9iExoGsWogGD5zoEjvNA== X-Received: from pgbds10.prod.google.com ([2002:a05:6a02:430a:b0:b42:38ba:fe24]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:6a25:b0:238:351a:6442 with SMTP id adf61e73a8af0-2405522ee22mr314041637.45.1754597821959; Thu, 07 Aug 2025 13:17:01 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:12 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-17-sagis@google.com> Subject: [PATCH v8 16/30] KVM: selftests: TDX: Add TDX MSR read/write tests From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The test verifies reads and writes for MSR registers with different access level. Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/tdx.h | 4 + tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 27 +++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 193 +++++++++++++++++- 3 files changed, 223 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index 97ceb90c8792..56359a8c4c19 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -10,10 +10,14 @@ #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 =20 #define TDG_VP_VMCALL_INSTRUCTION_IO 30 +#define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31 +#define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32 =20 uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, uint64_t write, uint64_t *data); void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_g= pa); uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12, uint64_t *r13, uint64_t *r14); +uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t *ret_val= ue); +uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value); #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index 5105dfae0e9e..99ec45a5a657 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -66,3 +66,30 @@ uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11,= uint64_t *r12, =20 return ret; } + +uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t *ret_val= ue) +{ + struct tdx_hypercall_args args =3D { + .r11 =3D TDG_VP_VMCALL_INSTRUCTION_RDMSR, + .r12 =3D index, + }; + uint64_t ret; + + ret =3D __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (ret_value) + *ret_value =3D args.r11; + + return ret; +} + +uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value) +{ + struct tdx_hypercall_args args =3D { + .r11 =3D TDG_VP_VMCALL_INSTRUCTION_WRMSR, + .r12 =3D index, + .r13 =3D value, + }; + + return __tdx_hypercall(&args, 0); +} diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index ae5749e5c605..079ac266a44e 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -455,6 +455,193 @@ void verify_guest_reads(void) printf("\t ... PASSED\n"); } =20 +/* + * Define a filter which denies all MSR access except the following: + * MSR_X2APIC_APIC_ICR: Allow read/write access (allowed by default) + * MSR_IA32_MISC_ENABLE: Allow read access + * MSR_IA32_POWER_CTL: Allow write access + */ +#define MSR_X2APIC_APIC_ICR 0x830 +static u64 tdx_msr_test_allow_bits =3D ~0ULL; +struct kvm_msr_filter tdx_msr_test_filter =3D { + .flags =3D KVM_MSR_FILTER_DEFAULT_DENY, + .ranges =3D { + { + .flags =3D KVM_MSR_FILTER_READ, + .nmsrs =3D 1, + .base =3D MSR_IA32_MISC_ENABLE, + .bitmap =3D (uint8_t *)&tdx_msr_test_allow_bits, + }, { + .flags =3D KVM_MSR_FILTER_WRITE, + .nmsrs =3D 1, + .base =3D MSR_IA32_POWER_CTL, + .bitmap =3D (uint8_t *)&tdx_msr_test_allow_bits, + }, + }, +}; + +/* + * Verifies MSR read functionality. + */ +void guest_msr_read(void) +{ + uint64_t data; + uint64_t ret; + + ret =3D tdg_vp_vmcall_instruction_rdmsr(MSR_X2APIC_APIC_ICR, &data); + tdx_assert_error(ret); + + ret =3D tdx_test_report_64bit_to_user_space(data); + tdx_assert_error(ret); + + ret =3D tdg_vp_vmcall_instruction_rdmsr(MSR_IA32_MISC_ENABLE, &data); + tdx_assert_error(ret); + + ret =3D tdx_test_report_64bit_to_user_space(data); + tdx_assert_error(ret); + + /* Expect this call to fail since MSR_IA32_POWER_CTL is write only */ + ret =3D tdg_vp_vmcall_instruction_rdmsr(MSR_IA32_POWER_CTL, &data); + if (ret) { + ret =3D tdx_test_report_64bit_to_user_space(ret); + tdx_assert_error(ret); + } else { + tdx_test_fatal(-99); + } + + tdx_test_success(); +} + +void verify_guest_msr_reads(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + uint64_t data; + int ret; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + + /* + * Set explicit MSR filter map to control access to the MSR registers + * used in the test. + */ + printf("\t ... Setting test MSR filter\n"); + ret =3D kvm_check_cap(KVM_CAP_X86_MSR_FILTER); + TEST_ASSERT(ret, "KVM_CAP_X86_MSR_FILTER is unavailable"); + + ret =3D ioctl(vm->fd, KVM_X86_SET_MSR_FILTER, &tdx_msr_test_filter); + TEST_ASSERT(ret =3D=3D 0, + "KVM_X86_SET_MSR_FILTER failed, ret: %i errno: %i (%s)", + ret, errno, strerror(errno)); + + vcpu =3D td_vcpu_add(vm, 0, guest_msr_read); + td_finalize(vm); + + printf("Verifying guest msr reads:\n"); + + printf("\t ... Setting test MSR values\n"); + /* Write arbitrary to the MSRs. */ + vcpu_set_msr(vcpu, MSR_X2APIC_APIC_ICR, 4); + vcpu_set_msr(vcpu, MSR_IA32_MISC_ENABLE, 5); + vcpu_set_msr(vcpu, MSR_IA32_POWER_CTL, 6); + + printf("\t ... Running guest\n"); + tdx_run(vcpu); + data =3D tdx_test_read_64bit_report_from_guest(vcpu); + TEST_ASSERT_EQ(data, 4); + + tdx_run(vcpu); + data =3D tdx_test_read_64bit_report_from_guest(vcpu); + TEST_ASSERT_EQ(data, 5); + + tdx_run(vcpu); + data =3D tdx_test_read_64bit_report_from_guest(vcpu); + TEST_ASSERT_EQ(data, TDG_VP_VMCALL_INVALID_OPERAND); + + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + +/* + * Verifies MSR write functionality. + */ +void guest_msr_write(void) +{ + uint64_t ret; + + ret =3D tdg_vp_vmcall_instruction_wrmsr(MSR_X2APIC_APIC_ICR, 4); + tdx_assert_error(ret); + + /* Expect this call to fail since MSR_IA32_MISC_ENABLE is read only */ + ret =3D tdg_vp_vmcall_instruction_wrmsr(MSR_IA32_MISC_ENABLE, 5); + if (ret) { + ret =3D tdx_test_report_64bit_to_user_space(ret); + tdx_assert_error(ret); + } else { + tdx_test_fatal(-99); + } + + ret =3D tdg_vp_vmcall_instruction_wrmsr(MSR_IA32_POWER_CTL, 6); + tdx_assert_error(ret); + + tdx_test_success(); +} + +void verify_guest_msr_writes(void) +{ + uint64_t ia32_misc_enable_val; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + uint64_t data; + int ret; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + + /* + * Set explicit MSR filter map to control access to the MSR registers + * used in the test. + */ + printf("\t ... Setting test MSR filter\n"); + ret =3D kvm_check_cap(KVM_CAP_X86_MSR_FILTER); + TEST_ASSERT(ret, "KVM_CAP_X86_MSR_FILTER is unavailable"); + + ret =3D ioctl(vm->fd, KVM_X86_SET_MSR_FILTER, &tdx_msr_test_filter); + TEST_ASSERT(ret =3D=3D 0, + "KVM_X86_SET_MSR_FILTER failed, ret: %i errno: %i (%s)", + ret, errno, strerror(errno)); + + vcpu =3D td_vcpu_add(vm, 0, guest_msr_write); + td_finalize(vm); + + ia32_misc_enable_val =3D vcpu_get_msr(vcpu, MSR_IA32_MISC_ENABLE); + + printf("Verifying guest msr writes:\n"); + + printf("\t ... Running guest\n"); + /* Only the write to MSR_IA32_MISC_ENABLE should trigger an exit */ + tdx_run(vcpu); + data =3D tdx_test_read_64bit_report_from_guest(vcpu); + TEST_ASSERT_EQ(data, TDG_VP_VMCALL_INVALID_OPERAND); + + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + printf("\t ... Verifying MSR values written by guest\n"); + + TEST_ASSERT_EQ(vcpu_get_msr(vcpu, MSR_X2APIC_APIC_ICR), 4); + TEST_ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_MISC_ENABLE), + ia32_misc_enable_val); + TEST_ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_POWER_CTL), 6); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -462,7 +649,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(7); + ksft_set_plan(9); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -477,6 +664,10 @@ int main(int argc, char **argv) "verify_guest_writes\n"); ksft_test_result(!run_in_new_process(&verify_guest_reads), "verify_guest_reads\n"); + ksft_test_result(!run_in_new_process(&verify_guest_msr_writes), + "verify_guest_msr_writes\n"); + ksft_test_result(!run_in_new_process(&verify_guest_msr_reads), + "verify_guest_msr_reads\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (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 CEAFE27A460 for ; Thu, 7 Aug 2025 20:17:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597825; cv=none; b=TOkuqXwV1mkZQAU7jSLJ8Ai73Q3KmSfPNwbdNNBiA88pjBYYXzfENiaO4HmXZfk57IleWHyfDo58lpyYZrgBd7h0r5P48bJ5bRX5AWmV1imBTQ8S3VPyq2tNR/6ENMZ3PPirno7BWN2SUWzUEnTka4xk2jLPK+B3gJo5UcNSCa0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597825; c=relaxed/simple; bh=1lLJEQt553XarCyVGURP6/QnoZ2UebtBy96ceC/3gK8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=VK2sw09V607NJCVGRoHz9uToXwjtqN2Xru1MauQR1J9qPOEiUZLOxVPczf+JCxQtJxzI4pOmY7DkRJd+DjpNG3GK61Ywm3nKl/bvtPxt+x+OkUwRFe4VJOIwROsBdXLDQ7X7jtBGsZhHAInLd74/GEfRJLnQpMd/w5ebZcNooUk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=e3AVs2QC; arc=none smtp.client-ip=209.85.214.201 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="e3AVs2QC" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2425e41424cso16922495ad.1 for ; Thu, 07 Aug 2025 13:17:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597823; x=1755202623; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=fHXS+IMdX42x6FMeqA3gkQMVcireV7tMgGO8OV5Mnhw=; b=e3AVs2QCc9NnGFsBQYPSG2Akl7trxCTBwBcYRxpPLgXqSDAJDth5/pm8s+O9xwxJM3 fE1JfYtShwXfOyc8SLHQKn9WC6kEotQfyhZx3pWEeUXvrHX6z0LxJjWqASybeLMRjvVh 74AKk+1ss7gmrfRFrQ3sQMIuOMVzl6X/rj2r9oMvIwHMts4fWxueHjAjtY6EpayyYqYb 2yHtud1UxK5yhxzwRAd1N0BxUb5hZL0d6XRZaY5lEcfE5to4Ar9SKYaIFcpQlerjzJDz H7VfdMgPr/t37KiNjCwUX+EUrraWtt1N2aEj9Pmcw2C4zJJj4hy+cmx3KrfcSTPtBDOM HcjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597823; x=1755202623; h=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; bh=fHXS+IMdX42x6FMeqA3gkQMVcireV7tMgGO8OV5Mnhw=; b=MICd4YFCvP5ImihMl/Yi7ZesxvfKW3MOT1ixBVWqvXg8eMN+EAEXL5b0gPOH08uIOw VJwNfABi/HFZ/ot1RegZEP6Li99jtNrP6Alyg7fqVMCW85qVmVbwgbfON2OiAlx+F3IV p2tA74siv+ePARp1zHR3UNcaCRwj0D1ljVKms7SgWMRnIZm8QHq28krDNmzwXKiKEVME 6hMsHpTCa/l0CAbLKHmAtMPRUQe8yNmOQehuXMcuxZBg6eEH1Kl1umOAbumXE7hGSV5Z SgHt7sHYH7Ba/e+LK6Qn1fBajReV1Wcp59u+k34fTOvWv1qNeyvy/q8fP6KIg/jJaQPd iYMg== X-Gm-Message-State: AOJu0YwIx1ZDGGFn1iDYaDh061AozlnkdzFPhJgXUnOx8EoYHUI/qDYX GZ4ejAWIoX1bv+tZ741++1EhKCPcwsCVv39lPwlDDAieNzbrpGoGqbrnGpX6raTkaOGULd7CaiD d+w== X-Google-Smtp-Source: AGHT+IFqenLs+t/iiOJ8dl6m0BMR2FI1dhWrueWing11YrkV8I+u/puGCyRBZbK2SKvLUeG3O0QjlAxWLw== X-Received: from plbkh8.prod.google.com ([2002:a17:903:648:b0:240:1bbf:686b]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:19ce:b0:240:cd3e:d860 with SMTP id d9443c01a7336-242c220df9cmr4079385ad.41.1754597823307; Thu, 07 Aug 2025 13:17:03 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:13 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-18-sagis@google.com> Subject: [PATCH v8 17/30] KVM: selftests: TDX: Add TDX HLT exit test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Erdem Aktas The test verifies that the guest runs TDVMCALL and the guest vCPU enters to the halted state. Co-developed-by: Sagi Shahar Signed-off-by: Sagi Shahar Signed-off-by: Erdem Aktas Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/tdx.h | 2 + tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 10 +++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 81 ++++++++++++++++++- 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index 56359a8c4c19..b5831919a215 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -9,6 +9,7 @@ #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 =20 +#define TDG_VP_VMCALL_INSTRUCTION_HLT 12 #define TDG_VP_VMCALL_INSTRUCTION_IO 30 #define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31 #define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32 @@ -20,4 +21,5 @@ uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, = uint64_t *r12, uint64_t *r13, uint64_t *r14); uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t *ret_val= ue); uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value); +uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag); #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index 99ec45a5a657..e89ca727286e 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -93,3 +93,13 @@ uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index,= uint64_t value) =20 return __tdx_hypercall(&args, 0); } + +uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag) +{ + struct tdx_hypercall_args args =3D { + .r11 =3D TDG_VP_VMCALL_INSTRUCTION_HLT, + .r12 =3D interrupt_blocked_flag, + }; + + return __tdx_hypercall(&args, 0); +} diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index 079ac266a44e..720ef5e87071 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -642,6 +642,83 @@ void verify_guest_msr_writes(void) printf("\t ... PASSED\n"); } =20 +/* + * Verifies HLT functionality. + */ +void guest_hlt(void) +{ + uint64_t interrupt_blocked_flag; + uint64_t ret; + + interrupt_blocked_flag =3D 0; + ret =3D tdg_vp_vmcall_instruction_hlt(interrupt_blocked_flag); + tdx_assert_error(ret); + + tdx_test_success(); +} + +void _verify_guest_hlt(int signum); + +void wake_me(int interval) +{ + struct sigaction action; + + action.sa_handler =3D _verify_guest_hlt; + sigemptyset(&action.sa_mask); + action.sa_flags =3D 0; + + TEST_ASSERT(sigaction(SIGALRM, &action, NULL) =3D=3D 0, + "Could not set the alarm handler!"); + + alarm(interval); +} + +void _verify_guest_hlt(int signum) +{ + static struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + /* + * This function will also be called by SIGALRM handler to check the + * vCPU MP State. If vm has been initialized, then we are in the signal + * handler. Check the MP state and let the guest run again. + */ + if (vcpu) { + struct kvm_mp_state mp_state; + + vcpu_mp_state_get(vcpu, &mp_state); + TEST_ASSERT_EQ(mp_state.mp_state, KVM_MP_STATE_HALTED); + + /* Let the guest to run and finish the test.*/ + mp_state.mp_state =3D KVM_MP_STATE_RUNNABLE; + vcpu_mp_state_set(vcpu, &mp_state); + return; + } + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_hlt); + td_finalize(vm); + + printf("Verifying HLT:\n"); + + printf("\t ... Running guest\n"); + + /* Wait 1 second for guest to execute HLT */ + wake_me(1); + tdx_run(vcpu); + + tdx_test_assert_success(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + +void verify_guest_hlt(void) +{ + _verify_guest_hlt(0); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -649,7 +726,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(9); + ksft_set_plan(10); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -668,6 +745,8 @@ int main(int argc, char **argv) "verify_guest_msr_writes\n"); ksft_test_result(!run_in_new_process(&verify_guest_msr_reads), "verify_guest_msr_reads\n"); + ksft_test_result(!run_in_new_process(&verify_guest_hlt), + "verify_guest_hlt\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pg1-f201.google.com (mail-pg1-f201.google.com [209.85.215.201]) (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 65F2227B4F7 for ; Thu, 7 Aug 2025 20:17:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597827; cv=none; b=speYNykjS7ZkeN6gP0472wM3Ven93on9fpluJOtR//z/PArSX3dQjYIVT3xQggxGciK8IKJfE0DH+tUbb62Z1/APHDeP7JRRrPws8Hrrp6Ygwur9mrLJu74I18a+Smeby+iksKZXkMo73Pwr7XvsA7A+8f/XAkB1rCfIvyAMh98= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597827; c=relaxed/simple; bh=FMkCKSKRcFZpMNh9Q4IZQtr8MTE2KZEt29yOX29RxXc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=emlQd4xAILhOLxtpX+xGgNdJ2QUz5Ecm6XoWI0RcyKFBXKLQVMAkWDxy2OmkORQlCDHyOvXbjmN6lfxGgGcPgLwFVUyedaNwzSxky9bQDrlosH1qIYtLC0bqN4t3wbvZRlvp2qTDaK6rau/ySxFEE5Uk/+/h5Z/62+kwI5M9ZlM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=WhUUPjGr; arc=none smtp.client-ip=209.85.215.201 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="WhUUPjGr" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b42464016c3so1306674a12.2 for ; Thu, 07 Aug 2025 13:17:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597825; x=1755202625; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=IsLTirUbGG0My77t7cEfLYkbyyzIAN4Kfd6VyRL4I/U=; b=WhUUPjGrjUdnRJShX1M5UOsdsCW+4pITrOUxlJUfGBXND4cwnRCGEhOEc/cTJi2OR1 NvtRVKdRFaPy06y1lMuT35l+jMULtYyN2ElvP5p9OhQH66vgWbxgsuwypQRcjHySxpa/ KLlrXSOtsQR8KeWLjYkxEmGBOUUrgUuDEXHWHJHNXv0EjGsT7rwdtWYEtk6kEEsYYQsj syz0BMZPxnzZkMneopZt0s2PsJ0x5LmNDCNJYo/m8OrJ23UJnDzGlbjck1sFbKI5iEMc 0AZbhNSjw0AJ2oHJ2GHCpo7XItOPgtAMfuQQ1lxvavze/m7nqgsdcLrATYc0zEewxvDb sOtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597825; x=1755202625; h=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; bh=IsLTirUbGG0My77t7cEfLYkbyyzIAN4Kfd6VyRL4I/U=; b=GJaMmAQiS7eUtNPUtiusSlYFePuTR63g9k/6cHq2x57mHy6HKbhCrNSXI9kAERw/e2 hGmgYpE6viIsEgT/0F6S4Ta/JqwyezzDf++HiLAUkMbNAYonaPh/jDxF+TNjpZupNEuD wofZ2YP/MBoIwhKBvmManu5ppnFFBvJ59ysFTGSdizLz+3T1LKDgVhFs2ybk4K0Nl2bI wX/QbjSmIi1mujjeD2vAO7O8WcTDo5P3XiDefqlBISiqH+cFl8bVUHCOxZosCFfvrpny 0z/uCGqlchwhdP9u3zIgLY/0TwdSm6b4YrMK1W3dr/dleOEtIYpcpSjUcX7V87iXFuln 40FA== X-Gm-Message-State: AOJu0YzL4pu4mLxR7w2IOtLD2qHUiBFbLOv7qwPVdhmARcNs7XOE7zAm 6+VwKRltX/HVrfvKKc64Hq3epVQky+H8FouVfXEIFlu+86z1ieaJ3aKwhcF+w7g8hD4ie92H8BP 7zQ== X-Google-Smtp-Source: AGHT+IEy6HdocJrCpnlewHwLvbW820fcwP7ySk0EHJc3YqSOfGsDRzi8yyD5Xo/x97qQOjknevYhxEyStA== X-Received: from pjbso3.prod.google.com ([2002:a17:90b:1f83:b0:311:1a09:11ff]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:dace:b0:240:3e41:57bf with SMTP id d9443c01a7336-242c2003f68mr4699385ad.13.1754597824722; Thu, 07 Aug 2025 13:17:04 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:14 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-19-sagis@google.com> Subject: [PATCH v8 18/30] KVM: selftests: TDX: Add TDX MMIO reads test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The test verifies MMIO reads of various sizes from the host to the guest. Co-developed-by: Isaku Yamahata Signed-off-by: Isaku Yamahata Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/tdx.h | 4 + .../selftests/kvm/include/x86/tdx/tdx_util.h | 1 + .../selftests/kvm/include/x86/tdx/test_util.h | 11 +++ tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 20 +++++ .../selftests/kvm/lib/x86/tdx/test_util.c | 19 ++++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 89 ++++++++++++++++++- 6 files changed, 143 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index b5831919a215..fa0b24873a8f 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -13,6 +13,7 @@ #define TDG_VP_VMCALL_INSTRUCTION_IO 30 #define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31 #define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32 +#define TDG_VP_VMCALL_VE_REQUEST_MMIO 48 =20 uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, uint64_t write, uint64_t *data); @@ -22,4 +23,7 @@ uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, = uint64_t *r12, uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t *ret_val= ue); uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value); uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag); +uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t siz= e, + uint64_t *data_out); + #endif // SELFTEST_TDX_TDX_H 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 d66cf17f03ea..c942aec7ad26 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h @@ -6,6 +6,7 @@ =20 #include "kvm_util.h" =20 +extern uint64_t tdx_s_bit; void tdx_filter_cpuid(struct kvm_vm *vm, struct kvm_cpuid2 *cpuid_data); void __tdx_mask_cpuid_features(struct kvm_cpuid_entry2 *entry); =20 diff --git a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h b/tool= s/testing/selftests/kvm/include/x86/tdx/test_util.h index 91031e956462..3330d5a54698 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/test_util.h @@ -17,6 +17,10 @@ #define PORT_READ 0 #define PORT_WRITE 1 =20 +/* MMIO direction */ +#define MMIO_READ 0 +#define MMIO_WRITE 1 + /* * Assert that some IO operation involving tdg_vp_vmcall_instruction_io() = was * called in the guest. @@ -24,6 +28,13 @@ void tdx_test_assert_io(struct kvm_vcpu *vcpu, uint16_t port, uint8_t size, uint8_t direction); =20 +/* + * Assert that some MMIO operation involving TDG.VP.VMCALL <#VERequestMMIO= > was + * called in the guest. + */ +void tdx_test_assert_mmio(struct kvm_vcpu *vcpu, uint64_t phys_addr, + uint32_t size, uint8_t is_write); + /* * Run the tdx vcpu and check if there was some failure in the guest, eith= er * an exception like a triple fault, or if a tdx_test_fatal() was hit. diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index e89ca727286e..8bf41e667fc1 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -4,6 +4,7 @@ =20 #include "tdx/tdcall.h" #include "tdx/tdx.h" +#include "tdx/test_util.h" =20 uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, uint64_t write, uint64_t *data) @@ -103,3 +104,22 @@ uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interr= upt_blocked_flag) =20 return __tdx_hypercall(&args, 0); } + +uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t siz= e, + uint64_t *data_out) +{ + struct tdx_hypercall_args args =3D { + .r11 =3D TDG_VP_VMCALL_VE_REQUEST_MMIO, + .r12 =3D size, + .r13 =3D MMIO_READ, + .r14 =3D address, + }; + uint64_t ret; + + ret =3D __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (data_out) + *data_out =3D args.r11; + + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c b/tools/te= sting/selftests/kvm/lib/x86/tdx/test_util.c index 8c3b6802c37e..f92ddda2d1ac 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c @@ -31,6 +31,25 @@ void tdx_test_assert_io(struct kvm_vcpu *vcpu, uint16_t = port, uint8_t size, vcpu->run->io.direction); } =20 +void tdx_test_assert_mmio(struct kvm_vcpu *vcpu, uint64_t phys_addr, + uint32_t size, uint8_t is_write) +{ + TEST_ASSERT(vcpu->run->exit_reason =3D=3D KVM_EXIT_MMIO, + "Got exit_reason other than KVM_EXIT_MMIO: %u (%s)\n", + vcpu->run->exit_reason, + exit_reason_str(vcpu->run->exit_reason)); + + TEST_ASSERT(vcpu->run->exit_reason =3D=3D KVM_EXIT_MMIO && + vcpu->run->mmio.phys_addr =3D=3D phys_addr && + vcpu->run->mmio.len =3D=3D size && + vcpu->run->mmio.is_write =3D=3D is_write, + "Got an unexpected MMIO exit values: %u (%s) %llu %u %u\n", + vcpu->run->exit_reason, + exit_reason_str(vcpu->run->exit_reason), + vcpu->run->mmio.phys_addr, vcpu->run->mmio.len, + vcpu->run->mmio.is_write); +} + void tdx_run(struct kvm_vcpu *vcpu) { td_vcpu_run(vcpu); diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index 720ef5e87071..563f1025c8a3 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -719,6 +719,91 @@ void verify_guest_hlt(void) _verify_guest_hlt(0); } =20 +/* Pick any address that was not mapped into the guest to test MMIO */ +#define TDX_MMIO_TEST_ADDR 0x200000000 +#define MMIO_SYNC_VALUE 0x42 + +void guest_mmio_reads(void) +{ + uint64_t mmio_test_addr =3D TDX_MMIO_TEST_ADDR | tdx_s_bit; + uint64_t data; + uint64_t ret; + + ret =3D tdg_vp_vmcall_ve_request_mmio_read(mmio_test_addr, 1, &data); + tdx_assert_error(ret); + if (data !=3D 0x12) + tdx_test_fatal(1); + + ret =3D tdg_vp_vmcall_ve_request_mmio_read(mmio_test_addr, 2, &data); + tdx_assert_error(ret); + if (data !=3D 0x1234) + tdx_test_fatal(2); + + ret =3D tdg_vp_vmcall_ve_request_mmio_read(mmio_test_addr, 4, &data); + tdx_assert_error(ret); + if (data !=3D 0x12345678) + tdx_test_fatal(4); + + ret =3D tdg_vp_vmcall_ve_request_mmio_read(mmio_test_addr, 8, &data); + tdx_assert_error(ret); + if (data !=3D 0x1234567890ABCDEF) + tdx_test_fatal(8); + + /* Make sure host and guest are synced to the same point of execution */ + tdx_test_report_to_user_space(MMIO_SYNC_VALUE); + + /* Read an invalid number of bytes. */ + ret =3D tdg_vp_vmcall_ve_request_mmio_read(mmio_test_addr, 10, &data); + tdx_assert_error(ret); + + tdx_test_success(); +} + +/* + * Verifies guest MMIO reads. + */ +void verify_mmio_reads(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_mmio_reads); + td_finalize(vm); + + printf("Verifying TD MMIO reads:\n"); + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 1, MMIO_READ); + *(uint8_t *)vcpu->run->mmio.data =3D 0x12; + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 2, MMIO_READ); + *(uint16_t *)vcpu->run->mmio.data =3D 0x1234; + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 4, MMIO_READ); + *(uint32_t *)vcpu->run->mmio.data =3D 0x12345678; + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 8, MMIO_READ); + *(uint64_t *)vcpu->run->mmio.data =3D 0x1234567890ABCDEF; + + tdx_run(vcpu); + TEST_ASSERT_EQ(tdx_test_read_report_from_guest(vcpu), MMIO_SYNC_VALUE); + + td_vcpu_run(vcpu); + TEST_ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYSTEM_EVENT); + TEST_ASSERT_EQ(vcpu->run->system_event.data[12], TDG_VP_VMCALL_INVALID_OP= ERAND); + + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -726,7 +811,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(10); + ksft_set_plan(11); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -747,6 +832,8 @@ int main(int argc, char **argv) "verify_guest_msr_reads\n"); ksft_test_result(!run_in_new_process(&verify_guest_hlt), "verify_guest_hlt\n"); + ksft_test_result(!run_in_new_process(&verify_mmio_reads), + "verify_mmio_reads\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (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 F213427CB38 for ; Thu, 7 Aug 2025 20:17:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597830; cv=none; b=S5KGay6UMUIMcnw18kceGzdDt2s+WhwOYEZJ359ojWbQHTpfrZyKjuU688thQ2DlhCpjwLZ1zdLozi+h/uC8q4ucU3U6Ts7MIzY20oWclOLF/Fc2qBhwlZBSZbdQNKUzxv4LWp3oHL5B7qZrnCpz9uwjI6b8R2fe5IuCxWJhxx0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597830; c=relaxed/simple; bh=NkZ9cw2OQkpKTyBr6XnTKZKOxHkmBwe+wNgxb8ukCTo=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=PCa6+BYatyeauzs5cpfOzaGx7yv5cbd85hrP1uw2Kc8g3FgGod3aIEYzGT3PiKD16XNcRMHk5sKzMhp9OgqiXLClmsVMXaaWzLJsHRknse+ukcnfrImwmc8mcD7jT5wr1xxFx1GVFmwN5AMllNyVjmqjybHjShANMIPeuU3HZ5E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=CIsxf155; arc=none smtp.client-ip=209.85.216.74 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="CIsxf155" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-31f4d0f60caso1435642a91.1 for ; Thu, 07 Aug 2025 13:17:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597826; x=1755202626; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=lGXEvvh28CILFU8veFYJPuuhWeDvdlK202GCjoHljc0=; b=CIsxf155Nn4ORlGN3obiaE94G2wj22Vnm3QOGfkzU+dflRorlXhpJj3o4NwdZnUoAI nE0jXotWm++qCYJk1ZzCFZ8hD7zWY4ugI5YNrC1nJgts5hkNij6JGj6U3DUzKpcEs6OW uEtnAW0fsLncJBl61evYtczbH+LIHqWKMhGQFBNg/Tohuo9mek5Lv+xml8bsSGZSZ+bp bbBeIjwZdNeoai28uLAY290UKIdFyaBIkNHwBemAT2bxpUHkqpRPGyJ4K+qMq5djtF50 0dgXkMYpoGJLN6tDAb4dh7NfZARWP8o0hmdrobGuRmO+ieHRaxLjR/EcoVomAsUviWnX Zlnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597826; x=1755202626; h=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; bh=lGXEvvh28CILFU8veFYJPuuhWeDvdlK202GCjoHljc0=; b=KLcZKMZly9X1pjifJhqJwCLQuC3QD8x0New+e8ZF/ejuNuha90CN9CobG9v2M8kmc9 200HpdebQGl/bTTmAzsLjgM1M07yc8PCaHAybh0h0C7ed8W2SfOrc3kWSsl0mQeuLix1 3ViyhitDTbWtPhZmM18t/Mx3XMPgM25+m3znUQvTienp4UmZJwS17jwhjt9a51m/Oazm bzjk+41Jujw4fo5sRZxg2KBNHfknMlHYDzOvbcCdig/AuXK3dfokZjYG4q1QbOCxOmmT k7UGqnZKPdehrzU6EMUqwhzzoLP5jVqSG8yayMni4wUDJLnXKwHiMXLzadjzft2kZ5j7 YJdQ== X-Gm-Message-State: AOJu0Ywin6n311pwIR2Lzb51RX+yY84Gz8VXHOC+9riqmIcCeE/2LYe6 2WWBWtBm42t4lMQ0aBHv56ybrhTRNMOTK0rJiAMfMfArCffvsBnuoSFUGIaBf3mZcbtwHGcDIuR F2w== X-Google-Smtp-Source: AGHT+IEt1bokf2gwgVn7hdK2GrWh3MEGT0E9AT9JiLMbohoSe5t35nvuUxv5BuJLVfGUiWauYYMf6L5SXw== X-Received: from pjph9.prod.google.com ([2002:a17:90a:9c09:b0:320:e3e2:6877]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:5249:b0:320:ff84:ceb5 with SMTP id 98e67ed59e1d1-32183b3f039mr501997a91.16.1754597826341; Thu, 07 Aug 2025 13:17:06 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:15 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-20-sagis@google.com> Subject: [PATCH v8 19/30] KVM: selftests: TDX: Add TDX MMIO writes test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The test verifies MMIO writes of various sizes from the guest to the host. Co-developed-by: Isaku Yamahata Signed-off-by: Isaku Yamahata Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/tdx.h | 2 + tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 14 +++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 85 ++++++++++++++++++- 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index fa0b24873a8f..2fd67c3e5128 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -25,5 +25,7 @@ uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, = uint64_t value); uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag); uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t siz= e, uint64_t *data_out); +uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t si= ze, + uint64_t data_in); =20 #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index 8bf41e667fc1..d61940fe7df4 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -123,3 +123,17 @@ uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t a= ddress, uint64_t size, =20 return ret; } + +uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t si= ze, + uint64_t data_in) +{ + struct tdx_hypercall_args args =3D { + .r11 =3D TDG_VP_VMCALL_VE_REQUEST_MMIO, + .r12 =3D size, + .r13 =3D MMIO_WRITE, + .r14 =3D address, + .r15 =3D data_in, + }; + + return __tdx_hypercall(&args, 0); +} diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index 563f1025c8a3..6ad675a93eeb 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -804,6 +804,87 @@ void verify_mmio_reads(void) printf("\t ... PASSED\n"); } =20 +void guest_mmio_writes(void) +{ + uint64_t mmio_test_addr =3D TDX_MMIO_TEST_ADDR | tdx_s_bit; + uint64_t ret; + + ret =3D tdg_vp_vmcall_ve_request_mmio_write(mmio_test_addr, 1, 0x12); + tdx_assert_error(ret); + + ret =3D tdg_vp_vmcall_ve_request_mmio_write(mmio_test_addr, 2, 0x1234); + tdx_assert_error(ret); + + ret =3D tdg_vp_vmcall_ve_request_mmio_write(mmio_test_addr, 4, 0x12345678= ); + tdx_assert_error(ret); + + ret =3D tdg_vp_vmcall_ve_request_mmio_write(mmio_test_addr, 8, 0x12345678= 90ABCDEF); + tdx_assert_error(ret); + + /* Make sure host and guest are synced to the same point of execution */ + tdx_test_report_to_user_space(MMIO_SYNC_VALUE); + + /* Write across page boundary. */ + ret =3D tdg_vp_vmcall_ve_request_mmio_write(PAGE_SIZE - 1, 8, 0); + tdx_assert_error(ret); + + tdx_test_success(); +} + +/* + * Verifies guest MMIO writes. + */ +void verify_mmio_writes(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + uint64_t byte_8; + uint32_t byte_4; + uint16_t byte_2; + uint8_t byte_1; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_mmio_writes); + td_finalize(vm); + + printf("Verifying TD MMIO writes:\n"); + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 1, MMIO_WRITE); + byte_1 =3D *(uint8_t *)(vcpu->run->mmio.data); + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 2, MMIO_WRITE); + byte_2 =3D *(uint16_t *)(vcpu->run->mmio.data); + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 4, MMIO_WRITE); + byte_4 =3D *(uint32_t *)(vcpu->run->mmio.data); + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 8, MMIO_WRITE); + byte_8 =3D *(uint64_t *)(vcpu->run->mmio.data); + + TEST_ASSERT_EQ(byte_1, 0x12); + TEST_ASSERT_EQ(byte_2, 0x1234); + TEST_ASSERT_EQ(byte_4, 0x12345678); + TEST_ASSERT_EQ(byte_8, 0x1234567890ABCDEF); + + tdx_run(vcpu); + TEST_ASSERT_EQ(tdx_test_read_report_from_guest(vcpu), MMIO_SYNC_VALUE); + + td_vcpu_run(vcpu); + TEST_ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYSTEM_EVENT); + TEST_ASSERT_EQ(vcpu->run->system_event.data[12], TDG_VP_VMCALL_INVALID_OP= ERAND); + + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -811,7 +892,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(11); + ksft_set_plan(12); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -834,6 +915,8 @@ int main(int argc, char **argv) "verify_guest_hlt\n"); ksft_test_result(!run_in_new_process(&verify_mmio_reads), "verify_mmio_reads\n"); + ksft_test_result(!run_in_new_process(&verify_mmio_writes), + "verify_mmio_writes\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (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 DD8C027E074 for ; Thu, 7 Aug 2025 20:17:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597830; cv=none; b=MsFLGMSYS92XITlNQT7DnH/A/MrTuZPb3DauqfrjlW9ibfyi2vBznPKuTEnIzdBMWkhMDFEx0ZZCF9S6+DyRI3tRBZ7wk3QpcJLy2ictpu8/qDp/HaFwmHcqGOMsO8/U/G9vQJBnKn5FtXE1OqrGev9G9WZQF9H752TBqTU/Txg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597830; c=relaxed/simple; bh=xl6zU/zvfsPbrUYNAsccEMJ9PE4FINSoXlDmAhqFRU0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=nppP9yGD+IVbi9PLKwoxWDNcXdeg1b6P3corr4PURl97HPOeCYxzIQGorpts2wqY33am1+velAlvgmtQCA6OrTYxQmXwckF/QS0io+wSKn+V9T69oMxPqyPmVGGakXAWanhBzu+Whw906sLWFayMpZxAg6v5aGt1evlsQqGhNNU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=QBpt/ucI; arc=none smtp.client-ip=209.85.216.74 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="QBpt/ucI" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-32147620790so1481743a91.1 for ; Thu, 07 Aug 2025 13:17:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597828; x=1755202628; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=druJe0O0RVRgmBCK/d78lVDLhUI96RPYL//ATHIqQ7o=; b=QBpt/ucI7IAdNccqbRTrH7rREGi4RTnWrmWgvdsXTKgAXQa3Ay07HpUSbSWKJhZ1Sh ncc3VX6i/6AwDrgK4PrS7tUFXybIBdtx1CytoeL7jSnDn9AxB2U/qgMmLX5iXHJm10+h pmB4LaZLqXd3qY0c9y3tsnP0/K44REyj/MFo+etzAQxI1yrb5/Gn5EPqJvJ+dGKwCRAV G10jVTMtA4QliHC3l79LqyL29OLdYJKPElXpPy2eKpWH9/XEO2HTr8izA3ne53eL+wHv Ke3o3kqZtlb2IO2ztFtwoshPLcUtrn+iCHwW0CNvE9ZsteoNjV/oiy1bh5JVANU7m0N5 9+cQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597828; x=1755202628; h=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; bh=druJe0O0RVRgmBCK/d78lVDLhUI96RPYL//ATHIqQ7o=; b=RibV4J1mAjnHogZix6BVO02pydn7hk1AK03n4OrsFH6cIs4eon8NkjRRTS/5H+QMsO OIlP1q974jcKNcKv9YJ35OHK5K2wFX0K53UF2pOl6gnL0hwt+9PNTriKvld/JGol2/6R 2egeJo2eyWlesnJtr2d9P7BRchmomu0UCxqWyUhWXrPVI3XdHRlJ69ldZfMqtgbY+brc thfCGidnoNBftmPjCqtQSaIJVaeJTv7BEErgYtonsiEIIdZVBfWGbB1L34p+NtWoL94w hcy0MslPe3QLkBEq/i8clvhm0/4Bef/oPJQVD/4skdjSWyWkcTdy5e4g4JZirmRorgGS VaHA== X-Gm-Message-State: AOJu0YzSWLWkEyYMg0Q4GviiPMOQS2+nbEAVodXKLsnd2LA8KVpm7MOm VgK9XMUIvvzznZGjSHB1Ka/3WeEGA2Ew2gM2hPssVlCYazojGowTfgQGzBMB3hi4++R/IEZPgMs /Ng== X-Google-Smtp-Source: AGHT+IGUSVXeE5dAKzb1GPjhE8I5Q7KUcp1AD2kuBLfcvmXIX2vkHNMZ7UR9w2EOlvLEGked2h5t1ulMcQ== X-Received: from pjpy17.prod.google.com ([2002:a17:90a:a411:b0:321:370d:cae5]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4a44:b0:31f:134:94ae with SMTP id 98e67ed59e1d1-321839e516dmr510895a91.11.1754597827850; Thu, 07 Aug 2025 13:17:07 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:16 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-21-sagis@google.com> Subject: [PATCH v8 20/30] KVM: selftests: TDX: Add TDX CPUID TDVMCALL test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This test issues a CPUID TDVMCALL from inside the guest to get the CPUID values as seen by KVM. Co-developed-by: Isaku Yamahata Signed-off-by: Isaku Yamahata Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/tdx.h | 4 + tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 25 ++++++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 78 ++++++++++++++++++- 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index 2fd67c3e5128..060158cb046b 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -9,6 +9,7 @@ #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 =20 +#define TDG_VP_VMCALL_INSTRUCTION_CPUID 10 #define TDG_VP_VMCALL_INSTRUCTION_HLT 12 #define TDG_VP_VMCALL_INSTRUCTION_IO 30 #define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31 @@ -27,5 +28,8 @@ uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t addr= ess, uint64_t size, uint64_t *data_out); uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t si= ze, uint64_t data_in); +uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax, uint32_t ecx, + uint32_t *ret_eax, uint32_t *ret_ebx, + uint32_t *ret_ecx, uint32_t *ret_edx); =20 #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index d61940fe7df4..fb391483d2fa 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -137,3 +137,28 @@ uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t = address, uint64_t size, =20 return __tdx_hypercall(&args, 0); } + +uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax, uint32_t ecx, + uint32_t *ret_eax, uint32_t *ret_ebx, + uint32_t *ret_ecx, uint32_t *ret_edx) +{ + struct tdx_hypercall_args args =3D { + .r11 =3D TDG_VP_VMCALL_INSTRUCTION_CPUID, + .r12 =3D eax, + .r13 =3D ecx, + }; + uint64_t ret; + + ret =3D __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (ret_eax) + *ret_eax =3D args.r12; + if (ret_ebx) + *ret_ebx =3D args.r13; + if (ret_ecx) + *ret_ecx =3D args.r14; + if (ret_edx) + *ret_edx =3D args.r15; + + return ret; +} diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index 6ad675a93eeb..2f75f12d2a44 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -885,6 +885,80 @@ void verify_mmio_writes(void) printf("\t ... PASSED\n"); } =20 +/* + * Verifies CPUID TDVMCALL functionality. + * The guest will then send the values to userspace using an IO write to be + * checked against the expected values. + */ +void guest_code_cpuid_tdcall(void) +{ + uint32_t eax, ebx, ecx, edx; + uint64_t err; + + /* Read CPUID leaf 0x1 from host. */ + err =3D tdg_vp_vmcall_instruction_cpuid(/*eax=3D*/1, /*ecx=3D*/0, + &eax, &ebx, &ecx, &edx); + tdx_assert_error(err); + + err =3D tdx_test_report_to_user_space(eax); + tdx_assert_error(err); + + err =3D tdx_test_report_to_user_space(ebx); + tdx_assert_error(err); + + err =3D tdx_test_report_to_user_space(ecx); + tdx_assert_error(err); + + err =3D tdx_test_report_to_user_space(edx); + tdx_assert_error(err); + + tdx_test_success(); +} + +void verify_td_cpuid_tdcall(void) +{ + struct kvm_cpuid_entry2 *cpuid_entry; + uint32_t eax, ebx, ecx, edx; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_code_cpuid_tdcall); + td_finalize(vm); + + printf("Verifying TD CPUID TDVMCALL:\n"); + + /* Wait for guest to report CPUID values */ + tdx_run(vcpu); + eax =3D tdx_test_read_report_from_guest(vcpu); + + tdx_run(vcpu); + ebx =3D tdx_test_read_report_from_guest(vcpu); + + tdx_run(vcpu); + ecx =3D tdx_test_read_report_from_guest(vcpu); + + tdx_run(vcpu); + edx =3D tdx_test_read_report_from_guest(vcpu); + + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + /* Get KVM CPUIDs for reference */ + cpuid_entry =3D vcpu_get_cpuid_entry(vcpu, 1); + TEST_ASSERT(cpuid_entry, "CPUID entry missing\n"); + + TEST_ASSERT_EQ(cpuid_entry->eax, eax); + /* Mask lapic ID when comparing ebx. */ + TEST_ASSERT_EQ(cpuid_entry->ebx & ~0xFF000000, ebx & ~0xFF000000); + TEST_ASSERT_EQ(cpuid_entry->ecx, ecx); + TEST_ASSERT_EQ(cpuid_entry->edx, edx); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -892,7 +966,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(12); + ksft_set_plan(13); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -917,6 +991,8 @@ int main(int argc, char **argv) "verify_mmio_reads\n"); ksft_test_result(!run_in_new_process(&verify_mmio_writes), "verify_mmio_writes\n"); + ksft_test_result(!run_in_new_process(&verify_td_cpuid_tdcall), + "verify_td_cpuid_tdcall\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (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 375A324886C for ; Thu, 7 Aug 2025 20:17:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597832; cv=none; b=iQf+soRNV8E6JTui8mdP/PmZ4JWr8Q79/nNOs6viuRnbC3swWCYdYdUv37QTg1K1MPN2YgtaHJP2xswINfmRiusYSp++MOpsN4mjFIe1b4l4SDx+tWoIbQ8pIihid2oF5tneLmpUpFWpiluR3ecWRnv+Q6aeXVTGgqodeLOJdPk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597832; c=relaxed/simple; bh=RXVJT3xKKpDFgdngx9y4dlRBL6JQNyl8/5ZSR2/B66Q=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=sOqB2Xfic1StUz3YZm805WpuhLgp5wF7YQ/sUtVLQTNEVRvGC0Z9WSj7wuaovCqAZsOzuggiqRMhbQ3+9RQb46spD9q/pip+hpns5wxkVjusObNKQCUeY+GbG+an/BksqkNhcTDef5RJr1KTphENkXkteK3/D7hCbDg+i+uTVvI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=U35JFMmW; arc=none smtp.client-ip=209.85.214.202 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="U35JFMmW" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-242abac2cb4so18204185ad.0 for ; Thu, 07 Aug 2025 13:17:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597830; x=1755202630; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=+3/DP/toZqy9fmiCiLsTNtC3sfq1PRsX7V9GLb3O0mQ=; b=U35JFMmWGwUcgwDR+NKWxUhJKmVhg30H8aZc9PS4fSQ5E151HpcNUYV4pRFDxUtn7N K7x/cqi8pBi0HMhjj7THDfQM89CR9Jhkx/CDLGzN0dbPXT49/iD+WQDv0aMi2l4Xra7/ RMhNmWSwxRFo8MT0xTRa7oajKyM90ARR2gICPmcazZ2k+e/QApEyGCVOd384Y+3ozjoW 5hsStYmu3vxTNIB420Bu4IJWNeI6w6zxUJiuE92JocQOywtncQnISPNOLktbSgPNiv2r ujhXCNLUbDPgegFFN4pwYysdqBZQeTHkxWUz+eIbmrDfEwhgUSYZXglnrmDMZswZovoj 9r5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597830; x=1755202630; h=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; bh=+3/DP/toZqy9fmiCiLsTNtC3sfq1PRsX7V9GLb3O0mQ=; b=QO0oZnF5YtQmhJmOToQEhqTEhdnga/cp7z+sMBTR+8kIuA6IIllefJabBjEFkJrN9D SwKrk5PrndW3+DWQizcXUVimRuQqFf4g7sKG/R4wGOlSDxEdQ/brbooyj97jbH1JZ36u z/sbKAXtzCxWp0fGdHdDhnBunuUQjDMrNYW3O2qlkzyV3ANTaKHeWb0IchdB9N5S21ON kayCUZRejDnTpyLkjoS+/vrOrMetAu33KPfCprHiAd7DfzCb8aO3N3r6DhbXIXNmyqZz yHZcXE0VWiLFdwCpwwXUggClMla9t8qcDKJrMzQTOpTidb4HQ7CpWVkjWSipUVI0JtXU RAsQ== X-Gm-Message-State: AOJu0YwnJtpmro56XVkx0gdmDI2S1qpFPB5ULuTISmAZ9DvneRD7kYse 346+flHHEWaWd6oxxiJkm0PV1LIMaeK8t4ryaT8x2i5Sj+Cx9WtDhbBJFifeujGj90vKilRhVSF oTg== X-Google-Smtp-Source: AGHT+IFJRnQ83ttz5IZxiNzcWF87OdqmEuYc3wMh19wWZE0+e7hLOUX6rDQmIqYB8sf4aztyJmmEccl9/A== X-Received: from pjpy17.prod.google.com ([2002:a17:90a:a411:b0:321:370d:cae5]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:8cd:b0:21f:4649:fd49 with SMTP id d9443c01a7336-242c222b0abmr4455255ad.49.1754597829703; Thu, 07 Aug 2025 13:17:09 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:17 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-22-sagis@google.com> Subject: [PATCH v8 21/30] KVM: selftests: TDX: Verify the behavior when host consumes a TD private memory From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ryan Afranji The test checks that host can only read fixed values when trying to access the guest's private memory. Signed-off-by: Ryan Afranji Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/x86/tdx_vm_test.c | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index 2f75f12d2a44..b6ef0348746c 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -959,6 +959,85 @@ void verify_td_cpuid_tdcall(void) printf("\t ... PASSED\n"); } =20 +/* + * Shared variables between guest and host for host reading private mem te= st + */ +static uint64_t tdx_test_host_read_private_mem_addr; +#define TDX_HOST_READ_PRIVATE_MEM_PORT_TEST 0x53 + +void guest_host_read_priv_mem(void) +{ + uint64_t placeholder =3D 0; + uint64_t ret; + + /* Set value */ + *((uint32_t *)tdx_test_host_read_private_mem_addr) =3D 0xABCD; + + /* Exit so host can read value */ + ret =3D tdg_vp_vmcall_instruction_io(TDX_HOST_READ_PRIVATE_MEM_PORT_TEST, + 4, PORT_WRITE, &placeholder); + tdx_assert_error(ret); + + /* Update guest_var's value and have host reread it. */ + *((uint32_t *)tdx_test_host_read_private_mem_addr) =3D 0xFEDC; + + tdx_test_success(); +} + +void verify_host_reading_private_mem(void) +{ + uint64_t second_host_read; + uint64_t first_host_read; + struct kvm_vcpu *vcpu; + vm_vaddr_t test_page; + uint64_t *host_virt; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_host_read_priv_mem); + + test_page =3D vm_vaddr_alloc_page(vm); + TEST_ASSERT(test_page < BIT_ULL(32), + "Test address should fit in 32 bits so it can be sent to the guest"); + + host_virt =3D addr_gva2hva(vm, test_page); + TEST_ASSERT(host_virt, + "Guest address not found in guest memory regions\n"); + + tdx_test_host_read_private_mem_addr =3D test_page; + sync_global_to_guest(vm, tdx_test_host_read_private_mem_addr); + + td_finalize(vm); + + printf("Verifying host's behavior when reading TD private memory:\n"); + + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_HOST_READ_PRIVATE_MEM_PORT_TEST, + 4, PORT_WRITE); + printf("\t ... Guest's variable contains 0xABCD\n"); + + /* Host reads guest's variable. */ + first_host_read =3D *host_virt; + printf("\t ... Host's read attempt value: %lu\n", first_host_read); + + /* Guest updates variable and host rereads it. */ + tdx_run(vcpu); + printf("\t ... Guest's variable updated to 0xFEDC\n"); + + second_host_read =3D *host_virt; + printf("\t ... Host's second read attempt value: %lu\n", + second_host_read); + + TEST_ASSERT(first_host_read =3D=3D second_host_read, + "Host did not read a fixed pattern\n"); + + printf("\t ... Fixed pattern was returned to the host\n"); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -966,7 +1045,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(13); + ksft_set_plan(14); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -993,6 +1072,8 @@ int main(int argc, char **argv) "verify_mmio_writes\n"); ksft_test_result(!run_in_new_process(&verify_td_cpuid_tdcall), "verify_td_cpuid_tdcall\n"); + ksft_test_result(!run_in_new_process(&verify_host_reading_private_mem), + "verify_host_reading_private_mem\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (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 1722927F183 for ; Thu, 7 Aug 2025 20:17:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597834; cv=none; b=OcTVikk3qe6o3+OsXoHQESe5piEYxaILho8edYdBHemGyTsZcFcHyc7troZm9lP1IVTujyt8kb7961r5GlgoT2+no4fP/GJYbVa7WKsFWc6/2Edk9uUo03G7Q+5J0sdLQOYqBFyHMEavQTorquUrdzx3P6edROzAgUouFlRMOh8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597834; c=relaxed/simple; bh=CRig0zw3CWJIoiQG1OZ5tbEeg//w2L5yCxNzrOTJm4Y=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=QNft/7Cl8mUmQM37KI+lar4MB+5nqs1JmSsdEEguTid1eenSYxFF08jIXjG8Py11bhuvgKRAxGRMVTKcwMP4v+tvk1JdhbOWnH1HKjEawiebDb/UJMPrUL9v3BGPwJZ3/0G14ciJEdJQ652KlxEySpZAXpO6K70pKFoM12oxX2g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=cMsRh26+; arc=none smtp.client-ip=209.85.214.201 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="cMsRh26+" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2405fdb7c15so19752635ad.0 for ; Thu, 07 Aug 2025 13:17:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597831; x=1755202631; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=PSF5kQu2h7S/uMOhNWxjVKAXvKJE0MwCJt3iWAtMmZI=; b=cMsRh26+jOfbmSAXgsd5tCIHWwuIiAGocqFWwb7f+pw2oVzNmEkqBG0ig+6dbekJbw +PgKd7tZrAN44p7t9KFCoeb3MMhzf4YfiAHjvl1U7LIlEU8LZq6aqbDvY6d0Ad46n4qq vApd3yxGTJ+c72/0yux4QHNc75XNF4EH18RjucdEPYaXCPZyAEF4o/gjXL1CEGcHLcUs vtXN6unI5n467SwZ5sBs7OxvTPMfuUHLfot4XZ+WGm3R0VZmXXdF10sMW1CURDckGysR eYi26rnAZ6DJesUpWftbX6UNzIFgDiwPCcTz+CwHb1UJzK/S8v8uL1RF1TL7A+hLFxMt MENw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597831; x=1755202631; h=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; bh=PSF5kQu2h7S/uMOhNWxjVKAXvKJE0MwCJt3iWAtMmZI=; b=dYG+vy08I+P6yVi8eu5JmEB/JEugWBoZ6uNL1Dt6/FRT0L+ZDKuqQ54jiVNRihYaxp LKfoUVCekDHhbtkvGlzrO6NjR+2hyZfqK+Eb2spWjovzP+TKC8r4C0KH0KPPuH3GLOBG Z79a2GY6fexYRKqgxJ/aMbaH0hPZz6rlxR1kJIFcbC0Uov1LKbSkoYRy6vjp0B1jdVZJ xTpLhd3m2LxMKaxNSwUXTx/1woqgPkfV6JljRbjS5kRhU88TqRobSUgUo2LH7Hlf4UCs gHOu1UyeSGfpJh3zze6SVTBRKdlJVfY4RG4qUaKijE59LyrNJ1C0JFtZFNjCckAq7wZK /ZTQ== X-Gm-Message-State: AOJu0YyEeMeTqQ9CowqXTfX7pIS8HzbcFP6+aPgoGrnEFKUGA3ub8zJL Bm994n5N3228s9aYtJw3LKITvB/c3M5BWPz8BUnMGBNIDt0FQY0wg6rfJ4toy/ul5lmZtASLY2b P2Q== X-Google-Smtp-Source: AGHT+IGJofHkLODAzprt0wUeE38NmGQht4PnRoP43YzG8FVZuQrVdCdZU4pd7Qd8m1NTHd8LJfXFc4Z2gw== X-Received: from pjtd2.prod.google.com ([2002:a17:90b:42:b0:321:76a2:947c]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:da8b:b0:242:8a7:6a6c with SMTP id d9443c01a7336-242c2008342mr5550025ad.17.1754597831113; Thu, 07 Aug 2025 13:17:11 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:18 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-23-sagis@google.com> Subject: [PATCH v8 22/30] KVM: selftests: TDX: Add TDG.VP.INFO test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Roger Wang Adds a test for TDG.VP.INFO. Introduce __tdx_module_call() that does needed shuffling from function parameters to registers used by the TDCALL instruction that is used by the guest to communicate with the TDX module. The first function parameter is the leaf number indicating which guest side function should be run, for example, TDG.VP.INFO. The guest uses new __tdx_module_call() to call TDG.VP.INFO to obtain TDX TD execution environment information from the TDX module. All returned registers are passed back to the host that verifies values for correctness. Co-developed-by: Sagi Shahar Signed-off-by: Sagi Shahar Signed-off-by: Roger Wang Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/tdcall.h | 19 +++ .../selftests/kvm/include/x86/tdx/tdx.h | 5 + .../selftests/kvm/lib/x86/tdx/tdcall.S | 68 +++++++++ tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 27 ++++ tools/testing/selftests/kvm/x86/tdx_vm_test.c | 133 +++++++++++++++++- 5 files changed, 251 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdcall.h b/tools/t= esting/selftests/kvm/include/x86/tdx/tdcall.h index e7440f7fe259..ab1a97a82fa9 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdcall.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdcall.h @@ -32,4 +32,23 @@ struct tdx_hypercall_args { /* Used to request services from the VMM */ u64 __tdx_hypercall(struct tdx_hypercall_args *args, unsigned long flags); =20 +/* + * Used to gather the output registers values of the TDCALL and SEAMCALL + * instructions when requesting services from the TDX module. + * + * This is a software only structure and not part of the TDX module/VMM AB= I. + */ +struct tdx_module_output { + u64 rcx; + u64 rdx; + u64 r8; + u64 r9; + u64 r10; + u64 r11; +}; + +/* Used to communicate with the TDX module */ +u64 __tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9, + struct tdx_module_output *out); + #endif // SELFTESTS_TDX_TDCALL_H diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index 060158cb046b..801ca879664e 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -6,6 +6,8 @@ =20 #include "kvm_util.h" =20 +#define TDG_VP_INFO 1 + #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 =20 @@ -31,5 +33,8 @@ uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t add= ress, uint64_t size, uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax, uint32_t ecx, uint32_t *ret_eax, uint32_t *ret_ebx, uint32_t *ret_ecx, uint32_t *ret_edx); +uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, + uint64_t *r8, uint64_t *r9, + uint64_t *r10, uint64_t *r11); =20 #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdcall.S b/tools/testi= ng/selftests/kvm/lib/x86/tdx/tdcall.S index b10769d1d557..c393a0fb35be 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdcall.S +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdcall.S @@ -91,5 +91,73 @@ __tdx_hypercall: pop %rbp ret =20 +#define TDX_MODULE_rcx 0 /* offsetof(struct tdx_module_output, rcx) */ +#define TDX_MODULE_rdx 8 /* offsetof(struct tdx_module_output, rdx) */ +#define TDX_MODULE_r8 16 /* offsetof(struct tdx_module_output, r8) */ +#define TDX_MODULE_r9 24 /* offsetof(struct tdx_module_output, r9) */ +#define TDX_MODULE_r10 32 /* offsetof(struct tdx_module_output, r10) */ +#define TDX_MODULE_r11 40 /* offsetof(struct tdx_module_output, r11) */ + +.globl __tdx_module_call +.type __tdx_module_call, @function +__tdx_module_call: + /* Set up stack frame */ + push %rbp + movq %rsp, %rbp + + /* Callee-saved, so preserve it */ + push %r12 + + /* + * Push output pointer to stack. + * After the operation, it will be fetched into R12 register. + */ + push %r9 + + /* Mangle function call ABI into TDCALL/SEAMCALL ABI: */ + /* Move Leaf ID to RAX */ + mov %rdi, %rax + /* Move input 4 to R9 */ + mov %r8, %r9 + /* Move input 3 to R8 */ + mov %rcx, %r8 + /* Move input 1 to RCX */ + mov %rsi, %rcx + /* Leave input param 2 in RDX */ + + tdcall + + /* + * Fetch output pointer from stack to R12 (It is used + * as temporary storage) + */ + pop %r12 + + /* + * Since this macro can be invoked with NULL as an output pointer, + * check if caller provided an output struct before storing output + * registers. + * + * Update output registers, even if the call failed (RAX !=3D 0). + * Other registers may contain details of the failure. + */ + test %r12, %r12 + jz .Lno_output_struct + + /* Copy result registers to output struct: */ + movq %rcx, TDX_MODULE_rcx(%r12) + movq %rdx, TDX_MODULE_rdx(%r12) + movq %r8, TDX_MODULE_r8(%r12) + movq %r9, TDX_MODULE_r9(%r12) + movq %r10, TDX_MODULE_r10(%r12) + movq %r11, TDX_MODULE_r11(%r12) + +.Lno_output_struct: + /* Restore the state of R12 register */ + pop %r12 + + pop %rbp + ret + /* Disable executable stack */ .section .note.GNU-stack,"",%progbits diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index fb391483d2fa..ab6fd3d7ae4b 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -162,3 +162,30 @@ uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax,= uint32_t ecx, =20 return ret; } + +uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, + uint64_t *r8, uint64_t *r9, + uint64_t *r10, uint64_t *r11) +{ + struct tdx_module_output out; + uint64_t ret; + + memset(&out, 0, sizeof(struct tdx_module_output)); + + ret =3D __tdx_module_call(TDG_VP_INFO, 0, 0, 0, 0, &out); + + if (rcx) + *rcx =3D out.rcx; + if (rdx) + *rdx =3D out.rdx; + if (r8) + *r8 =3D out.r8; + if (r9) + *r9 =3D out.r9; + if (r10) + *r10 =3D out.r10; + if (r11) + *r11 =3D out.r11; + + return ret; +} diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index b6ef0348746c..82acc17a66ab 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -1038,6 +1038,135 @@ void verify_host_reading_private_mem(void) printf("\t ... PASSED\n"); } =20 +/* + * Do a TDG.VP.INFO call from the guest + */ +void guest_tdcall_vp_info(void) +{ + uint64_t rcx, rdx, r8, r9, r10, r11; + uint64_t err; + + err =3D tdg_vp_info(&rcx, &rdx, &r8, &r9, &r10, &r11); + tdx_assert_error(err); + + /* return values to user space host */ + err =3D tdx_test_report_64bit_to_user_space(rcx); + tdx_assert_error(err); + + err =3D tdx_test_report_64bit_to_user_space(rdx); + tdx_assert_error(err); + + err =3D tdx_test_report_64bit_to_user_space(r8); + tdx_assert_error(err); + + err =3D tdx_test_report_64bit_to_user_space(r9); + tdx_assert_error(err); + + err =3D tdx_test_report_64bit_to_user_space(r10); + tdx_assert_error(err); + + err =3D tdx_test_report_64bit_to_user_space(r11); + tdx_assert_error(err); + + tdx_test_success(); +} + +/* + * TDG.VP.INFO call from the guest. Verify the right values are returned + */ +void verify_tdcall_vp_info(void) +{ + const struct kvm_cpuid_entry2 *cpuid_entry; + uint32_t ret_num_vcpus, ret_max_vcpus; + uint64_t rcx, rdx, r8, r9, r10, r11; + const int num_vcpus =3D 2; + struct kvm_vcpu *vcpus[num_vcpus]; + uint64_t attributes; + struct kvm_vm *vm; + int gpa_bits =3D -1; + uint32_t i; + + vm =3D td_create(); + +#define TDX_TDPARAM_ATTR_SEPT_VE_DISABLE_BIT BIT(28) + /* Setting attributes parameter used by TDH.MNG.INIT to 0x10000000 */ + attributes =3D TDX_TDPARAM_ATTR_SEPT_VE_DISABLE_BIT; + + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, attributes); + + for (i =3D 0; i < num_vcpus; i++) + vcpus[i] =3D td_vcpu_add(vm, i, guest_tdcall_vp_info); + + td_finalize(vm); + + printf("Verifying TDG.VP.INFO call:\n"); + + /* Get KVM CPUIDs for reference */ + + for (i =3D 0; i < num_vcpus; i++) { + struct kvm_vcpu *vcpu =3D vcpus[i]; + + cpuid_entry =3D vcpu_get_cpuid_entry(vcpu, 0x80000008); + TEST_ASSERT(cpuid_entry, "CPUID entry missing\n"); + gpa_bits =3D (cpuid_entry->eax & GENMASK(23, 16)) >> 16; + TEST_ASSERT_EQ((1UL << (gpa_bits - 1)), tdx_s_bit); + + /* Wait for guest to report rcx value */ + tdx_run(vcpu); + rcx =3D tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report rdx value */ + tdx_run(vcpu); + rdx =3D tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r8 value */ + tdx_run(vcpu); + r8 =3D tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r9 value */ + tdx_run(vcpu); + r9 =3D tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r10 value */ + tdx_run(vcpu); + r10 =3D tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r11 value */ + tdx_run(vcpu); + r11 =3D tdx_test_read_64bit_report_from_guest(vcpu); + + ret_num_vcpus =3D r8 & 0xFFFFFFFF; + ret_max_vcpus =3D (r8 >> 32) & 0xFFFFFFFF; + + /* first bits 5:0 of rcx represent the GPAW */ + TEST_ASSERT_EQ(rcx & 0x3F, gpa_bits); + /* next 63:6 bits of rcx is reserved and must be 0 */ + TEST_ASSERT_EQ(rcx >> 6, 0); + TEST_ASSERT_EQ(rdx, attributes); + TEST_ASSERT_EQ(ret_num_vcpus, num_vcpus); + TEST_ASSERT_EQ(ret_max_vcpus, vm_check_cap(vm, KVM_CAP_MAX_VCPUS)); + /* VCPU_INDEX =3D i */ + TEST_ASSERT_EQ(r9, i); + /* + * verify reserved bits are 0 + * r10 bit 0 (SYS_RD) indicates that the TDG.SYS.RD/RDM/RDALL + * functions are available and can be either 0 or 1. + */ + TEST_ASSERT_EQ(r10 & ~1, 0); + TEST_ASSERT_EQ(r11, 0); + + /* Wait for guest to complete execution */ + tdx_run(vcpu); + + tdx_test_assert_success(vcpu); + + printf("\t ... Guest completed run on VCPU=3D%u\n", i); + } + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -1045,7 +1174,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(14); + ksft_set_plan(15); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -1074,6 +1203,8 @@ int main(int argc, char **argv) "verify_td_cpuid_tdcall\n"); ksft_test_result(!run_in_new_process(&verify_host_reading_private_mem), "verify_host_reading_private_mem\n"); + ksft_test_result(!run_in_new_process(&verify_tdcall_vp_info), + "verify_tdcall_vp_info\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (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 302D827B4F7 for ; Thu, 7 Aug 2025 20:17:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597834; cv=none; b=Rwa8uulkgspM8XDmR1xoa0kFX6GA0f4wdWp7Kd41oqpkjmUiDMMzeXmefuHYGxhFOki0HU20ME3FokztBDEActLQryE9+WkztzYUCqjSQoXoczXvV2m/Dl2PyNuUAu7TBciGqG1C60AygXSNScH2/sf+gLtPDk4RQtJzFh1Ru5Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597834; c=relaxed/simple; bh=Cx031TrNZdIdQOdyX5MvihIAkWY+q9L/OKrZ+vPmjlk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=mYM4+Z4J4x/+07WvyK8G5PINfKiy+qV7uxow455UIdV0pnBoRUMs2UhANqSrAC9gkJNMb3LFKij5UlivXJ5SKYcbPQRxn/c7vf1GVyc2TQqbo6W3OqX9aaVWOejm/K3eo2m0dpvJ8msXMivJNBNYuHYf4hTUcAzGEPH9u4m5l8k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=vPuZMWUy; arc=none smtp.client-ip=209.85.214.201 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="vPuZMWUy" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2400b28296fso21118035ad.1 for ; Thu, 07 Aug 2025 13:17:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597833; x=1755202633; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=j3wuATvJOp/SkY0VMTyZzPLWrVuKCL/L6FqFW9/aW0g=; b=vPuZMWUykW85vr/wUjK3QQMoHeV4Zz+KVwBtTvK7shKxAyy3E633YVhLX4r5ad4847 2YdpmahzlOzPrkptmxnKIdSdurHZpdXSB4FubuFLVC3Z0k4d7L4dXGbwybpdOrOmR4YK 73L2obkmBKni/ry2KhMlJL1T13EDGaNO6scZcXPKeSDN/SeyhmT1eQhiLCqeRrYB99WC jc0Eo0Wi5Uu1qfVzaF8zI9u3yWGNgMM0suJCfdYQFg78zlab2Glk8huP3Y2I2Mis9hG5 L3RxQviaR+bxvrkcxlIicSDVkQmK7RmhhidvALVDDSnovNuMuCi7gkDPfFDPZ3vnGyU1 QxSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597833; x=1755202633; h=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; bh=j3wuATvJOp/SkY0VMTyZzPLWrVuKCL/L6FqFW9/aW0g=; b=JArv5MGq1P8Awmhpq52CY766v/mwrwEHiV4REGSgNhz9zen+UuM6JHWQvsFLFjIqJW JPYf0KGNgPyYg5eACwJu0l6ryCE2yUhJ9N+hgtCoeXgZZKNgPl4fJB+UVKYIo7YsPvDx x61orygkLGwwViHUQCOD0C3VJCAjWUEZEbOZlZJB+2OHezWpbYxlsTFnCtWMDjl8KZmP pWhExhStR+k9iPuGlpTzAg+8m0xk91+n/O8zViMYi3Vcxcq5N649yXnxRY9jj/B8wSRF PJ61eS+r/DEGbgY3eqVU7LteDq985nIKG+Ltfbw4POaNyABueNBlYYlgjVAxxzUQ+/pG 6kiA== X-Gm-Message-State: AOJu0Yw7vl+A7OySc9o+RSAG1xIexDJwq4DG4RUWJRlrOh7APw4UZSLJ dUQEA6d+P7M5geTgQUeYcqWGkEc2o4W8v9gTa0Shm5PhoEFaeu3X5Dbe4aQd4TNM/K1ZEqsFoRS NWw== X-Google-Smtp-Source: AGHT+IE/3DFZe9krhrc2eyCS++Yn/kdLvd8XWaVDRyTWJURT0NfTFvhoaMS+6eOuMSLA/3cLW1O97RFczg== X-Received: from pjoa22.prod.google.com ([2002:a17:90a:8c16:b0:31e:d9dc:605f]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:ef0a:b0:235:f459:69c7 with SMTP id d9443c01a7336-242c225dbfemr4507735ad.52.1754597832669; Thu, 07 Aug 2025 13:17:12 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:19 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-24-sagis@google.com> Subject: [PATCH v8 23/30] KVM: selftests: Add functions to allow mapping as shared From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng virt_map() enforces a private mapping for private memory. Introduce virt_map_shared() that creates a shared mapping for private as well as shared memory. This way, the TD does not have to remap its page tables at runtime. Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- .../testing/selftests/kvm/include/kvm_util.h | 23 +++++++++++++ tools/testing/selftests/kvm/lib/kvm_util.c | 34 +++++++++++++++++++ .../testing/selftests/kvm/lib/x86/processor.c | 15 ++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index 0d1f24c9f7c7..2e444c172261 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -662,6 +662,8 @@ vm_vaddr_t vm_vaddr_alloc_page(struct kvm_vm *vm); =20 void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, unsigned int npages); +void virt_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, + unsigned int npages); void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa); void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva); vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva); @@ -1137,6 +1139,27 @@ static inline void virt_pg_map(struct kvm_vm *vm, ui= nt64_t vaddr, uint64_t paddr virt_arch_pg_map(vm, vaddr, paddr); } =20 +/* + * VM Virtual Page Map as Shared + * + * Input Args: + * vm - Virtual Machine + * vaddr - VM Virtual Address + * paddr - VM Physical Address + * + * Output Args: None + * + * Return: None + * + * Within @vm, creates a virtual translation for the page starting + * at @vaddr to the page starting at @paddr. + */ +void virt_arch_pg_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t p= addr); + +static inline void virt_pg_map_shared(struct kvm_vm *vm, uint64_t vaddr, u= int64_t paddr) +{ + virt_arch_pg_map_shared(vm, vaddr, paddr); +} =20 /* * Address Guest Virtual to Guest Physical diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index f7e00ea0b211..14edb1de5434 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -7,6 +7,7 @@ #include "test_util.h" #include "kvm_util.h" #include "processor.h" +#include "sparsebit.h" #include "ucall_common.h" =20 #include @@ -1621,6 +1622,39 @@ void virt_map(struct kvm_vm *vm, uint64_t vaddr, uin= t64_t paddr, } } =20 +/* + * Map a range of VM virtual address to the VM's physical address as shared + * + * Input Args: + * vm - Virtual Machine + * vaddr - Virtual address to map + * paddr - VM Physical Address + * npages - The number of pages to map + * + * Output Args: None + * + * Return: None + * + * Within the VM given by @vm, creates a virtual translation for + * @npages starting at @vaddr to the page range starting at @paddr. + */ +void virt_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, + unsigned int npages) +{ + size_t page_size =3D vm->page_size; + size_t size =3D npages * page_size; + + TEST_ASSERT(vaddr + size > vaddr, "Vaddr overflow"); + TEST_ASSERT(paddr + size > paddr, "Paddr overflow"); + + while (npages--) { + virt_pg_map_shared(vm, vaddr, paddr); + sparsebit_set(vm->vpages_mapped, vaddr >> vm->page_shift); + vaddr +=3D page_size; + paddr +=3D page_size; + } +} + /* * Address VM Physical to Host Virtual * diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index 3977719c7893..7742c01d48b1 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -181,7 +181,8 @@ static uint64_t *virt_create_upper_pte(struct kvm_vm *v= m, return pte; } =20 -void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int = level) +static void ___virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t pad= dr, + int level, bool protected) { const uint64_t pg_size =3D PG_LEVEL_SIZE(level); uint64_t *pml4e, *pdpe, *pde; @@ -231,17 +232,27 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr,= uint64_t paddr, int level) * Neither SEV nor TDX supports shared page tables, so only the final * leaf PTE needs manually set the C/S-bit. */ - if (vm_is_gpa_protected(vm, paddr)) + if (protected) *pte |=3D vm->arch.c_bit; else *pte |=3D vm->arch.s_bit; } =20 +void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int = level) +{ + ___virt_pg_map(vm, vaddr, paddr, level, vm_is_gpa_protected(vm, paddr)); +} + void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr) { __virt_pg_map(vm, vaddr, paddr, PG_LEVEL_4K); } =20 +void virt_arch_pg_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t p= addr) +{ + ___virt_pg_map(vm, vaddr, paddr, PG_LEVEL_4K, false); +} + void virt_map_level(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, uint64_t nr_bytes, int level) { --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 E6A0F27FD5D for ; Thu, 7 Aug 2025 20:17:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597836; cv=none; b=R4GOG5p2IKGgcMYTB+UMFaijFFnwQ2DYclnrp6r8kkNzrpuuheH4WhldWVoh5aDzF+Xev9IRGyEYP+wR1v+p3IxxkAZvfC4j8tctOcyl+lmFoxLb8/NPBkyIbjgWAZZ5Q8IT84z5J3B/zOkwGgiTdxyPvy+UyoFXzClPAks47bs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597836; c=relaxed/simple; bh=CFukzjZq/1pgwTOu4oDAaQDChh7pnujoWzTOhp2nE4k=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=GTYLIQWXsqg+LuLtF7ZPon0PYsca3YGT+bMgctNoHjbqhljxm05iagpqSOluvq9OrI+euj1Rn8tgEBLcnl1/HJXt6E807RTj6Z3VG33T87qeNtPdo/DuAOy8/i5ehzH9hMm3TvTnZ1wFpe3MrZLqYcZYyw9sP1977fsJuIL/rE4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=R1X7Uczk; arc=none smtp.client-ip=209.85.216.73 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="R1X7Uczk" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-3217ba6843cso838232a91.2 for ; Thu, 07 Aug 2025 13:17:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597834; x=1755202634; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=j1U4zqJkCnUTzEIFqbPfzhS8WqwxaoFKWnc0WvJH/fI=; b=R1X7UczkLyj3Esm/Hy706lh5WPckLPvm+LImPsA4nYxMq0ZVNdCiw0puEn2no2osat xurpj8l9qb2yX59b0c0hCJQYUVziIDvblpzJg+JNZaUkfGMTEveWLuP8b4Li1QBJBpQl N4GpTsTfR473EkFyEDAuQ57qK6o1K+p7nC1M/JKvfKjPuwWxz8GuG1dgP60wjkneyXRH sKZMUQ1pjjlfMEcwYOlXBP7kfK7LzWKKEWBPH4srw1BooNYsTiFe71cASm7IOs4fK/KE 1eKuYoAGtVO2JuVA6mhzR1/LxSiqqowKkKwzCuxvWWxzQx9FWaK9cU+PogzhrvrWoAVJ oHSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597834; x=1755202634; h=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; bh=j1U4zqJkCnUTzEIFqbPfzhS8WqwxaoFKWnc0WvJH/fI=; b=BL+8JGjVUOy5J3XMGkFO8kG6tkosy1DZsN0iVu2rCAEaNXGNvYtcCRFT3m5AYYvzYh lM0zK0mC2prlUaN6IE3DiYx4g46QLvT0H04V6vEft7urpli9unzxFtILicZySyrBVOvT oYe1u1RwPxSjvhBmmCUIGpsWLejH0vRymnZgGPyxH7zP95IPmKa7sbit6ChEDjbO4edv eCe8QAMVUw7yI1I1mnWSj+TLYwSBw7Ydz7KShax/OemPt9BHe8z2AXyY7qJnt/HqDfwf UZwk2in/yXwEcVAXwWmpiu+l85/E7sc+rv/IxbnCjWII1kJwOwyHqNxKDJ4E2ke5JdsX 6rEA== X-Gm-Message-State: AOJu0YxFSYuPNo64dqh94qB68DDKf/h+yKhZLPzDFSHSiOroLym3iqYq SKAkDeWR3fb0J6zI9yY4S/u49GbORqhyMszkDytgPXqbwPqyKWtS83/L0pndF9IZqFHOJSuD5Uo a+A== X-Google-Smtp-Source: AGHT+IEPsLciEJiNH2hoU3Se3hluI14HHOYMagza7uQX3fjQnAy/LHEhFb4uM748Ovvqjw/ve/fcvyIkrA== X-Received: from pjqf9.prod.google.com ([2002:a17:90a:a789:b0:312:e914:4548]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:2b4f:b0:31f:335d:3424 with SMTP id 98e67ed59e1d1-32183c481d4mr457672a91.27.1754597834136; Thu, 07 Aug 2025 13:17:14 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:20 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-25-sagis@google.com> Subject: [PATCH v8 24/30] KVM: selftests: TDX: Add shared memory test From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ryan Afranji Test that host and guest can exchange data via shared memory. Set up shared memory by first allocating as private and then mapping the same GPA as shared. The guest starts with a request to map a page of memory to shared. This request is done via a hypercall (TDG.VP.VMCALL) from the guest that the kernel converts to KVM_EXIT_HYPERCALL with KVM_HC_MAP_GPA_RANGE that is sent back to the test for handling. Handle the guest's request using the KVM_SET_MEMORY_ATTRIBUTES ioctl(). After the shared memory is set up the guest writes to it and notifies the host from where the data is verified. In return, the host writes to the same memory that is verified by the guest. Co-developed-by: Ackerley Tng Signed-off-by: Ackerley Tng Co-developed-by: Binbin Wu Signed-off-by: Binbin Wu Signed-off-by: Ryan Afranji Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/include/x86/tdx/tdx.h | 4 + .../selftests/kvm/include/x86/tdx/tdx_util.h | 2 + tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 26 ++++ .../selftests/kvm/lib/x86/tdx/tdx_util.c | 32 +++++ .../selftests/kvm/x86/tdx_shared_mem_test.c | 129 ++++++++++++++++++ 6 files changed, 194 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/tdx_shared_mem_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 4a147d498bd2..bdeb40a258e1 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -152,6 +152,7 @@ TEST_GEN_PROGS_x86 +=3D steal_time TEST_GEN_PROGS_x86 +=3D system_counter_offset_test TEST_GEN_PROGS_x86 +=3D pre_fault_memory_test TEST_GEN_PROGS_x86 +=3D x86/tdx_vm_test +TEST_GEN_PROGS_x86 +=3D x86/tdx_shared_mem_test =20 # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86 +=3D x86/nx_huge_pages_test diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index 801ca879664e..88f3571df16f 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -9,6 +9,7 @@ #define TDG_VP_INFO 1 =20 #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 +#define TDG_VP_VMCALL_MAP_GPA 0x10001 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 =20 #define TDG_VP_VMCALL_INSTRUCTION_CPUID 10 @@ -18,6 +19,8 @@ #define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32 #define TDG_VP_VMCALL_VE_REQUEST_MMIO 48 =20 +void handle_userspace_map_gpa(struct kvm_vcpu *vcpu); + uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, uint64_t write, uint64_t *data); void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_g= pa); @@ -36,5 +39,6 @@ uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax, ui= nt32_t ecx, uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, uint64_t *r8, uint64_t *r9, uint64_t *r10, uint64_t *r11); +uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64_t size, uint64_t *= data_out); =20 #endif // SELFTEST_TDX_TDX_H 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 c942aec7ad26..ae39b78aa4af 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h @@ -17,5 +17,7 @@ void td_initialize(struct kvm_vm *vm, enum vm_mem_backing= _src_type src_type, uint64_t attributes); void td_finalize(struct kvm_vm *vm); void td_vcpu_run(struct kvm_vcpu *vcpu); +void handle_memory_conversion(struct kvm_vm *vm, uint32_t vcpu_id, uint64_= t gpa, + uint64_t size, bool shared_to_private); =20 #endif // SELFTESTS_TDX_KVM_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index ab6fd3d7ae4b..bae84c34c19e 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -1,11 +1,21 @@ // SPDX-License-Identifier: GPL-2.0-only =20 +#include #include =20 #include "tdx/tdcall.h" #include "tdx/tdx.h" +#include "tdx/tdx_util.h" #include "tdx/test_util.h" =20 +void handle_userspace_map_gpa(struct kvm_vcpu *vcpu) +{ + handle_memory_conversion(vcpu->vm, vcpu->id, vcpu->run->hypercall.args[0], + vcpu->run->hypercall.args[1] << 12, + vcpu->run->hypercall.args[2] & KVM_MAP_GPA_RANGE_ENCRYPTED); + vcpu->run->hypercall.ret =3D 0; +} + uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, uint64_t write, uint64_t *data) { @@ -189,3 +199,19 @@ uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, =20 return ret; } + +uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64_t size, uint64_t *= data_out) +{ + struct tdx_hypercall_args args =3D { + .r11 =3D TDG_VP_VMCALL_MAP_GPA, + .r12 =3D address, + .r13 =3D size + }; + uint64_t ret; + + ret =3D __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (data_out) + *data_out =3D args.r11; + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/tes= ting/selftests/kvm/lib/x86/tdx/tdx_util.c index 5e4455be828a..c5bee67099c5 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c @@ -608,4 +608,36 @@ void td_finalize(struct kvm_vm *vm) void td_vcpu_run(struct kvm_vcpu *vcpu) { vcpu_run(vcpu); + + /* Handle TD VMCALLs that require userspace handling. */ + if (vcpu->run->exit_reason =3D=3D KVM_EXIT_HYPERCALL && + vcpu->run->hypercall.nr =3D=3D KVM_HC_MAP_GPA_RANGE) { + handle_userspace_map_gpa(vcpu); + } +} + +/* + * Handle conversion of memory with @size beginning @gpa for @vm. Set + * @shared_to_private to true for shared to private conversions and false + * otherwise. + * + * Since this is just for selftests, just keep both pieces of backing + * memory allocated and not deallocate/allocate memory; just do the + * minimum of calling KVM_MEMORY_ENCRYPT_REG_REGION and + * KVM_MEMORY_ENCRYPT_UNREG_REGION. + */ +void handle_memory_conversion(struct kvm_vm *vm, uint32_t vcpu_id, uint64_= t gpa, + uint64_t size, bool shared_to_private) +{ + struct kvm_memory_attributes range; + + range.address =3D gpa; + range.size =3D size; + range.attributes =3D shared_to_private ? KVM_MEMORY_ATTRIBUTE_PRIVATE : 0; + range.flags =3D 0; + + pr_debug("\t... call KVM_SET_MEMORY_ATTRIBUTES ioctl from vCPU %u with gp= a=3D%#lx, size=3D%#lx, attributes=3D%#llx\n", + vcpu_id, gpa, size, range.attributes); + + vm_ioctl(vm, KVM_SET_MEMORY_ATTRIBUTES, &range); } diff --git a/tools/testing/selftests/kvm/x86/tdx_shared_mem_test.c b/tools/= testing/selftests/kvm/x86/tdx_shared_mem_test.c new file mode 100644 index 000000000000..79745e36ce3a --- /dev/null +++ b/tools/testing/selftests/kvm/x86/tdx_shared_mem_test.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#include "kvm_util.h" +#include "processor.h" +#include "tdx/tdcall.h" +#include "tdx/tdx.h" +#include "tdx/tdx_util.h" +#include "tdx/test_util.h" +#include "test_util.h" + +#define TDX_SHARED_MEM_TEST_PRIVATE_GVA (0x80000000) +#define TDX_SHARED_MEM_TEST_VADDR_SHARED_MASK BIT_ULL(30) +#define TDX_SHARED_MEM_TEST_SHARED_GVA \ + (TDX_SHARED_MEM_TEST_PRIVATE_GVA | \ + TDX_SHARED_MEM_TEST_VADDR_SHARED_MASK) + +#define TDX_SHARED_MEM_TEST_GUEST_WRITE_VALUE (0xcafecafe) +#define TDX_SHARED_MEM_TEST_HOST_WRITE_VALUE (0xabcdabcd) + +#define TDX_SHARED_MEM_TEST_INFO_PORT 0x87 + +/* + * Shared variable between guest and host + */ +static uint64_t test_mem_shared_gpa; + +void guest_shared_mem(void) +{ + uint32_t *test_mem_shared_gva =3D + (uint32_t *)TDX_SHARED_MEM_TEST_SHARED_GVA; + + uint64_t placeholder; + uint64_t ret; + + /* Map gpa as shared */ + ret =3D tdg_vp_vmcall_map_gpa(test_mem_shared_gpa, PAGE_SIZE, + &placeholder); + if (ret) + tdx_test_fatal_with_data(ret, __LINE__); + + *test_mem_shared_gva =3D TDX_SHARED_MEM_TEST_GUEST_WRITE_VALUE; + + /* Exit so host can read shared value */ + ret =3D tdg_vp_vmcall_instruction_io(TDX_SHARED_MEM_TEST_INFO_PORT, 4, + PORT_WRITE, &placeholder); + if (ret) + tdx_test_fatal_with_data(ret, __LINE__); + + /* Read value written by host and send it back out for verification */ + ret =3D tdg_vp_vmcall_instruction_io(TDX_SHARED_MEM_TEST_INFO_PORT, 4, + PORT_WRITE, + (uint64_t *)test_mem_shared_gva); + if (ret) + tdx_test_fatal_with_data(ret, __LINE__); +} + +int verify_shared_mem(void) +{ + vm_vaddr_t test_mem_private_gva; + uint64_t test_mem_private_gpa; + uint32_t *test_mem_hva; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_shared_mem); + + /* + * Set up shared memory page for testing by first allocating as private + * and then mapping the same GPA again as shared. This way, the TD does + * not have to remap its page tables at runtime. + */ + test_mem_private_gva =3D vm_vaddr_alloc(vm, vm->page_size, + TDX_SHARED_MEM_TEST_PRIVATE_GVA); + TEST_ASSERT_EQ(test_mem_private_gva, TDX_SHARED_MEM_TEST_PRIVATE_GVA); + + test_mem_hva =3D addr_gva2hva(vm, test_mem_private_gva); + TEST_ASSERT(test_mem_hva, + "Guest address not found in guest memory regions\n"); + + test_mem_private_gpa =3D addr_gva2gpa(vm, test_mem_private_gva); + virt_map_shared(vm, TDX_SHARED_MEM_TEST_SHARED_GVA, test_mem_private_gpa,= 1); + + test_mem_shared_gpa =3D test_mem_private_gpa | vm->arch.s_bit; + sync_global_to_guest(vm, test_mem_shared_gpa); + + td_finalize(vm); + + vm_enable_cap(vm, KVM_CAP_EXIT_HYPERCALL, BIT_ULL(KVM_HC_MAP_GPA_RANGE)); + + printf("Verifying shared memory accesses for TDX\n"); + + /* Begin guest execution; guest writes to shared memory. */ + printf("\t ... Starting guest execution\n"); + + /* Handle map gpa as shared */ + tdx_run(vcpu); + + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_SHARED_MEM_TEST_INFO_PORT, 4, PORT_WRITE); + TEST_ASSERT_EQ(*test_mem_hva, TDX_SHARED_MEM_TEST_GUEST_WRITE_VALUE); + + *test_mem_hva =3D TDX_SHARED_MEM_TEST_HOST_WRITE_VALUE; + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_SHARED_MEM_TEST_INFO_PORT, 4, PORT_WRITE); + TEST_ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offse= t), + TDX_SHARED_MEM_TEST_HOST_WRITE_VALUE); + + printf("\t ... PASSED\n"); + + kvm_vm_free(vm); + + return 0; +} + +int main(int argc, char **argv) +{ + if (!is_tdx_enabled()) { + printf("TDX is not supported by the KVM\n" + "Skipping the TDX tests.\n"); + return 0; + } + + return verify_shared_mem(); +} --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (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 3E5B3280339 for ; Thu, 7 Aug 2025 20:17:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597837; cv=none; b=h2WwJUCzlfG3HYY3oytjYroiQXNyMd4tPj6prrsNuzDjFut7FsSs6lqChngLdjyNW+n1lx/ntShmvlHjKORTTdTYOOib4Gj3B9g8gifoxadJpgqddypoHaEkbp6xga/py1pZY3NspoxUhWqr1+3S/3glaJox+YTnKDkvnSg4YeY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597837; c=relaxed/simple; bh=nf0EzG5NgSXKa/TrkEawzdB34B3daS0Giz+DgYxepKc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=lwv2U1JhiV/bWdvvx7GpyBzuJzE4EtLPVO48XTPxV3rTvSlu46U9LqSM23IA8RV1LsjjB1MNIzAoLLeklTXn/hy3F7ztYLyyqoqm4XK1GlD+MluMMOTyzpHp1O80fDuAyXE2RQ2/pP1wkVqDn22sWBNb96+Uf5Yz5lPY2Bvc0iw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=eEYHgR5I; arc=none smtp.client-ip=209.85.216.74 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="eEYHgR5I" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-31eb41391f3so1433629a91.0 for ; Thu, 07 Aug 2025 13:17:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597836; x=1755202636; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=iq172XdXxDqkESP8AaCKlxAjIACVlq1lEydY7qNJG/k=; b=eEYHgR5Ig2P560wuONsaZ/RZZ+sv1mUM1WNVm94Ajo5W9FVpE382KJWbsD1sEQMPM5 7O/9SVcsEe1c4j4xpLPNHUgy0aJKjlooNNC4vcGU7Mgk64yfamNSxXjH6VJNcs4PsDg8 uc+ztRONLyFPy9XDoQOzyxbLn1twHgBc1lVLWGVesqF6ZAJcUwGRHBhFT0FP5Fj9GcWB afETwl2vYRZa96rIZySdHxveUw6ARX//WJVnIIXLgI5xm0IpGDCHcsOuNbVQ/GdwLHwh vTp1ZjIGTrVzkkEdBZoSyRqD5BxqMdevBziqeSyyWqCV2TRSQ0yvLsfiyjR6Wj45vdI0 m92A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597836; x=1755202636; h=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; bh=iq172XdXxDqkESP8AaCKlxAjIACVlq1lEydY7qNJG/k=; b=c+BZj8nJ69cwKxX+RVKSyV4xF3W29twOXfIqbCXVT6UHIZ3yiAq/jUJkd7jYzXHFkg 43b5CmTK/s3KhAccPmdPIWWvUpLtwmYoBvT4/4bWdBf6KCYvPOO2yiPwPAcyymu7fcYi SdmjOXTDk3Np8GFl559D+OiZW/QAL+4M3VZZ/DcuvjFIduGtK5YmamhPVjbwVtIvW/Ll XWVxDDPgON5DesJJPBbdH6g9uhevdzVBLKQuA2TDQpPqS/xBA2yMi03pTQ7WqF/ir8Kz tLzwgaCZ1QUTW8WW5wPPBV3AlbSRHj0r6dyiiqQ0He8GBGXPcmQYDzKUiEtD+7cjpJVo T52w== X-Gm-Message-State: AOJu0YzrtT+8KTv9WIm0XV4yUqWwNl/iYa3v6nMDjtpNbxTcr3OfixXz qQYzJdMgjuiw01hdTyUQyAtdOuz/u0R5i1ifDzSbOYXhQdJwbLXGdH7TzuUfAzMZzcij16fZLR/ KSw== X-Google-Smtp-Source: AGHT+IF9GDKYO/YboaNdsTUnSP/4IoWgR2B49CtjJAmqyOJRj3Eemq3TkQ+JtNffql2w5H+tGl/Z0AxnOA== X-Received: from pjvb4.prod.google.com ([2002:a17:90a:d884:b0:314:29b4:453]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:1fc3:b0:311:fde5:c4c2 with SMTP id 98e67ed59e1d1-321839c8a75mr496473a91.1.1754597835694; Thu, 07 Aug 2025 13:17:15 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:21 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-26-sagis@google.com> Subject: [PATCH v8 25/30] KVM: selftests: KVM: selftests: Expose new vm_vaddr_alloc_private() From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng vm_vaddr_alloc_private allow specifying both the virtual and physical addresses for the allocation. Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/include/kvm_util.h | 3 +++ tools/testing/selftests/kvm/lib/kvm_util.c | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index 2e444c172261..add0b91ebce0 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -652,6 +652,9 @@ vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t s= z, vm_vaddr_t vaddr_min, vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, enum kvm_mem_region_type type); +vm_vaddr_t vm_vaddr_alloc_private(struct kvm_vm *vm, size_t sz, + vm_vaddr_t vaddr_min, vm_paddr_t paddr_min, + enum kvm_mem_region_type type); vm_vaddr_t vm_vaddr_identity_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, enum kvm_mem_region_type type); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 14edb1de5434..2b442639ee2d 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1503,6 +1503,13 @@ vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, = size_t sz, return ____vm_vaddr_alloc(vm, sz, vaddr_min, KVM_UTIL_MIN_PFN * vm->page_= size, type, false); } =20 +vm_vaddr_t vm_vaddr_alloc_private(struct kvm_vm *vm, size_t sz, + vm_vaddr_t vaddr_min, vm_paddr_t paddr_min, + enum kvm_mem_region_type type) +{ + return ____vm_vaddr_alloc(vm, sz, vaddr_min, paddr_min, type, true); +} + /* * Allocate memory in @vm of size @sz beginning with the desired virtual a= ddress * of @vaddr_min and backed by physical address equal to returned virtual --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (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 28BBA28135B for ; Thu, 7 Aug 2025 20:17:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597839; cv=none; b=LCR2t506ohffOwTStwtwtgwofer/wTntQ8aSjhCdxFA5CEf7E/zLU9xc94VVvQELu62Y/hMbdv/0njKAxR/My4CnLQkHZOZbkUQ5v7e3Cy7Fw/2+akrHY//CMhoWjElUyxwmZmc5Fh4ojevjZ+cE+jDJlnlSSE4XRghER7BDSYY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597839; c=relaxed/simple; bh=ndNmo3n7jVsJUhaVFvSU4GOTOiKiQ6V9KrRi130HlcQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Tv0zd/Y3EEmFoocfnSLMwWLUVjxl9ewimUlQGZCFKy/xivk8OTx0P6pDeYWhkbpkQmHUb9EAWWtVWHievtBhw07+T0Fr9v2cZLo1EPb3uPzMrbkvvaXTx0ytoEri151MFo+3U7+DUygPpqF8PHfT8EvCsGNxJObKyGb+aNurc30= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ifjMxrFN; arc=none smtp.client-ip=209.85.214.202 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ifjMxrFN" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-24249098fd0so16918995ad.0 for ; Thu, 07 Aug 2025 13:17:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597837; x=1755202637; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=yBWU1Sn84q4yPaJOeH6SG4vPoOnSToM6CD8DOZcfEIE=; b=ifjMxrFNDIuMbQqPPPpDiZq8HOcLCJC1j7qYcrMj/yQ4z5YeAMlvGt09LDBGZOOjX6 nl6oMVK4IgDuY7bXFMB6YWJrJaHQWO0KLK2Fw1AiGivcsUZpiQNI4ERdJTtod/TJG1Yk 4e14Ofj6eeed1tQGBmxYGhzkVa7aD+FvVahVgmNNgVS9V8kHK142TXP/6Oov8MKkJ6LZ srHDHgWdB7bMCP54b+N1DECEYdXz8+yoXoCmm9/W01wtTkjO3yx9jWSyPlBEMGYsUJ34 QQUav5IHOiGqaduGkM23cWCb4uNvWMi4zH3tB32QYW3HbcVjtu0z69pzR8lDOEOXPRHW 6yyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597837; x=1755202637; h=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; bh=yBWU1Sn84q4yPaJOeH6SG4vPoOnSToM6CD8DOZcfEIE=; b=XGZPIvPwm7u1PDO0ZJiKSJ/mm4dWAboWdzajgeYFwL50ZtY1kaXyn3HwgmWuzmDrP/ dT1EVRvsAobqfznUDxlyRhx9wkOnAmKrxUhBSAuP/tzymdY5d8xq68RR07OyrPpAILg9 PxsMqq+a8C/oFOH8K6k6E/kINuMLHZZYbQV0xeQJk3qoHo5Sy+aqHnmts95fMQcrn6xs HnKkV/sFy4wDVD4ZOnsVN4tUK9v12XcEltDxMmmdXCwLjGjsJsTexxXP36qDhapoZGH3 Tw19/8kzRIfLZ5HFdwUQGu7QxYMCjrqVv9J1Zq2UGAgDfCudX1K4R2zWqAQtBj8lbD8j 7ihw== X-Gm-Message-State: AOJu0YwYJAqzc0hGLRIdAhSFRcMg4LIG2W5PzTCTkWIeSFRY+pLx2IF+ VPCRNyup0PldgOKqbXcNXZCbuBaLWpO72+Ofeka5o88yQOp0LXgSgQfCkxYzKizj0C3J3JZbgw5 plQ== X-Google-Smtp-Source: AGHT+IECHI4Izk33wOMfxJ6pDGHsZG05/2uZ1BEat0BzueMP70wBC7iSjK5nEYAcwKaUV/DsQbQaAEwBDw== X-Received: from pltf11.prod.google.com ([2002:a17:902:74cb:b0:234:d00c:b347]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:19ef:b0:234:aa9a:9e0f with SMTP id d9443c01a7336-242c203f9e9mr4272425ad.23.1754597837261; Thu, 07 Aug 2025 13:17:17 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:22 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-27-sagis@google.com> Subject: [PATCH v8 26/30] KVM: selftests: TDX: Add support for TDG.MEM.PAGE.ACCEPT From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng Add support for TDG.MEM.PAGE.ACCEPT that the guest uses to accept a pending private page, previously added by TDH.MEM.PAGE.AUG or after conversion using the KVM_SET_MEMORY_ATTRIBUTES ioctl(). Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/include/x86/tdx/tdx.h | 2 ++ tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index 88f3571df16f..53637159fa12 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -7,6 +7,7 @@ #include "kvm_util.h" =20 #define TDG_VP_INFO 1 +#define TDG_MEM_PAGE_ACCEPT 6 =20 #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_MAP_GPA 0x10001 @@ -40,5 +41,6 @@ uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, uint64_t *r8, uint64_t *r9, uint64_t *r10, uint64_t *r11); uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64_t size, uint64_t *= data_out); +uint64_t tdg_mem_page_accept(uint64_t gpa, uint8_t level); =20 #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index bae84c34c19e..a51ab7511936 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -3,6 +3,7 @@ #include #include =20 +#include "processor.h" #include "tdx/tdcall.h" #include "tdx/tdx.h" #include "tdx/tdx_util.h" @@ -215,3 +216,9 @@ uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64= _t size, uint64_t *data_o *data_out =3D args.r11; return ret; } + +uint64_t tdg_mem_page_accept(uint64_t gpa, uint8_t level) +{ + return __tdx_module_call(TDG_MEM_PAGE_ACCEPT, (gpa & PAGE_MASK) | level, + 0, 0, 0, NULL); +} --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 5DF4628152F for ; Thu, 7 Aug 2025 20:17:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597840; cv=none; b=XVze6GSMmhu1bArXDGtqBdmt+lP2Of6F1/0C7JpAdwe6OQ6PvI2JOt8PuW71INy2yAArM1zKkJ/SRBs9EiKrjM7dN6OtGbyuEN4CdZHxkWG5FnTK85fNu6LE4pHh6NLrjYxCze+M2gGAbg4gM6Hlm16o1ygWKKHMD0bwVwEVAok= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597840; c=relaxed/simple; bh=lDPkiqgqLnS2hIwk/kcRCl9YxEjkdiRRNID0A7F0VAA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=O38aJ4Svi+D+QHWXqcFppo3ws3uI5B2VCzXPrJtc/Jhy5GAUzq2zOBkzQSFFD2MRRJL1pxKMyGMj1C4grji9TfLt0b+qlUxUD1UN8phb/WlpVt/aYwz7Yhr0I/y06/5f0bEImYV0aoW23It5NpSfG466ovAyrRJR5NYKiBGkq3c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=z47yLss3; arc=none smtp.client-ip=209.85.216.73 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="z47yLss3" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-31ea6231678so2109896a91.0 for ; Thu, 07 Aug 2025 13:17:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597839; x=1755202639; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=4dbQa13oAbzCDXWZST2Fz7qe3oTtyOGSFzX0b1otAhk=; b=z47yLss3lqniPdHyaLUlt4SGaV7K9fdwwP5hySwlUkDzLUQdbMFbnBnnu2mMazNlQ4 pOL8Or5HNsd1LWlFUpGo0uxeHLzNM0VW6HdAHbzvNR7UhCCRYICMp0+yEc0eHzweQgaQ mj93vy6Vx6HHXPmCJBAwwoHdTWH1NBs8aPs4pJbRxTDO78toR9JKspF3tqUBgLeahq7F Qc2flfdb2qVmArotb+ECjqBbFCgvITaAh9WO6Kk0BMI3uf0o24mY4quy+rHgt+aqFNDL AsT6Bfjm8XIA8yyPjqEtA+C7S+VlXyM3qQm+Wbc/IdiqhNtNKuRA//woDexfWnDha66C KUAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597839; x=1755202639; h=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; bh=4dbQa13oAbzCDXWZST2Fz7qe3oTtyOGSFzX0b1otAhk=; b=e1DoJdhi5oXt+GfUfpRMKJ6RwM6WOdkqfWiZWjtRt2J9OvxB0NheRldvR2/BTljcXu 5yhmSoaaZYAaFwnHl56RgTaBQWXWnGm3CL/iqWoLsygEI7JFdG47JTb+s7ThPZQrwK5e WgAXSAZbiheHL7bEV8i2mjq8XfvRxiYrtdWrIRbvjQeMCw6XTi8/y+GRXD/8hWKv1aLO 6r6mM6xywwQ8Dorhuu0AFFMC2HbinltvvLU1VyWk8yQb3caQTWA+wgI833qowyagcO1y xE+GE3SYV6bXOHqwDlmOSpWMcLPFK40vNUQ4WCA2eQyx1FkTHQ+eEplKfcEF9eZKWfXN 8OPA== X-Gm-Message-State: AOJu0Yz4XdsKoqUmD+zSC+Z/lxqgdivSnA7hZXzCAVl2aao3SUD4wbvt DOGABn9BC6Bjy7suySSAo+jYbJweRX9gbfOXQnhIJkWiSGlbqOcnKrBZ0+C2E06Eb2RgkpywweM VtA== X-Google-Smtp-Source: AGHT+IG2Lk4NOPEbEjMFa+XZyNu3Q1qhg7BUXzj5BBM1i5dAZdBMzmsaEaxU8P2uH91Sze4Rm/UBNniW1g== X-Received: from pjov3.prod.google.com ([2002:a17:90a:9603:b0:31c:2fe4:33b6]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:544c:b0:31e:a48c:25ef with SMTP id 98e67ed59e1d1-32184529833mr212813a91.10.1754597838787; Thu, 07 Aug 2025 13:17:18 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:23 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-28-sagis@google.com> Subject: [PATCH v8 27/30] KVM: selftests: TDX: Add support for TDG.VP.VEINFO.GET From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng Support TDG.VP.VEINFO.GET that the guest uses to obtain the virtualization exception information of the recent #VE exception. Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- .../selftests/kvm/include/x86/tdx/tdx.h | 21 +++++++++++++++++++ tools/testing/selftests/kvm/lib/x86/tdx/tdx.c | 19 +++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/test= ing/selftests/kvm/include/x86/tdx/tdx.h index 53637159fa12..55e52ad3de55 100644 --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h @@ -7,6 +7,7 @@ #include "kvm_util.h" =20 #define TDG_VP_INFO 1 +#define TDG_VP_VEINFO_GET 3 #define TDG_MEM_PAGE_ACCEPT 6 =20 #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 @@ -43,4 +44,24 @@ uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64_t size, uint64_t *= data_out); uint64_t tdg_mem_page_accept(uint64_t gpa, uint8_t level); =20 +/* + * Used by the #VE exception handler to gather the #VE exception + * info from the TDX module. This is a software only structure + * and not part of the TDX module/VMM ABI. + * + * Adapted from arch/x86/include/asm/tdx.h + */ +struct ve_info { + uint64_t exit_reason; + uint64_t exit_qual; + /* Guest Linear (virtual) Address */ + uint64_t gla; + /* Guest Physical Address */ + uint64_t gpa; + uint32_t instr_len; + uint32_t instr_info; +}; + +uint64_t tdg_vp_veinfo_get(struct ve_info *ve); + #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c b/tools/testing/= selftests/kvm/lib/x86/tdx/tdx.c index a51ab7511936..e42b586808a1 100644 --- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.c @@ -222,3 +222,22 @@ uint64_t tdg_mem_page_accept(uint64_t gpa, uint8_t lev= el) return __tdx_module_call(TDG_MEM_PAGE_ACCEPT, (gpa & PAGE_MASK) | level, 0, 0, 0, NULL); } + +uint64_t tdg_vp_veinfo_get(struct ve_info *ve) +{ + struct tdx_module_output out; + uint64_t ret; + + memset(&out, 0, sizeof(struct tdx_module_output)); + + ret =3D __tdx_module_call(TDG_VP_VEINFO_GET, 0, 0, 0, 0, &out); + + ve->exit_reason =3D out.rcx; + ve->exit_qual =3D out.rdx; + ve->gla =3D out.r8; + ve->gpa =3D out.r9; + ve->instr_len =3D out.r10 & 0xffffffff; + ve->instr_info =3D out.r10 >> 32; + + return ret; +} --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (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 E7108283144 for ; Thu, 7 Aug 2025 20:17:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597843; cv=none; b=BWz2b3qZY+9kEdg3a461PdK1yWUc292vw4BZthquzI0UHCO4OqGyxdUBnf1lwvugmxzA2r8Bd8FmN0LVwfp4djAOcHZHX5KgNvGxqoU2aLezSXfvMEfVpnpHWHpOmwqL6z8dfg7pakKg8MjMfNHNJR/eULP4l7XLhdEMX/m3CGk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597843; c=relaxed/simple; bh=5V/Uk/vrVxWs5cFs9pwQXAjz5rbj0AkSbLRxLJRhUfE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=jf/tcX5ARDZtxhe9xaeAgaw377XSrMyN++OF/J+Iw3kV3KAFZXxpf+kkVMwxqJVGX50BAtpWaQQPOIauyyDaApkbMVSEm/UJiaPdMscJYHMlOeqEAKyYGaVaxJwCq6OrsePhlBcmCWRcfs9hp+3tljEPP5pMXo8jHi6Tmh0ilTM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=nJF/OeIM; arc=none smtp.client-ip=209.85.216.74 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="nJF/OeIM" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-31f74a64da9so1615599a91.2 for ; Thu, 07 Aug 2025 13:17:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597840; x=1755202640; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=jI2thjxokBvAd3Gvlvl4ty+/7Jc/pmQTHuyW99Exciw=; b=nJF/OeIMhoFcNt0keoPG2fQ/HGzaO5oGZkf7hBZj6nG9W77Rn9zyyvVc5i8JP/9iBu foKGJFT/BapC86Mg9bs9kU29LwMOcvUNOeedxo+x/y1+AZdQg2DAKLZKwlC4KipikX34 X2rwvo74GYTY9bv9AMIKJH84Dg2nKS6NdVm9idfa0UpeIOMd9n/bx5RILeSbPqp+Uf8U Dlkmxsrc3EKAFQkG32RPcPHcBwEWnPlO4bbalHLYgAsgmX4ClZ5o7xImb5fqTvDeB45K RRGW6jDGJmw6YcjASg9QagSyRegkqIok0uJEZHvRROOP2+u7DkdHU0CxBgAr+hwZNrAe ow8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597840; x=1755202640; h=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; bh=jI2thjxokBvAd3Gvlvl4ty+/7Jc/pmQTHuyW99Exciw=; b=rIK8ehjHK5m1Tn4m/i+3480ESQ1GTH+reOAOifnKZRQSTPGyvZcRhxsEIMOMrP/z6S /W3pzhcBMMb5DF0nVPoPZ8Y3MwqBoZBKIGDwepbWm0Iamw6z1poO1+D6Y4l9/qg3T5G6 qMLxpbMWsZtNPLiLY9opP1cQafk9OHKQZYrZjpC44S1cw5Q2C+NtqQ5E3PY/iWMkbrVn ggBP+Oxg9Zy4CIBlVCeaj+ND/RCorPlaDHZkRQndY8QZpoHZ9ow15q6KzJG3jafDutVx vffSQpUdySmRcOvqqmAacAdr8KWR6uaTgiyi1KRGyDk9RWLnE6ZtWvQwjkuIuf3offwy hToQ== X-Gm-Message-State: AOJu0Yz0zJA88CDDYqADWLDJKxr279JUoNWzsxTUj3CoviBlx5duaGNZ WgL9kQnlLPaIMJU2riGf5eCu2CtJBCaT7IdfQgtLeF+aFQJkx6T3dgDmuUZlzxEpqHUju2VacoC NEg== X-Google-Smtp-Source: AGHT+IFaB+pyCuHTXjDHbvkPqVXu5AmJ2aDF7FkIoYXp/+CIgX0dTDSXECySrq5zcnyOQPtob99t0LTOEg== X-Received: from pjro15.prod.google.com ([2002:a17:90a:b88f:b0:31f:1dad:d0a4]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90a:e703:b0:31f:6d95:8f76 with SMTP id 98e67ed59e1d1-32183c41d91mr500446a91.29.1754597840197; Thu, 07 Aug 2025 13:17:20 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:24 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-29-sagis@google.com> Subject: [PATCH v8 28/30] KVM: selftests: TDX: Add TDX UPM selftest From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng This tests the use of guest memory with explicit TDG.VP.VMCALL calls. Provide a 2MB memory region to the TDX guest with a 40KB focus area at offset 1MB intended to be shared between host and guest. The entire 2MB region starts out as private with the guest filling it with a pattern and a check from the host to ensure the host is not able to see the pattern. The guest then requests via TDG.VP.VMCALL that the 40KB focus area be shared with checks that the host and guest has the same view of the memory. Finally the guest requests the 40KB memory to be private again with checks to confirm this is the case. Co-developed-by: Binbin Wu Signed-off-by: Binbin Wu Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../testing/selftests/kvm/x86/tdx_upm_test.c | 397 ++++++++++++++++++ 2 files changed, 398 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/tdx_upm_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index bdeb40a258e1..191fc5dad854 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -153,6 +153,7 @@ TEST_GEN_PROGS_x86 +=3D system_counter_offset_test TEST_GEN_PROGS_x86 +=3D pre_fault_memory_test TEST_GEN_PROGS_x86 +=3D x86/tdx_vm_test TEST_GEN_PROGS_x86 +=3D x86/tdx_shared_mem_test +TEST_GEN_PROGS_x86 +=3D x86/tdx_upm_test =20 # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86 +=3D x86/nx_huge_pages_test diff --git a/tools/testing/selftests/kvm/x86/tdx_upm_test.c b/tools/testing= /selftests/kvm/x86/tdx_upm_test.c new file mode 100644 index 000000000000..387258ab1a62 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/tdx_upm_test.c @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "processor.h" +#include "tdx/tdcall.h" +#include "tdx/tdx.h" +#include "tdx/tdx_util.h" +#include "tdx/test_util.h" +#include "test_util.h" + +/* TDX UPM test patterns */ +#define PATTERN_CONFIDENCE_CHECK (0x11) +#define PATTERN_HOST_FOCUS (0x22) +#define PATTERN_GUEST_GENERAL (0x33) +#define PATTERN_GUEST_FOCUS (0x44) + +/* + * 0x80000000 is arbitrarily selected. The selected address need not be th= e same + * as TDX_UPM_TEST_AREA_GVA_PRIVATE, but it should not overlap with selfte= st + * code or boot page. + */ +#define TDX_UPM_TEST_AREA_GPA (0x80000000) +/* Test area GPA is arbitrarily selected */ +#define TDX_UPM_TEST_AREA_GVA_PRIVATE (0x90000000) +/* Select any bit that can be used as a flag */ +#define TDX_UPM_TEST_AREA_GVA_SHARED_BIT (32) +/* + * TDX_UPM_TEST_AREA_GVA_SHARED is used to map the same GPA twice into the + * guest, once as shared and once as private + */ +#define TDX_UPM_TEST_AREA_GVA_SHARED \ + (TDX_UPM_TEST_AREA_GVA_PRIVATE | \ + BIT_ULL(TDX_UPM_TEST_AREA_GVA_SHARED_BIT)) + +/* The test area is 2MB in size */ +#define TDX_UPM_TEST_AREA_SIZE SZ_2M +/* 0th general area is 1MB in size */ +#define TDX_UPM_GENERAL_AREA_0_SIZE SZ_1M +/* Focus area is 40KB in size */ +#define TDX_UPM_FOCUS_AREA_SIZE (SZ_32K + SZ_8K) +/* 1st general area is the rest of the space in the test area */ +#define TDX_UPM_GENERAL_AREA_1_SIZE \ + (TDX_UPM_TEST_AREA_SIZE - TDX_UPM_GENERAL_AREA_0_SIZE - \ + TDX_UPM_FOCUS_AREA_SIZE) + +/* + * The test memory area is set up as two general areas, sandwiching a focus + * area. The general areas act as control areas. After they are filled, t= hey + * are not expected to change throughout the tests. The focus area is memo= ry + * permissions change from private to shared and vice-versa. + * + * The focus area is intentionally small, and sandwiched to test that when= the + * focus area's permissions change, the other areas' permissions are not + * affected. + */ +struct __packed tdx_upm_test_area { + uint8_t general_area_0[TDX_UPM_GENERAL_AREA_0_SIZE]; + uint8_t focus_area[TDX_UPM_FOCUS_AREA_SIZE]; + uint8_t general_area_1[TDX_UPM_GENERAL_AREA_1_SIZE]; +}; + +static void fill_test_area(struct tdx_upm_test_area *test_area_base, + uint8_t pattern) +{ + memset(test_area_base, pattern, sizeof(*test_area_base)); +} + +static void fill_focus_area(struct tdx_upm_test_area *test_area_base, + uint8_t pattern) +{ + memset(test_area_base->focus_area, pattern, + sizeof(test_area_base->focus_area)); +} + +static bool check_area(uint8_t *base, uint64_t size, uint8_t expected_patt= ern) +{ + size_t i; + + for (i =3D 0; i < size; i++) { + if (base[i] !=3D expected_pattern) + return false; + } + + return true; +} + +static bool check_general_areas(struct tdx_upm_test_area *test_area_base, + uint8_t expected_pattern) +{ + return (check_area(test_area_base->general_area_0, + sizeof(test_area_base->general_area_0), + expected_pattern) && + check_area(test_area_base->general_area_1, + sizeof(test_area_base->general_area_1), + expected_pattern)); +} + +static bool check_focus_area(struct tdx_upm_test_area *test_area_base, + uint8_t expected_pattern) +{ + return check_area(test_area_base->focus_area, + sizeof(test_area_base->focus_area), expected_pattern); +} + +static bool check_test_area(struct tdx_upm_test_area *test_area_base, + uint8_t expected_pattern) +{ + return (check_general_areas(test_area_base, expected_pattern) && + check_focus_area(test_area_base, expected_pattern)); +} + +static bool fill_and_check(struct tdx_upm_test_area *test_area_base, uint8= _t pattern) +{ + fill_test_area(test_area_base, pattern); + + return check_test_area(test_area_base, pattern); +} + +#define TDX_UPM_TEST_ASSERT(x) \ + do { \ + if (!(x)) \ + tdx_test_fatal(__LINE__); \ + } while (0) + +/* + * Shared variables between guest and host + */ +static struct tdx_upm_test_area *test_area_gpa_private; +static struct tdx_upm_test_area *test_area_gpa_shared; + +/* + * Test stages for syncing with host + */ +enum { + SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST =3D 1, + SYNC_CHECK_READ_SHARED_MEMORY_FROM_HOST, + SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AGAIN, +}; + +#define TDX_UPM_TEST_ACCEPT_PRINT_PORT 0x87 + +/* + * Does vcpu_run, and also manages memory conversions if requested by the = TD. + */ +void vcpu_run_and_manage_memory_conversions(struct kvm_vm *vm, + struct kvm_vcpu *vcpu) +{ + for (;;) { + vcpu_run(vcpu); + if (vcpu->run->exit_reason =3D=3D KVM_EXIT_HYPERCALL && + vcpu->run->hypercall.nr =3D=3D KVM_HC_MAP_GPA_RANGE) { + uint64_t gpa =3D vcpu->run->hypercall.args[0]; + + handle_memory_conversion(vm, vcpu->id, gpa, + vcpu->run->hypercall.args[1] << 12, + vcpu->run->hypercall.args[2] & + KVM_MAP_GPA_RANGE_ENCRYPTED); + vcpu->run->hypercall.ret =3D 0; + continue; + } else if (vcpu->run->exit_reason =3D=3D KVM_EXIT_IO && + vcpu->run->io.port =3D=3D TDX_UPM_TEST_ACCEPT_PRINT_PORT) { + uint64_t gpa =3D tdx_test_read_64bit(vcpu, + TDX_UPM_TEST_ACCEPT_PRINT_PORT); + + printf("\t ... guest accepting 1 page at GPA: 0x%lx\n", + gpa); + continue; + } else if (vcpu->run->exit_reason =3D=3D KVM_EXIT_SYSTEM_EVENT) { + TEST_FAIL("Guest reported error. error code: %lld (0x%llx)\n", + vcpu->run->system_event.data[12], + vcpu->run->system_event.data[13]); + } + break; + } +} + +static void guest_upm_explicit(void) +{ + struct tdx_upm_test_area *test_area_gva_private =3D + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_PRIVATE; + struct tdx_upm_test_area *test_area_gva_shared =3D + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_SHARED; + uint64_t failed_gpa; + uint64_t ret =3D 0; + + /* Check: host reading private memory does not modify guest's view */ + fill_test_area(test_area_gva_private, PATTERN_GUEST_GENERAL); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST); + + TDX_UPM_TEST_ASSERT(check_test_area(test_area_gva_private, PATTERN_GUEST_= GENERAL)); + + /* Remap focus area as shared */ + ret =3D tdg_vp_vmcall_map_gpa((uint64_t)test_area_gpa_shared->focus_area, + sizeof(test_area_gpa_shared->focus_area), + &failed_gpa); + TDX_UPM_TEST_ASSERT(!ret); + + /* General areas should be unaffected by remapping */ + TDX_UPM_TEST_ASSERT(check_general_areas(test_area_gva_private, PATTERN_GU= EST_GENERAL)); + + /* + * Use memory contents to confirm that the memory allocated using mmap + * is used as backing memory for shared memory - PATTERN_CONFIDENCE_CHECK + * was written by the VMM at the beginning of this test. + */ + TDX_UPM_TEST_ASSERT(check_focus_area(test_area_gva_shared, PATTERN_CONFID= ENCE_CHECK)); + + /* Guest can use focus area after remapping as shared */ + fill_focus_area(test_area_gva_shared, PATTERN_GUEST_FOCUS); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_SHARED_MEMORY_FROM_HOST); + + /* Check that guest has the same view of shared memory */ + TDX_UPM_TEST_ASSERT(check_focus_area(test_area_gva_shared, PATTERN_HOST_F= OCUS)); + + /* Remap focus area back to private */ + ret =3D tdg_vp_vmcall_map_gpa((uint64_t)test_area_gpa_private->focus_area, + sizeof(test_area_gpa_private->focus_area), + &failed_gpa); + TDX_UPM_TEST_ASSERT(!ret); + + /* General areas should be unaffected by remapping */ + TDX_UPM_TEST_ASSERT(check_general_areas(test_area_gva_private, PATTERN_GU= EST_GENERAL)); + + /* Focus area should be zeroed after remapping */ + TDX_UPM_TEST_ASSERT(check_focus_area(test_area_gva_private, 0)); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AG= AIN); + + /* Check that guest can use private memory after focus area is remapped a= s private */ + TDX_UPM_TEST_ASSERT(fill_and_check(test_area_gva_private, PATTERN_GUEST_G= ENERAL)); + + tdx_test_success(); +} + +static void run_selftest(struct kvm_vm *vm, struct kvm_vcpu *vcpu, + struct tdx_upm_test_area *test_area_base_hva) +{ + tdx_run(vcpu); + tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, + PORT_WRITE); + TEST_ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offse= t), + SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST); + + /* + * Check that host sees PATTERN_CONFIDENCE_CHECK when trying to read guest + * private memory. This confirms that regular memory (userspace_addr in + * struct kvm_userspace_memory_region) is used to back the host's view + * of private memory, since PATTERN_CONFIDENCE_CHECK was written to that + * memory before starting the guest. + */ + TEST_ASSERT(check_test_area(test_area_base_hva, PATTERN_CONFIDENCE_CHECK), + "Host should read PATTERN_CONFIDENCE_CHECK from guest's private memo= ry."); + + vcpu_run_and_manage_memory_conversions(vm, vcpu); + tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, + PORT_WRITE); + TEST_ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offse= t), + SYNC_CHECK_READ_SHARED_MEMORY_FROM_HOST); + + TEST_ASSERT(check_focus_area(test_area_base_hva, PATTERN_GUEST_FOCUS), + "Host should have the same view of shared memory as guest."); + TEST_ASSERT(check_general_areas(test_area_base_hva, PATTERN_CONFIDENCE_CH= ECK), + "Host's view of private memory should still be backed by regular mem= ory."); + + /* Check that host can use shared memory */ + fill_focus_area(test_area_base_hva, PATTERN_HOST_FOCUS); + TEST_ASSERT(check_focus_area(test_area_base_hva, PATTERN_HOST_FOCUS), + "Host should be able to use shared memory."); + + vcpu_run_and_manage_memory_conversions(vm, vcpu); + tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, + PORT_WRITE); + TEST_ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offse= t), + SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AGAIN); + + TEST_ASSERT(check_general_areas(test_area_base_hva, PATTERN_CONFIDENCE_CH= ECK), + "Host's view of private memory should be backed by regular memory."); + TEST_ASSERT(check_focus_area(test_area_base_hva, PATTERN_HOST_FOCUS), + "Host's view of private memory should be backed by regular memory."); + + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + printf("\t ... PASSED\n"); +} + +static bool address_between(uint64_t addr, void *lo, void *hi) +{ + return (uint64_t)lo <=3D addr && addr < (uint64_t)hi; +} + +static void guest_ve_handler(struct ex_regs *regs) +{ + struct ve_info ve; + uint64_t ret; + + ret =3D tdg_vp_veinfo_get(&ve); + TDX_UPM_TEST_ASSERT(!ret); + + /* For this test, we will only handle EXIT_REASON_EPT_VIOLATION */ + TDX_UPM_TEST_ASSERT(ve.exit_reason =3D=3D EXIT_REASON_EPT_VIOLATION); + + /* Validate GPA in fault */ + TDX_UPM_TEST_ASSERT(address_between(ve.gpa, + test_area_gpa_private->focus_area, + test_area_gpa_private->general_area_1)); + + tdx_test_send_64bit(TDX_UPM_TEST_ACCEPT_PRINT_PORT, ve.gpa); + +#define MEM_PAGE_ACCEPT_LEVEL_4K 0 +#define MEM_PAGE_ACCEPT_LEVEL_2M 1 + ret =3D tdg_mem_page_accept(ve.gpa & PAGE_MASK, MEM_PAGE_ACCEPT_LEVEL_4K); + TDX_UPM_TEST_ASSERT(!ret); +} + +static void verify_upm_test(void) +{ + struct tdx_upm_test_area *test_area_base_hva; + vm_vaddr_t test_area_gva_private; + uint64_t test_area_npages; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_upm_explicit); + + vm_install_exception_handler(vm, VE_VECTOR, guest_ve_handler); + + /* + * Set up shared memory page for testing by first allocating as private + * and then mapping the same GPA again as shared. This way, the TD does + * not have to remap its page tables at runtime. + */ + test_area_npages =3D TDX_UPM_TEST_AREA_SIZE / vm->page_size; + vm_userspace_mem_region_add(vm, + VM_MEM_SRC_ANONYMOUS, TDX_UPM_TEST_AREA_GPA, + 3, test_area_npages, KVM_MEM_GUEST_MEMFD); + vm->memslots[MEM_REGION_TEST_DATA] =3D 3; + + test_area_gva_private =3D vm_vaddr_alloc_private(vm, TDX_UPM_TEST_AREA_SI= ZE, + TDX_UPM_TEST_AREA_GVA_PRIVATE, + TDX_UPM_TEST_AREA_GPA, + MEM_REGION_TEST_DATA); + TEST_ASSERT_EQ(test_area_gva_private, TDX_UPM_TEST_AREA_GVA_PRIVATE); + + test_area_gpa_private =3D (struct tdx_upm_test_area *) + addr_gva2gpa(vm, test_area_gva_private); + virt_map_shared(vm, TDX_UPM_TEST_AREA_GVA_SHARED, + (uint64_t)test_area_gpa_private, + test_area_npages); + TEST_ASSERT_EQ(addr_gva2gpa(vm, TDX_UPM_TEST_AREA_GVA_SHARED), + (vm_paddr_t)test_area_gpa_private); + + test_area_base_hva =3D addr_gva2hva(vm, TDX_UPM_TEST_AREA_GVA_PRIVATE); + + TEST_ASSERT(fill_and_check(test_area_base_hva, PATTERN_CONFIDENCE_CHECK), + "Failed to mark memory intended as backing memory for TD shared memo= ry"); + + sync_global_to_guest(vm, test_area_gpa_private); + test_area_gpa_shared =3D (struct tdx_upm_test_area *) + ((uint64_t)test_area_gpa_private | vm->arch.s_bit); + sync_global_to_guest(vm, test_area_gpa_shared); + + td_finalize(vm); + + printf("Verifying UPM functionality: explicit MapGPA\n"); + + vm_enable_cap(vm, KVM_CAP_EXIT_HYPERCALL, BIT_ULL(KVM_HC_MAP_GPA_RANGE)); + + run_selftest(vm, vcpu, test_area_base_hva); + + kvm_vm_free(vm); +} + +int main(int argc, char **argv) +{ + ksft_print_header(); + + if (!is_tdx_enabled()) + ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); + + ksft_set_plan(1); + ksft_test_result(!run_in_new_process(&verify_upm_test), + "verify_upm_test\n"); + + ksft_finished(); +} --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (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 150C0273D8E for ; Thu, 7 Aug 2025 20:17:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597854; cv=none; b=teZkQpdFTL1TvTwVdH4Di8uPIQYBNl1rbcphbv6uXgYR1mBCV2CTTJtE1Wc925+45CUkXalj2lNx/5WifKuo/mBW+GjJOtd3CUV+pIAJXU/y+7wDgw7KZNECa5vQh0rNS89cqwD7PArs10/IYPK6cppra34OkYulBdqIzesNErk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597854; c=relaxed/simple; bh=fGZK/ZXLopkNT4N/Idl0CuDWio5yEH37+0eJsgwxQLI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=G+Hn7aVGaNrEWJYa76rGLPTaWlJ5nO+e6FEf8kKH0MMb3KzsushehaZ6W93HPVbzGoa+oSGVE+v2rVtxSSucWEVW/1BIZ4zyhUc7tyceaCXbwWXooZD/AJWs0f2J6KBu0KMiVRSiFq5x88zBRVcXjnHLD+o6mgIYfHQq44vQA3w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=m9HAWPVF; arc=none smtp.client-ip=209.85.214.201 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="m9HAWPVF" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2400a932e59so20344205ad.1 for ; Thu, 07 Aug 2025 13:17:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597852; x=1755202652; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=15Qpka96Z78Ss7GgewBHLqp6k9wV1uf8bbKpYv0vf/c=; b=m9HAWPVFoJ9eOzYyuv14HEcy9qu9zqad+8Zjv7rB0TTxkhdOFiI6QlSkqo/brIOb6D ZrNZJJh9qdWrEUCMcr9DAR/prTV9llf1eo1ONkNpDLJfoxstiGU4qa0je5pE5V1gb0uG WENIhuz0gKkkBHepSWMWs0pb/r0ycevtJzhJnY6q8lrwCjOM4L9ACRNCjERhEK9UPb8Z tQTL6am3G3AWyfZuV4vK1RDK74yPAiZohk4W7IdKqB2jnrxVIE3GVt+dnQiArboZmhAg /XqF0pDqU33Q+iSmkROe2f4XWyS1IVhyYs7lpRekjuWrj89FVhHQ+A20lh6L0mW90sL7 Uh0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597852; x=1755202652; h=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; bh=15Qpka96Z78Ss7GgewBHLqp6k9wV1uf8bbKpYv0vf/c=; b=n6AOudIXBWON/SEP1VSn7F5Ai5tkvQP3eQ7Do7BxXzTWN9egTeIQ5d4zX+HF2wDYDD uB76ehZZLc5UpKxnmJB2cEUBVmbU+KWW/gRSEykbliUHBN2Uu7B4VMtl0Fcmw0U2dLKF nuCbgo5Xffdyf0Gn6uM8cYYofM5BPkdeY8jaGBPNWw9H7I7WF6bGvhy/qmKslOdfNSaX noeEZKFx00fWiJGA8/UK+Q01lhzqE0XiCXlfsY1xdQZQZSD/7Zst3xSOWwu73xwJ8CEH J+3H5tjPm+mlMyr7CEw36LMzRZp0GcBvqRtyNsd7fpsCv/rvNWR9xS8gzob46uziqQea tM1A== X-Gm-Message-State: AOJu0Yz6+mg42tJhu5g6Sbd1eZwh2vVC/2aBAt+JLk61n2Q1F3llfPA8 aHv1/WJwAlhWpOHlxHgz0qoXpfv4KX1G041XniOrE4kSV78EX3ZzQX1Kf2iZhdGYAomYj33S1Eq VKw== X-Google-Smtp-Source: AGHT+IHCtaiYFn/vLOawALqf+Yv3wNQbooOQ7dEJrMNEqHSOnJMVgt+8XOAAcARXXu+JZtBqaOY3X2QjmQ== X-Received: from pjbsn13.prod.google.com ([2002:a17:90b:2e8d:b0:31f:6965:f3e6]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:d4ca:b0:240:2e99:906c with SMTP id d9443c01a7336-242c209fa2bmr4556155ad.15.1754597841757; Thu, 07 Aug 2025 13:17:21 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:25 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-30-sagis@google.com> Subject: [PATCH v8 29/30] KVM: selftests: TDX: Add TDX UPM selftests for implicit conversion From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng This tests the use of guest memory without explicit TDG.VP.VMCALL calls. Provide a 2MB memory region to the TDX guest with a 40KB focus area at offset 1MB intended to be shared between host and guest. The guest does not request memory to be shared or private using TDG.VP.VMCALL but instead relies on memory to be converted automatically based on its access via shared or private mapping. The host automatically converts the memory when guest exits with KVM_EXIT_MEMORY_FAULT. The 2MB region starts out as private with the guest filling it with a pattern, followed by a check from the host to ensure the host is not able to see the pattern. The guest then accesses the 40KB focus area via its shared mapping to trigger implicit conversion followed by checks that the host and guest has the same view of the memory. Finally the guest accesses the 40KB memory via its private mapping to trigger the implicit conversion to private followed by checks to confirm this is the case. Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- .../testing/selftests/kvm/x86/tdx_upm_test.c | 88 ++++++++++++++++--- 1 file changed, 76 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/kvm/x86/tdx_upm_test.c b/tools/testing= /selftests/kvm/x86/tdx_upm_test.c index 387258ab1a62..2ea5bf6d24b7 100644 --- a/tools/testing/selftests/kvm/x86/tdx_upm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_upm_test.c @@ -150,10 +150,10 @@ enum { * Does vcpu_run, and also manages memory conversions if requested by the = TD. */ void vcpu_run_and_manage_memory_conversions(struct kvm_vm *vm, - struct kvm_vcpu *vcpu) + struct kvm_vcpu *vcpu, bool handle_conversions) { for (;;) { - vcpu_run(vcpu); + _vcpu_run(vcpu); if (vcpu->run->exit_reason =3D=3D KVM_EXIT_HYPERCALL && vcpu->run->hypercall.nr =3D=3D KVM_HC_MAP_GPA_RANGE) { uint64_t gpa =3D vcpu->run->hypercall.args[0]; @@ -164,6 +164,13 @@ void vcpu_run_and_manage_memory_conversions(struct kvm= _vm *vm, KVM_MAP_GPA_RANGE_ENCRYPTED); vcpu->run->hypercall.ret =3D 0; continue; + } else if (handle_conversions && + vcpu->run->exit_reason =3D=3D KVM_EXIT_MEMORY_FAULT) { + handle_memory_conversion(vm, vcpu->id, vcpu->run->memory_fault.gpa, + vcpu->run->memory_fault.size, + vcpu->run->memory_fault.flags =3D=3D + KVM_MEMORY_EXIT_FLAG_PRIVATE); + continue; } else if (vcpu->run->exit_reason =3D=3D KVM_EXIT_IO && vcpu->run->io.port =3D=3D TDX_UPM_TEST_ACCEPT_PRINT_PORT) { uint64_t gpa =3D tdx_test_read_64bit(vcpu, @@ -241,8 +248,48 @@ static void guest_upm_explicit(void) tdx_test_success(); } =20 +static void guest_upm_implicit(void) +{ + struct tdx_upm_test_area *test_area_gva_private =3D + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_PRIVATE; + struct tdx_upm_test_area *test_area_gva_shared =3D + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_SHARED; + + /* Check: host reading private memory does not modify guest's view */ + fill_test_area(test_area_gva_private, PATTERN_GUEST_GENERAL); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST); + + TDX_UPM_TEST_ASSERT(check_test_area(test_area_gva_private, PATTERN_GUEST_= GENERAL)); + + /* Use focus area as shared */ + fill_focus_area(test_area_gva_shared, PATTERN_GUEST_FOCUS); + + /* General areas should not be affected */ + TDX_UPM_TEST_ASSERT(check_general_areas(test_area_gva_private, PATTERN_GU= EST_GENERAL)); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_SHARED_MEMORY_FROM_HOST); + + /* Check that guest has the same view of shared memory */ + TDX_UPM_TEST_ASSERT(check_focus_area(test_area_gva_shared, PATTERN_HOST_F= OCUS)); + + /* Use focus area as private */ + fill_focus_area(test_area_gva_private, PATTERN_GUEST_FOCUS); + + /* General areas should be unaffected by remapping */ + TDX_UPM_TEST_ASSERT(check_general_areas(test_area_gva_private, PATTERN_GU= EST_GENERAL)); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AG= AIN); + + /* Check that guest can use private memory after focus area is remapped a= s private */ + TDX_UPM_TEST_ASSERT(fill_and_check(test_area_gva_private, PATTERN_GUEST_G= ENERAL)); + + tdx_test_success(); +} + static void run_selftest(struct kvm_vm *vm, struct kvm_vcpu *vcpu, - struct tdx_upm_test_area *test_area_base_hva) + struct tdx_upm_test_area *test_area_base_hva, + bool implicit) { tdx_run(vcpu); tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, @@ -260,7 +307,7 @@ static void run_selftest(struct kvm_vm *vm, struct kvm_= vcpu *vcpu, TEST_ASSERT(check_test_area(test_area_base_hva, PATTERN_CONFIDENCE_CHECK), "Host should read PATTERN_CONFIDENCE_CHECK from guest's private memo= ry."); =20 - vcpu_run_and_manage_memory_conversions(vm, vcpu); + vcpu_run_and_manage_memory_conversions(vm, vcpu, implicit); tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, PORT_WRITE); TEST_ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offse= t), @@ -276,7 +323,7 @@ static void run_selftest(struct kvm_vm *vm, struct kvm_= vcpu *vcpu, TEST_ASSERT(check_focus_area(test_area_base_hva, PATTERN_HOST_FOCUS), "Host should be able to use shared memory."); =20 - vcpu_run_and_manage_memory_conversions(vm, vcpu); + vcpu_run_and_manage_memory_conversions(vm, vcpu, implicit); tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, PORT_WRITE); TEST_ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offse= t), @@ -322,17 +369,19 @@ static void guest_ve_handler(struct ex_regs *regs) TDX_UPM_TEST_ASSERT(!ret); } =20 -static void verify_upm_test(void) +static void verify_upm_test(bool implicit) { struct tdx_upm_test_area *test_area_base_hva; vm_vaddr_t test_area_gva_private; uint64_t test_area_npages; struct kvm_vcpu *vcpu; struct kvm_vm *vm; + void *guest_code; =20 vm =3D td_create(); td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); - vcpu =3D td_vcpu_add(vm, 0, guest_upm_explicit); + guest_code =3D implicit ? guest_upm_implicit : guest_upm_explicit; + vcpu =3D td_vcpu_add(vm, 0, guest_code); =20 vm_install_exception_handler(vm, VE_VECTOR, guest_ve_handler); =20 @@ -373,15 +422,28 @@ static void verify_upm_test(void) =20 td_finalize(vm); =20 - printf("Verifying UPM functionality: explicit MapGPA\n"); + if (implicit) + printf("Verifying UPM functionality: implicit conversion\n"); + else + printf("Verifying UPM functionality: explicit MapGPA\n"); =20 vm_enable_cap(vm, KVM_CAP_EXIT_HYPERCALL, BIT_ULL(KVM_HC_MAP_GPA_RANGE)); =20 - run_selftest(vm, vcpu, test_area_base_hva); + run_selftest(vm, vcpu, test_area_base_hva, implicit); =20 kvm_vm_free(vm); } =20 +void verify_upm_test_explicit(void) +{ + verify_upm_test(false); +} + +void verify_upm_test_implicit(void) +{ + verify_upm_test(true); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -389,9 +451,11 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(1); - ksft_test_result(!run_in_new_process(&verify_upm_test), - "verify_upm_test\n"); + ksft_set_plan(2); + ksft_test_result(!run_in_new_process(&verify_upm_test_explicit), + "verify_upm_test_explicit\n"); + ksft_test_result(!run_in_new_process(&verify_upm_test_implicit), + "verify_upm_test_implicit\n"); =20 ksft_finished(); } --=20 2.51.0.rc0.155.g4a0f42376b-goog From nobody Sun Oct 5 05:27:09 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (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 25A26283FD7 for ; Thu, 7 Aug 2025 20:17:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597845; cv=none; b=hbqD18t3POXto/ZQ6tbPTGgwzubGWySFqN+dnv1nV3njaczyoCg7xSkaV0INKpJjPQtUXLIEqsPzn1ytLCHH265rpli9vX/6iR3HrEPGX4H/LxVqw369UClpgjMlBjzFteNP84OFpZA698X9XgW9vDMqv8SnveRkHACZ72RjqHM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597845; c=relaxed/simple; bh=KtQGB5hdsruK0bKKPNTRCRaeujSBA7S7BYfY9UZQvic=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=h2HmIQUZDHsv6COIp3UarpeFIl4Z8zLOCKch0QYdfAw7BPlAEZ4onr4yB3+aHjQMJiUm5Ee6Rbp0dr3MWYjWg2Uy3TAAzaWuvV94Kh3z5G+rg9FbAu95iGCo7Lt/o/H3mcJMK9o/l/li60PASmDyLDKYn7cy+anaGnwNn+CBbDQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=FCepqIPc; arc=none smtp.client-ip=209.85.216.74 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--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="FCepqIPc" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-31eb41391f3so1433732a91.0 for ; Thu, 07 Aug 2025 13:17:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597843; x=1755202643; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=M0suFohlUZGBEGCM79JG64gwQy4zWTa1/ANBR7d4wLU=; b=FCepqIPcGNmF3uU3qppEbg4klpL8ohYpCI1WJO/JX2W5YiHg7CM96fsTWjUj0VfaKQ I9K2XLSIReZn3cvb/0EIFUewrAavZmZR3RYWJiKnUVtNoj8J6b+M36TLgy3VM5Wyqvn6 WHdYfwOqh3GnIcHDrxhJNDW4N+J9kjPNzlN7dQV23lc0UuISzMsEFDrG2TjYiDxyfcMC MrJ/2T+WGxJ4xNdUjsTR5gr/05VFtUqHtMhXmnpK+I/GA/nAjFAk4tRtg3QZTjB/QbOI c8KseObeJjLsp+PmLOncrQ8q4n6T3n1lzbk+yfFTjnR/7QLjUQrhGpCX8yrkN4fhXOXV 7Ggg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597843; x=1755202643; h=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; bh=M0suFohlUZGBEGCM79JG64gwQy4zWTa1/ANBR7d4wLU=; b=i3qOME+H1CeIvyaCpxOq/OoJMCtGdYQgIQosbmRAbKmgngPif3XRUS96Vuy9XU/yvo FZRd1bfp+j3PsIIFtHWwZP0Tuv+Sk+PWf9+tdRs5C0p48jD8u9dOUPTe7R7CXNl1b4yz KvJehP305hUaHQk8r+A3wBBST/RmScLcWU+Xka8KBy8Up87fORrPRu21E0LchGfkBotH 1OtPqQuFHiYyS/UOKOfUV6jxnoI1Y/Q2gNObYVFXCiaM17QYSlDxXhb1Xm4ltuqVqqTB tb8DGqz14/GajCgU1crrop/X/zUKpl5B5mxHJQAOCBNoXphMuUekj5/VwSn58I1aqXrI jxeA== X-Gm-Message-State: AOJu0YwP+t3NGFmhksEgP7EJX3YXxNgMiNT+uaMpEOZ/yPHhQv03N64Q Ji/Wg60dJJsv+Y1bi4KW2bpD2aiA1uCGof0nJmMEO4ucD50aKCiQnJkN1yYFprOEdsmBqa6xPkn P5w== X-Google-Smtp-Source: AGHT+IGuwnBgHT00Pa47b7PWARfkX6jqZRvjGaZTcLQlg02HegQiirvTj6AbnOkdTgp8ehpde97Ui17D4A== X-Received: from pjv4.prod.google.com ([2002:a17:90b:5644:b0:313:245:8921]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:28c5:b0:31a:ab75:6e45 with SMTP id 98e67ed59e1d1-32183c42d6dmr441878a91.28.1754597843391; Thu, 07 Aug 2025 13:17:23 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:26 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-31-sagis@google.com> Subject: [PATCH v8 30/30] KVM: selftests: TDX: Test LOG_DIRTY_PAGES flag to a non-GUEST_MEMFD memslot From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Yan Zhao Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yan Zhao Add a selftest to verify that adding flag KVM_MEM_LOG_DIRTY_PAGES to a !KVM_MEM_GUEST_MEMFD memslot does not produce host errors in TDX. Signed-off-by: Yan Zhao Signed-off-by: Sagi Shahar --- tools/testing/selftests/kvm/x86/tdx_vm_test.c | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/= selftests/kvm/x86/tdx_vm_test.c index 82acc17a66ab..410d814dd39a 100644 --- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c @@ -1167,6 +1167,47 @@ void verify_tdcall_vp_info(void) printf("\t ... PASSED\n"); } =20 +#define TDX_LOG_DIRTY_PAGES_FLAG_TEST_GPA (0xc0000000) +#define TDX_LOG_DIRTY_PAGES_FLAG_TEST_GVA_SHARED (0x90000000) +#define TDX_LOG_DIRTY_PAGES_FLAG_REGION_SLOT 10 +#define TDX_LOG_DIRTY_PAGES_FLAG_REGION_NR_PAGES (0x1000 / getpagesize()) + +void guest_code_log_dirty_flag(void) +{ + memset((void *)TDX_LOG_DIRTY_PAGES_FLAG_TEST_GVA_SHARED, 1, 8); + tdx_test_success(); +} + +/* + * Verify adding flag KVM_MEM_LOG_DIRTY_PAGES to a !KVM_MEM_GUEST_MEMFD me= mslot + * in a TD does not produce host errors. + */ +void verify_log_dirty_pages_flag_on_non_gmemfd_slot(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm =3D td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu =3D td_vcpu_add(vm, 0, guest_code_log_dirty_flag); + + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, + TDX_LOG_DIRTY_PAGES_FLAG_TEST_GPA, + TDX_LOG_DIRTY_PAGES_FLAG_REGION_SLOT, + TDX_LOG_DIRTY_PAGES_FLAG_REGION_NR_PAGES, + KVM_MEM_LOG_DIRTY_PAGES); + virt_map_shared(vm, TDX_LOG_DIRTY_PAGES_FLAG_TEST_GVA_SHARED, + (uint64_t)TDX_LOG_DIRTY_PAGES_FLAG_TEST_GPA, + TDX_LOG_DIRTY_PAGES_FLAG_REGION_NR_PAGES); + td_finalize(vm); + + printf("Verifying Log dirty flag:\n"); + vcpu_run(vcpu); + tdx_test_assert_success(vcpu); + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -1174,7 +1215,7 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(15); + ksft_set_plan(16); ksft_test_result(!run_in_new_process(&verify_td_lifecycle), "verify_td_lifecycle\n"); ksft_test_result(!run_in_new_process(&verify_report_fatal_error), @@ -1205,6 +1246,8 @@ int main(int argc, char **argv) "verify_host_reading_private_mem\n"); ksft_test_result(!run_in_new_process(&verify_tdcall_vp_info), "verify_tdcall_vp_info\n"); + ksft_test_result(!run_in_new_process(&verify_log_dirty_pages_flag_on_non_= gmemfd_slot), + "verify_log_dirty_pages_flag_on_non_gmemfd_slot\n"); =20 ksft_finished(); return 0; --=20 2.51.0.rc0.155.g4a0f42376b-goog