From nobody Fri Oct 10 09:22:17 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 256E123C8B3 for ; Fri, 13 Jun 2025 19:14:14 +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=1749842056; cv=none; b=ZWf035phnvtCe3XStyoWPxxG4WV17uzpTzVZvye6hxFvCFu00YK5lFyIS27hDR9EwrlZfKB3Re0yAYfhApqzgXPCGsqAKv0J5DkvJR7n809yhEuLnl77WYT4crhb51hFmoFQqQ7iyuW3/+mJ9sF/pehP97iE0iuK/0YDGxPXgCc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842056; c=relaxed/simple; bh=QuoLs+Ux/84Fr9p1idJvfX2ZqaXEeJLcVJ7fjk8E1lI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Nj4J+3/Rsku0LhC+LhQOwKMYuy7SH6ddu59cJYlUJBPDBxS2aus4N5HEXmVwBXYOjnJhVSVeT+p1vvrykP+rdlPcfInTvEFQ+vxNZynJ7dR3a4kMg0425vNdqo42TwQd9m2B9tCPCTxGXa7uIAJTvfgBbNDsKF+Zyu4MD90Hy7s= 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=wUCMjW9H; 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="wUCMjW9H" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b2ede156ec4so2827189a12.0 for ; Fri, 13 Jun 2025 12:14:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842054; x=1750446854; 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=+8nR6zImbEfU50Eu9z3twsYvD96Y1yoYJi3jd8xgLx4=; b=wUCMjW9HOeW8D41iioeTYFGt1Noeodi/Am/DeAmASpS7iuz39bQOynq6ddWI3W6IhY XWlLQH/nFWL5Bs1xo561bKjeA0A7atEJ9TFzkWo3/opnnSLX6jRh7gp0Pkyo4sE5+cOM eVMz4L2y6apHpitZ3/YPmi1vL+hj4u33Jiae1wCPP1OWVZGByywP1gbAlHRNYD8iHwV9 WCcTFcmQtVfYQ4neaiOpu59IaQcLlbau7Cwu7Hgl9S5w1mC8M4cGSIVUSBwDjb1MKfMl l17+LlPxH38TlQwn9mLdVec2K+7ChFX+4k7mhDDFZWpWdyVJKZFlV5jULWDO8dm24dXa Xxxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842054; x=1750446854; 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=+8nR6zImbEfU50Eu9z3twsYvD96Y1yoYJi3jd8xgLx4=; b=HXzw09fz3vT8J0MYs4OVi6hgQVuYNF9ZaCsFeunK4wbbr+CQWagAC25usNo0P+zNN0 dpd7vadkGxF+Vw5fx/hzl6WqS1YG2kID7zCajNVanlezG6/WS3/VuIb7JgJjy20aIB+p h8npQh6dKn+cWjoK6RjuP6Jh8nmBYkiWUpiBdmHjBe0uuqjc6+OePkFPpDSVzHfbwPkw iFncZjxaq9CQ3U6h4T01vRrkzfIjhxaUdNX5Mx3L/T3MoIgckQyH3zOglri3uROLFKMZ hpZ5H8qLfUmGE3Q/7GoE+77t/SyDG6ISnk/LKVgMVIgnTaAXXXAohK8wBMehRznuDqDB aGug== X-Gm-Message-State: AOJu0YyUeL0fDBiuzbZuFEkkIrPLr2LAdTmDhJkBMi8b/FTyg1UXouP0 is6nLAL1G5T1Jh5OHdR1ihroH8XZm/QvMyQ3dTPSFNi74TAEmx/tYzxQHyvTLUcIYDa/leIFnjT xvQ== X-Google-Smtp-Source: AGHT+IEQ8vV+FXVD3XBCjRhMRewZ5yjQ1j2sph+yUOFNhR655zuqbYE+7ObmNf6VZS8HUTBkCOPm+HspBQ== X-Received: from pfblh20.prod.google.com ([2002:a05:6a00:7114:b0:746:2117:6f55]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:513:b0:21a:de8e:5cbb with SMTP id adf61e73a8af0-21fbd550de1mr661897637.25.1749842054156; Fri, 13 Jun 2025 12:14:14 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:28 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-2-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 5724924169B for ; Fri, 13 Jun 2025 19:14:16 +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=1749842057; cv=none; b=dCPVkSx/Ygba7PaIRei7cY6NEatylJn2tqgMA8qUL3RaW4eO+Yi3T1Eh70keU67DvrqsoPVbMQUG0D176/bpnRhrce6B1eoRay35FVmY5j9hxaBLDiw5cH6VZKM5Bm4uUNf/aE5wM98JQZ1cZg+UHEArhUe0moREUchMgM6Z3c4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842057; c=relaxed/simple; bh=y/hrB1WH2W68tURtle+cVWCtRB2T0n9nfcp8qRvBYpI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=mStWgiORP1OYxibxdIEFjZ/Bg+HMSzQ5GC0OPKzn4nV2/orW4DlsXgLPw+/PcCiMJrK4FmX7wTKPWjFrCpw9ifXzOFbyIkti0KHQC8JsEUe74LgFTammIdjKIHy41opv/eG9e5QRKs9aYkzGWnS2zK+XCsYncmLQyxdfjDd+4JQ= 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=xHlTAdJW; 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="xHlTAdJW" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b2c37558eccso1820360a12.1 for ; Fri, 13 Jun 2025 12:14:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842056; x=1750446856; 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=vOmgMRXV+mc8xC1osg2zhcuISDjyHCoSZSrFaYvlLLs=; b=xHlTAdJWVPSS5wdYQH8WRX9r6pHX74riahODGrI7rNJB93QNzLn0UJ+4grsHejCos5 eEtTjCqxrPL5SZAB35Y3qO6gS88IhOudQPaqLg2KJ4HsWoAK0Z2/B7h/hTp2k5Y2jhpE x5BCS6yqC5wD2Mp0tJGZO7brsS19eTrzbKJ/qZUdz/0JpeAF6n4H9CvTxtxt2YFWlbPl O6ofIQih0Qs8bdnA8y2TxOLNZ+kaxpP5TGSd+h6bu4tr3/kJ1Ph3sGtJuDLwjV+LqYGW 3nFq7OZ22rovxFWJbmMfwBSxiFQI2605vV/5XTn9VRJ5xzGs7E4riLvFSWuc254rgkVh YPKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842056; x=1750446856; 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=vOmgMRXV+mc8xC1osg2zhcuISDjyHCoSZSrFaYvlLLs=; b=bDJm4tP+nhg5Wp+v+aGmlupsehqvuLiUjMurs5AaSk8WMn11TVneQNNHJDGB5v8/V0 Skpe0+7NiLR1plvaYx4uMjYBYVfUtj16HS5v6/ekpXQn52kO8hpyWJRN+vF/nclHXiUR Se/6BPfdPR5FJCNFekcYIeom/B6JsLWuT/7CWLONADNRRCxw1X7jiGNCqhGFwHYXnFCx 96osksorHGmwoSkP1pfuro+6s2VbdCF3ARmkLUCw1OQnyX4ccGE1ftmZybT+zZbQq8Qw xD8m6H9UpwAiBgeg2BCjv2khsNimxneKXBwdP+N+s3STGD0QAfxpQBcGzx8If2/LHkXg cijA== X-Gm-Message-State: AOJu0YyJIQN8iMgrghsFQcGztbLfkrWfb+P+ID+9wUDoX1LwW5Cf+aA6 Vt06CqBs6hYrsDz7em1dsv/LGGA6J/x4Kf+8JdPswpPSWNDjgJpje9Cb/+PYvzp+FltDt2mEDzA c3g== X-Google-Smtp-Source: AGHT+IHAhgpmm/q01FxLsxN/r16xAnrj+YeQUD4vxuoiPdSbJLlzwjizxPtfCy3TN+V0J86WsXFecaW5gg== X-Received: from pjbqa3.prod.google.com ([2002:a17:90b:4fc3:b0:308:6685:55e6]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:3d43:b0:313:d6d9:8891 with SMTP id 98e67ed59e1d1-313f1be1d48mr1058480a91.3.1749842055693; Fri, 13 Jun 2025 12:14:15 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:29 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-3-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 DCC1524DCF0 for ; Fri, 13 Jun 2025 19:14:17 +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=1749842060; cv=none; b=LST/0zXkhRPuabia6TvKDasQZ8iu5d9GBMIaRb+LLizOSrlsGO8UEhADmTKwmcOhuCIwUZOfY/QgnjlWHyplB7fTacB8HeSKyHE8AnQCJe55/Wu1KPAfpooV8LPH7pU0sQaTRw0PS4oME47G5OEmf0g3LKDYzo61JW+eMmS7AOU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842060; c=relaxed/simple; bh=CZWxcHUWIhBEiyWiB8Z0zKn1NDMKTAMio7jW/0D0t28=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=tfz+RjSShweJh9jPijVjbvKOyFdAEunuiLE2Ao8UweekO3WBnbGEbwNUX60vn2ruHGcz/TWOD1NicaghZIELnAB+X17SCB+IA8jcZ8MhIO70ZsVf7zpKC65njOMl92M6YodE17sAYH2y0cuMXrfCNfM/9yxceO3ZO3spM5tbbKE= 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=xWzCelGk; 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="xWzCelGk" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-3122368d82bso3477074a91.0 for ; Fri, 13 Jun 2025 12:14:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842057; x=1750446857; 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=eGEpLUgqYonvIFbVng+CrES4z2xij5mJ0NWE1vzcGwk=; b=xWzCelGkIZ7DRH6ns82atV8v2tof31E8Eun95Ns7Z58js8RBx1UmOwMI6Xd5LANNjH 8XuZJwcdrGRMRBvvonc6Dbjn02EGZcgDShh4M6pmSeHaNDcDa8UKeplFzTt+js7pFlP9 ZYazBoXiOcDvmNUVhEsKInSj/2EjksOD8bPZmFDQWqY+osTNYOhQC1Yk6I/8c/Pf1Oi3 KS1ndoObwWcKA1FULqJzZ1BCjftrbn/FunB0xlhbua6f8lvK8MXpDY/H+6zwnlWOwP91 sHfy1oi2wVtmIgDBV+VGrdLGC45KIZuj1bpma1fZM0WiqahXbEz1qAzIIdWYPXdU7Pl2 Bm9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842057; x=1750446857; 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=eGEpLUgqYonvIFbVng+CrES4z2xij5mJ0NWE1vzcGwk=; b=n8GcodqZrZHB2s1JvtnOrB0qFEFlJWjrtbWnz0fxFcH3i8oKsDp/eK0cRjpGnhgm5n l8hW6nb35cKbRFjDSgW76XyjTtdtMDUdzyoKFODjql65mlkU41RAXuN6VNh0ASTc/XSh aB9wzp2lGAr4vDH7KVCN9Nt9kYSl/vLIm8QcCZJyNnlSrtUOZcrjeH7zfrJ1xVpZXcA4 EA6ZFWVsGbOk9Wns6een2FLfUtXwGQo/prQ10yfILfwPewot9l8++mYuMmGw++mhV7EB feVxmAr/t081RFhVVdln1DTqBsmzlWoEOpKxPza1jE4rrJBaf9Wub1NMkg5RMvKVsiJg TMqw== X-Gm-Message-State: AOJu0Yzfhsl/7ljdfqESYNI6RJMhP50lHu/wQcFx0Co2yATBjsmbr7QX /LP69ikI43+yHAmE2Mps+o2cWl9iWF/z75ofqZTv1dgCb0yLSjmaL5DWQO3e0GAlRDLOlvJpBRQ ucQ== X-Google-Smtp-Source: AGHT+IGT7zb30UgV45DG78+lDcZgeztvaDSS1mxGV5acscZ5LWb0SsPW7nfVbgggzN4Y8RwiM+4/xNFPgg== X-Received: from pjgg14.prod.google.com ([2002:a17:90b:57ce:b0:2fc:2c9c:880]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:5284:b0:313:db0b:75e4 with SMTP id 98e67ed59e1d1-313f1d2a17emr1364010a91.33.1749842057235; Fri, 13 Jun 2025 12:14:17 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:30 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-4-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 28F142522BA for ; Fri, 13 Jun 2025 19:14:19 +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=1749842060; cv=none; b=govW4UG+WJLCpjKy74s43yfrNPhIrthl1maYTr1GVnjyWbEiXkDtnjmbblAXErJEB0CmZhpqeeEkPfi2/uSL1njfQP7oWUJrGTXwy2Gzh8bSGmwZp9UInmbZ9l0ZOrNDY1HUV1fwjALYmXhLshj8WUh+3eFZwnt8ESmCRJBHAQY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842060; c=relaxed/simple; bh=rcNojIrkKk71ZnhBfmVVb45xpOUbdROsZ4vsY+fOfXE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ce4KWTWG8BpcXsWLfa7tcmCOZEbhTmZwHea7SzJYRnfQqblso4zCcCoAET8yk/Oj6Ee+v5q3lqbeWIglhn7v9ULjeuM5j5daFp7/z0h7PC2lMGnGgWwesWl84Y5I7EVpgbwD98Eh7HA4Y5kkP7avYwbuK1Je1RqBhk47KqBLCt4= 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=3VVGb4jD; 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="3VVGb4jD" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b2f02cd1daeso1712001a12.3 for ; Fri, 13 Jun 2025 12:14:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842058; x=1750446858; 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=gcb9ynWPHJDnOBsaC+w2WlTETP9YsMoWaIZTF4OWeus=; b=3VVGb4jD0ht45eFYVRBwyFPG+6Tiyius9NlrGnIVY+TPsyeXbLgurSUjB+gWr3/Xy+ uWy2Edbij3ynqh6p36w5D1RKemjO8O8YgfthsuUZvAVtRkBjOn4j3sd23DOmMEYmv3Yq lSmwMFisjypvc8HHBOnz0R4G8v3+jQZ+Lcp0IcD+Ow0awWMq2eBtHv3gSC2DWFvJkWQr M+kkCBtemAqzmyUnSFMoiPHseB3PbxfPCttIqrCBNI2homAQ3QLfW5cDJA8X3HeJdzZc iAgbXSp7LVgQ6z5ZSwolAYpdZbMjUsbxJbaYdLEpmyOyQkgYuO8WZiGD79VqjdYKni4M hcVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842058; x=1750446858; 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=gcb9ynWPHJDnOBsaC+w2WlTETP9YsMoWaIZTF4OWeus=; b=SNqo+8KuBqPO7t22UVGilrlk1h2O9RQJ1j1vgLDauig6YQTPYRJmD4lMDNlgw+hUyB WHqy6iii1oKCaelMfcGSCZTmyvF3aWNnMajJVhuGk2Vmqjtr2e2oZSrC8AWW0Wi+Ljdl 8T+ltcktEah3xOaa7RCReQXSlOn4QMuQtRjIBtdMOybwveBcQMkcqFPSCHV6DPDMaPDL JwUx5kgbjCloKhSUtxcu5eWiay2sGJlqE8jJKrOwPuXxvb8qtEjPCJvyoKziUOyPq8IW u1x4Aaas4UirmixFRQIEeUBLkKj5JJ9ELwPKvrSc1JUz+WbHzUR+LWCchhf86jR2tUPg DlQQ== X-Gm-Message-State: AOJu0Yxzm7k2apKHU2Ace0/4MAh253heuiBGS7z2wGhyQ0R/DYL5a0gv 75RQEETeULXEr0GF7w7ke7abW8h8SpjiPW0StvbDxNohyn8nu3rFfn25kZgeCT4K04ra0uWQGWo 33w== X-Google-Smtp-Source: AGHT+IEsw8JvuYmpQZvLNlubbPq4JN8tgwPDg0ZH3gf2iYtNn2ncDksTRsRAcT4gWuA7GIhv67eR9tNt9A== X-Received: from pjbqn11.prod.google.com ([2002:a17:90b:3d4b:b0:311:4aa8:2179]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:5250:b0:312:1c83:58fb with SMTP id 98e67ed59e1d1-313f1c6f67cmr1129215a91.1.1749842058508; Fri, 13 Jun 2025 12:14:18 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:31 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-5-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 AB88D239E79 for ; Fri, 13 Jun 2025 19:14:20 +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=1749842063; cv=none; b=ii/UL2wDSBUIsq1h4OiI2KFRi1CJfqITcskWdquuMD66HUSffzXVIusSjl+Z4fXfgoL0UBxA9vKGriHLPHeS6EJYLzsi1i7DcSibxlsx9ChjHxR91dFmyMl2mkI0Wvb685sJ4ucQfzg0eWTrSR9E91khIaLEhDtH+6AaehBEkIU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842063; c=relaxed/simple; bh=WuNQeIEjxP0MpZ43wQJ8QH7/E4ptzd6ZC4ALnAIRTio=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=VZooaQ+h/6efCwoSRNnlJuGsng6m756Lvt4K154+gv9dJION+pBLIjcmCf4lKbCj1Eb2OWAvMcDuXFPBqTAZArxTKQ9Vo4BA6BhrMgk+Rc2iMn8tx8zBaPKtyH8mXoqyawIRJgD8AUPrCR53OqpA0heeWpfOLPM3T5BSX0qSayA= 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=Kez1Vmlu; 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="Kez1Vmlu" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-311ef4fb5fdso2104833a91.1 for ; Fri, 13 Jun 2025 12:14:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842060; x=1750446860; 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=lK8PSoEGI5Kbvnp6kPiiz7QOvkRIGce991kbDt0U/HU=; b=Kez1VmluuKC4Hhsc58tcbMt3SFtDCOg+rO6quYIdNFPBDKxRK7EZosIZPiS1gDxSsJ QibalauIbXzcL5Txt8fcW+4jUO2ow9riW9GGrV6/sUZL21K5Mqio9AHha+KVA17/8YYq gDvRcXkEn1hizdrXuH922dysA5e6Wy5U5/gJq6F9rMC+CsCRagNAfcilGCdg2fVaBjXu W+1AG4CuQRAs4mLvjhMeuYqqgvIoLtHhFTJdw3QOPujfA5sNa/cgnqtLaUGLUdL4zIAT KLFarg9edTW1f6bmMr1VN2dRJHBKdP5gJKBilHYDxvannRyFV1XJNgO1pycjyxKTc6he K+/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842060; x=1750446860; 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=lK8PSoEGI5Kbvnp6kPiiz7QOvkRIGce991kbDt0U/HU=; b=YXQBoWvLY21Xoy/V+wMWd4dNxvorVqLAKnS2zhZykIYhYQAs4wDjjZm9LNiKMReyzP zo/DlfqXUBHGBRgrnqbxVlQVak0Y3lasTky8D19fOg5h6vrIRXTjb+DSKFZzX5oF92Av UdLHfIJs73LickKhRpdfRASYiyG9tHImbHNDy2nO7mcu3uIdkLlFeVMmeRNF3t4hX7gu HKLxPocwjwNgw02jFl4DfHDZT1ejoLlRSOSy42FI4iMNTq9ulBxQTiRF1rt7Lk4g/HhO dDupEZa//A8g9pMMn9xyP4wsquTRqLVQ+awJqRCdgIyE179ukIKNrg0+5e2n/8qQ78z5 fS5w== X-Gm-Message-State: AOJu0YxQvSECTrbb5GBlfD2oU4l6olRJeI10+tIDNOhQ4dryTZFL0l9c MIrhyJxuFS2zd9/dcMv1HDQ6/T9CXjs9HGmmfk0j9rxZcePuLTGiSy2FVUXunKeaLWLbcqzlsi0 ADw== X-Google-Smtp-Source: AGHT+IG2rnq08o1rOOulMjf3/xAjuyKFVtU58bEMOUg+186GSEJdawuT9DZLEd/V6esV4Z1DRz0RGaOAmQ== X-Received: from pjbsm7.prod.google.com ([2002:a17:90b:2e47:b0:312:f650:c7aa]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:3dcd:b0:311:a314:c2e0 with SMTP id 98e67ed59e1d1-313f1cae3b7mr1173552a91.20.1749842059954; Fri, 13 Jun 2025 12:14:19 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:32 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-6-sagis@google.com> Subject: [PATCH v7 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 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..d9f4ecd6ffbc 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 104E925A2C0 for ; Fri, 13 Jun 2025 19:14:22 +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=1749842064; cv=none; b=djLrI3momc08tADlFZ7HMuhf+wr9Clwi1TJHWkLI05+iWzY+NnuZqNoFiUSsWXb6ZCWRH6YybV/XPBqC9uW371CRBZcyfLEwYRloeBPfRgEUEd3Bf1Rh62o0VvTFPtDPwbaNDucwyVGSicOxIEoG4Rr1iHTg97NJu2Yn6v2K80c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842064; c=relaxed/simple; bh=OonyLTR3/swd/U1Mmwwgmw5zqxLheIbNAF4jVd/qgfs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=oiYhRG/sJGdYbvQ6l9JUMWsTfyhA013XL+e5okHVBtjjUE+BG9ySbZzVPq1FwFgkQJUpbSnCMMpc2wEChzTy+VbGUDGF2XP7nisj4xSrD2zgzVPZy9KkOemZERqY+2r1jaYBWoR8t31jJbwRNufuKu+TDUDCg1QZOs3VxzX9J+Y= 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=JVsc0EWi; 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="JVsc0EWi" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b2fcbd76b61so2298897a12.3 for ; Fri, 13 Jun 2025 12:14:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842061; x=1750446861; 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=2UcojkCHrQxtH5hldlPMr9j63gRaYxzXi6/8ZN/k6QE=; b=JVsc0EWiG5PnOnYEw+aWjQGBl3WkDXzGkz9Vy6T6k4GSylHMTnwOhlw9PeD0oIxykE CQ7fqHnjgT5Fr8NXh1vas4mpcB2oRU6pFzAzw0MtUD4WGn5ti46DccTUbadWLGqBV8jB qvO8CaoMSrJHavWpQAESFYkQq98qmFhOE6vgzZOIoVWkRiBQzPOwvCHcqLNC6HjU/N7c KttVIGjMCP2+va/AsGnMlRFtItzNDk8RykfvDKx616lTggLZT3/Q2lIkBR/n7Nf00jpf IZdV4K+ykKm1gu+hPm91pA29vAUEEHGpsxCF2c5sYLxSLxZOWDTng8sHyjGO0FUFvT1/ frww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842061; x=1750446861; 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=2UcojkCHrQxtH5hldlPMr9j63gRaYxzXi6/8ZN/k6QE=; b=T0ujyfC9X7I2Ys42+idSVVpIQdt0rQgi4XUdFmUANGzWF9OdH0kia0py0WVeI/Hgba or75ZIh2ib7sRniaQc0hlozZObb8DVyT8rPMsBizrJiph0OtlZo6mlhjuzcroM/fqu10 4K8lE6uDDUYLg69OlnlKCIS8Gwzm65D/PkgM6BkvvpTNQ+qdYOHNaaClzaoyzIJdU9/K clFTmQ5Ra9R00ZOZ03cW2hyijNuQwAxw4rXjulNIIuQ+A7ByyglxZqn7viAW7t85XoIW Uahc87g0DwJjTmlPI+VjPo5E7vOCvVV0O9a70WZuNeHua+kNxwEHrmHVxu61HesxYOtX gQRQ== X-Gm-Message-State: AOJu0YwtaxZ0IpiteSaAG5G9rVv9EX0ciucQNfUsT40ruSxtmbGizK3W OiFdlTf9PlTtqRBMZBE84Tr7cbDpnlYg5LOfb7yj++KqQW6dArz+76zkUhA/JGPUM2y0DILHlvc 63w== X-Google-Smtp-Source: AGHT+IE5eF+kxb6VLiE2fNkSUDgpls4vOCLtVr5Q/29gPedOOB72vxfQCXU21zJ/4QF72crD7AvLY5JwTQ== X-Received: from pfbko19.prod.google.com ([2002:a05:6a00:4613:b0:746:18ec:d11a]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:7702:b0:1f5:64fd:68ea with SMTP id adf61e73a8af0-21fbd54d5f3mr685924637.4.1749842061538; Fri, 13 Jun 2025 12:14:21 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:33 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-7-sagis@google.com> Subject: [PATCH v7 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 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 d9f4ecd6ffbc..ce422da10f50 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 F0F85275B09 for ; Fri, 13 Jun 2025 19:14:23 +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=1749842065; cv=none; b=MBnCEav4Wr41DguHFzskRbpqkAcMFnQsrcJUQ08WsGZJa4Xc/e00A2MVMKt32WQbemKVeDGZFIsZFlufXTXCKHpo8okC19/KyjcoraeIiyjuJrHD7UYCM9V9ke7Y0vjGQN3f+kPE3x6rIpHPSAvM3C++eqe+utImQuKzGCCQ8Hw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842065; c=relaxed/simple; bh=n+34/TQnDhQUpWV9zBPtETMCqc79945QBOwUvQHWJuI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=nK2xfCxMAPDsvOATT3pzLvuWPsWTUyvbq6gPiOhqOy3nhrlBL7QDVjrmejwrA9S65PIo+GuqWo0hCa/K7CbpFnkjRjF2RJbIiP6Z4PVltJFbGsv+1tECJnjsGwGk2gybBTea1rFLQnbv2T5vJZfNkKaoaFMBVQjPDMPjmvT4YgY= 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=jb/G19Au; 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="jb/G19Au" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-311ef4fb5fdso2104846a91.1 for ; Fri, 13 Jun 2025 12:14:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842063; x=1750446863; 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=KKvGThASRp3H2fuQgg3irPPgWW1C0TLSvPp1AQa9Mz0=; b=jb/G19Au2VOTqbuMe9VbDT9Wgc5PWcD1zc1vNVEUhsFj9L/RKJ2FEEdvvTi1sdlQCp xGvkT50H4aCGT4VMDCfRQBWOoYF+Nz6rtb6BMnpFt1EpzDsAb6me0+/ZO4K+ruwNWcnX wyDbQhNHMlbByeYcdwOw70iadNJO0xARyTxWs+FIfc1OPWmsFfCQiQET35FYuN0Oalpg BzOPCpIRpjms+1pf2L6ZPKGBrQuyljCKTxb6dUjdahyduALLMIBR4w7x+c4Qx4dYE1z5 lvVmRMsHI72iDH4hhaqCZXD4d0UfEocfO/7JRYshQyvVcyN9jcguinFA48Rl/kFN0oDp naUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842063; x=1750446863; 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=KKvGThASRp3H2fuQgg3irPPgWW1C0TLSvPp1AQa9Mz0=; b=eVAVMayu3uWx8+0xf4hN5CKYqbzwYtYnkOq3s2cs81FNYjMjiaky/A67axCLv3+FjM fbD4RHplniuJKmLqU1pcbRkdx0Rzplh851oLNlIcTHUKI+dI+ht72jfjMGL2OQxkWev/ zYwp4gkK8PsqPrbxN7ZnMmQltkBZ/PQ3JmL4qgOuC4cQBPNYvJ4zFb4Zh77z0ZJ7t8Lj Z0RiIfzBNz4Xg/C4gte1tWo7E9qAV355PYR1lh4uLaxLo5MEO3PMFB1GBFJwNN0yf3ir 3YdpqQl8xAyeHz9/spavepqNqHTEWZzocdv3Pn/+6ML+jttbrwwH95IrkkPHN04MRgdS 0mqw== X-Gm-Message-State: AOJu0YzhsUrkPMFhL/lUo9g/WX/Xulk/XoTSh301DMonGkk99azwt1JA PwG+FM78TThXQvc8G5gP6rPHJcMeGTBIiLUcu3FSpxhEITVIER/gDw1k9pkqk6Sui+pORIidgg8 GzQ== X-Google-Smtp-Source: AGHT+IEBcUSdKCdQQyJat53qjznsfsYVoRbsmkBiaiRjdIDqSqw1KmSy96Z3hS82BrR5/3y0caOOvTW4Pw== X-Received: from pjm11.prod.google.com ([2002:a17:90b:2fcb:b0:311:ff32:a85d]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:55cd:b0:312:639:a06a with SMTP id 98e67ed59e1d1-313f1d0aa4emr1154843a91.31.1749842063073; Fri, 13 Jun 2025 12:14:23 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:34 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-8-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 63FFE258CF9 for ; Fri, 13 Jun 2025 19:14:25 +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=1749842068; cv=none; b=kKPAfT2V2D+zuajGn89FGZrUIh9w09y5GfKK4v9k/dnfAkhZdCVIIACal+uSuWSMFSmGdv+TQhiB9HcUiWnA3Em5ed49G79Zf0Qz572IsgnEcYXVtQ6VZ4/mXoxV1FzrUy9M1Lqqu4EFjRiPlgszMPwvLDfpSTef9Boglqc6c7E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842068; c=relaxed/simple; bh=KcVmSP1z2F1a4ltip8O2m08swJFdtWWy+j4vG4u1hDQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=mxzQfLNlhY82Bwp5+HN/NpcoYaa2By9EXyLMt1txYpwP1pT8g0DcO30Pn7PJPKgMsnPSv4hEvp1lmqAna6LsNovcmLvepTMygU+tdfa8R3IRoyj0SOEYP4p3rsHSKJwEi2MxlymFotV7iXqRKsmb+XTcJkjegJXwEB1cFOu7EAA= 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=T9mgj1L/; 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="T9mgj1L/" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-23507382e64so22352405ad.2 for ; Fri, 13 Jun 2025 12:14:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842065; x=1750446865; 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=8AuGWyHRN5gujSVF8K3xVc7oiFPlkN5tzT3tBT+wdnU=; b=T9mgj1L/4sH6Wu09lsHAJ5Ukx3qoJyBYHvHzsnwoZqs86XKYZioxfi5Sq2mBoDifVt 3wI4f6o3LrjidLCq3oETimLyPz+ysppwsMy9LpenI+5d95Zi6S/hvdfrRKCTlnDs3SgA eQVtGH/JiRnl84re/8diMaTwRwSYyCnAFbT+cCLNel62ev/yxgSg2ol+ksCdrLiCy7An P2bl1R5pE8F9Rn3N6s3sQ7Q9TSUwnRC/y12F0M2MZn9/4D4cNSnagzJ6DDyr6dcP7w6h 7TBQCz+/VJfTovANygYhsKFTrFs7tCGzPJTqTuSeS0qq97olhnHP7vb5Svvb8RKKLgJ1 gP0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842065; x=1750446865; 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=8AuGWyHRN5gujSVF8K3xVc7oiFPlkN5tzT3tBT+wdnU=; b=YnZHZo3rLIZp4eaNdr/CVxNNvpbmp7VT+LW4M7PQKYNbl1kfMkn+IjOUPpZbFOYLyA QoYGs2cCIvy9VNtautc/0wXzKhHR/WjLU76Uv8FrIDNweQ1M6nDOqjjMrgt/1RAMtDAS cKQlC7nJ2nSFLKVTSIZC/tpyAKlK0NHs85/PYqw5wMuCrstdliGhCIai0DhF4cpjHZCX KzhsBVWcX7uZdMvGAGRVy6dpPgZjFBRjaWQNhmz4hwwD3m32kn2T+W8pw9GweaDMLlQC bdD7MPmv5ROUQk+QpYkOjXIYsExtutd9hBV8pf2C62fwvpcKfzutzXvXQEW9euLGwEVi etQA== X-Gm-Message-State: AOJu0YxZKVLDvc31OgMbhNZQC+uYy1I5Enj7zag05zTathBTNafEhkUa zkiXS+mgoRTOf+lm8D4wmVwZfiTZIP3r7vCL5RAVj3RI4TefU7M3J98FS0zeb2vjZrCRu4C+lK2 xxg== X-Google-Smtp-Source: AGHT+IF18P5p08M+J/Joy/4/oVDXDnwIzpUjm+DY25LUCmL9I7E9TjnRyHCMNZ7btIS+DLrs42822fh7aQ== X-Received: from pgbbo11.prod.google.com ([2002:a05:6a02:38b:b0:b2f:6681:1f1e]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:c943:b0:234:8a4a:adac with SMTP id d9443c01a7336-2366b32d048mr7098285ad.20.1749842064612; Fri, 13 Jun 2025 12:14:24 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:35 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-9-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 C69C2293C70 for ; Fri, 13 Jun 2025 19:14:26 +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=1749842068; cv=none; b=BaR+mH8GQ5CTgOajoqBJgkpyK35U52m6WMvL5gRBsuO6yUXbDpIWE/9sSxgdNYvS+YGvQMVvpoHBCUqMR8qmCPI3OOTY16BmKuZiLRnGb1eJ8B3gdYMbDaM/9B+3b1dixWb0bIRrCP0pNqyJahdaWb/FMIYV1Mf/gH1ZQMb3JSY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842068; c=relaxed/simple; bh=FcmIlUux67UGLiz8+1UiQqr3crSpqFAxAYrBNtt9ZEA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=T9Q+k25WBWfQNaGB7YQIvlhOahQJURx0WUn0xF5EQVvaso1QV9n+9yGkhFbiHSbcUH28WmpXNUCUy/beHUMdDXicVDGGJjrXQAORAHu1+okAHCXeJ3FUjQHfM1ZNqBlM/LPkv473S4IGLqWvhHd2Mi16Thk4cUP9C1aFSVxXJZA= 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=1c4igUWq; 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="1c4igUWq" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-747fa83d81dso2150824b3a.3 for ; Fri, 13 Jun 2025 12:14:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842066; x=1750446866; 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=L/f7eHRsOcl8TGxBm/wAVYEHHS0nzB4uFx/d02MqorQ=; b=1c4igUWqUSlGYZh/diCVCYmfvNvUIG6axZrL+zUocIvxGWH6MKIYvbxpBy4qnx9qgd 0nwQ4hM+g8TNSdGrnj3gu8nOP8vMaHkqq0MOgpn3qvI/2RCj+g3aOjDKT7MwaxuxbfxF Z+AGJPcNtZo+cJNtUPnOrfiSzWKWrwiNPuTgm9bfzFY1QTMp2AY9dlYfK2mvzxsKcM5R UmwR8LNnrPkxNCEFrvWAAOPEztE6kYUTSScHYC8EwJA1IhQlN1ib5hUP3QLqeeiJD4tw tisVHtc6SvOdSD/rfTNNx4q9riCGbYJkfV5MPW5sXD6bpvR48RjUlH1JNvSP27LpyhIn iLww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842066; x=1750446866; 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=L/f7eHRsOcl8TGxBm/wAVYEHHS0nzB4uFx/d02MqorQ=; b=EMrdKHjlOyNDm4y4V+N+xvr/I109c8i58XPEinm8uSZ4rLmpaKXSZqjrzGfIZKZ4wA 6NuedkfiLIr8jWb11BtTbMTcXzxQfV+QA+fSi+frZNMysco+PNw51+v5oOu/xXb+BXLG qbUrkAF+zChY8ZzZq6F+6lvnQGmtkLKE2Dk2jQ7umtIJ5Eeo9KBjHtssIOaVIbuRTss3 uA2t6Z3/ojYnyo3/u5YZSz/ubUn5FCmIP4TjDM68tdHEZN+2ABOsg6u6M8rCBmDUK7go hcPAalDCaXExf0HHJrpIpw9zqfwf6UF7L1ELUp7PoyJ3kGN1eV5jbK5HfcvKh8FNqb53 uD7w== X-Gm-Message-State: AOJu0YwK7s0iiburllzFdVreUwMVuG5eYBLvT5CeM/1ll5Y8AJzATzx5 E3L4B5FvM7bZVlExUdHaXvx82KHZU0HgzBLg45zO0PaOMY0JM3ktDkYWgmOa/OIhH5s2CXJ2OLR IVQ== X-Google-Smtp-Source: AGHT+IEfiVADLG8MI4TU0GdG3K24Fm+n408i+ibK9JXlbmMQ+fWu+GA+LqI/KL+S0/7MFSYl9fjqgWQJ8g== X-Received: from pfbef26.prod.google.com ([2002:a05:6a00:2c9a:b0:747:aac7:7c2]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:21c3:b0:748:68dd:ecc8 with SMTP id d2e1a72fcca58-7489cfea237mr601439b3a.22.1749842066228; Fri, 13 Jun 2025 12:14:26 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:36 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-10-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 4CB9C2BF04D for ; Fri, 13 Jun 2025 19:14:28 +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=1749842070; cv=none; b=dviZUnk9Sv1Ev8GsfXvgt0HKc3wPLxhmu6y88ayf1TyIJD+4par2Twe5lp6iaDnifNvQMPVZh5u1/MM6V7cQDiyQ/ae5mdtU+Qy+bPPHuvBummKE6Qst3jK6TzroBV/mbijNsP9/VIfwR4dJdokUcae5kUXjkV2EVTJcA8kEtdU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842070; c=relaxed/simple; bh=qA4ohxxS+vE8iiREeVJzTRaGY2RbIWWfLxdMUKYZJZk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Ati/IYkmNTpSP/8jJl5tMJNvBOKp74xvrYXOLYgLKdrlQWLKIO+oyBY44bZnDzE0n9daSdpbQBZnbJQJNm87NzcoJjDXp1yWCUuVqkgAUxlKXmDFG5kSyvcG9Ii3MRxVtX43kzn4YfS4LBbgx5NndpBTtw8ofEbippbpbCC2Fj0= 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=bMtElpHh; 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="bMtElpHh" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-31332dc2b59so2072278a91.0 for ; Fri, 13 Jun 2025 12:14:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842068; x=1750446868; 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=HociWBs1/0Gsb5gy2IveodPFH7cmxollP6TAWtAYOo0=; b=bMtElpHhUBdyiQLpzg57ri3iqCWgL3pGwYvwt7a3uF0Wi/GCKw5t5EYWPcmFXWXGvE am2PVSyZAiGT0CUeKNq4ek7vPpsU8UZDvTj4SfyWiu9bcPYB1uQRAKO4yjX/0t504N5M hDnwWecuCYOo51C4WV9b3PBWqkjkGjg4HCMwPdvvyVs4dm/D1kgl/YLncyElXiAgiPxB +pNxhaPmj8fVEkhvBAAffCxeUufRZFVb9Tf+ly+77gKphgTR3yx40zvXOOu2Xc/QPUVb KUuaGOzx2WPk14gR0ike6PvMHp3bWwhcbSqlZvfZ3m6JF/Eud+BmrAvUDELKQmLvZru9 A4GA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842068; x=1750446868; 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=HociWBs1/0Gsb5gy2IveodPFH7cmxollP6TAWtAYOo0=; b=PQRaD7J/RN7eJa2IoENFzwqgexw4S4KPUYor43Nn+IQJnawi0XSxy9l1geePqUflFw CTghLELRBlipQWQ1QckxUVLCZFBVETyp3DdhOuSjtXCy5+xHyMhkf595S6u30ezXzBnI 0RT8iR+sFYsOUPm4i9tee/ebONDxncuY/UXXr+DNfUdB+Q1M5RnB3yIfcsQPSV56JzXV u94iPJHcK9y2P8lHlY3X1Irge/TbyGiYFDAJzoI4VmqHNen5v7CUv5PBJhpTgehSau9F 0CU4cmo7qT48oKKYqnEGHEH+TqnW336JKw70uTEJBRvhgUWopGj4BnSFRlBtWUTVoqqY 5jRw== X-Gm-Message-State: AOJu0Yzo4tdSm+jmeYr4HCGsG22/kSC/daf5BX7hhmSrS1vALaMPuaII xt9WlAvUPPiaCiT6gVMe5mn0I21HoauSzE2eDrMAPnsPV5d4Aq31H/Qo/vJD1o9BVYF0ZXOb44f /VA== X-Google-Smtp-Source: AGHT+IF5X+YgI8YMiqLZp24uKESiND+Xjg2x97EcCHeG1WV/H6ywto51kNtjAupUPtcn9jsfx7ZyQMhkBA== X-Received: from pjwx12.prod.google.com ([2002:a17:90a:c2cc:b0:311:9b25:8e87]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:586b:b0:312:39c1:c9cf with SMTP id 98e67ed59e1d1-313f1be1c89mr1323198a91.7.1749842067784; Fri, 13 Jun 2025 12:14:27 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:37 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-11-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 DD5D82BF06F for ; Fri, 13 Jun 2025 19:14:29 +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=1749842071; cv=none; b=K6MjqMwdcx75YlLkJl29QMxJ2Umloq9fXi+w/kHg7Me4FTHnapjNvQojCd/0fPj5MS9zNYFuriWBxT8/hRNIPjTdXvZaDp16iVeaN5UaTiW1PzW3Dd5igEqNmibs9SfAJZSJIzvjvK2ggDZZuPYuwG403UHR3DuJETL2f7kIS4A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842071; c=relaxed/simple; bh=uqIxOmX3BYXbbCv1CMHqHbbyU277l6eBkNwagdau+oY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=J/YXni4OuGFPRwBEgD08Dw3bPqzjNDzi+zQ2bJwHMfJLqTj7w9SMZp7tHcn1hWGUijpON/7q97Vw8PhZDvhSICcj+8jaNwEdP/2HM4xBIiaxzQMxXcZ2+HlkYZAPdkF0TmQlklERZ1IhIZf7ufzr37W4p29s14llgAVeojYegTU= 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=uZ9DKfe2; 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="uZ9DKfe2" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-748764d84feso3135764b3a.2 for ; Fri, 13 Jun 2025 12:14:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842069; x=1750446869; 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=N/svNuuxjLlsSpnXIsQtll5AlQK2Oa/4goaN4sSAXj0=; b=uZ9DKfe2jk/5QcYfSeiGO/YcrkPJfSHJXc8I2ZqyYvpKaWdIWbq1cbQpO3C7P5lFoe YbE8BHtpRlRU1KOx8xAHXKVh61gaMckS9KqUE87V0Xzf8s6HzI2tnP9M/g47RKBi7rc2 hMLRIraYsHd6DqGIRzI0rCqxjTc1L6Sue9WLkKG06cdfx5QUaLdfqeFQsJtpgv6RCE7A iHKgairVLxDJExdiLARgkexbIwt/iTmOeTpH9iPO8Fbx7P1NTNkweQo8ajqTPDasw+Dm wPi54FVFkS1lat1ksCNu4wrU/6Kicc8S+/OI89Ku/TM1THYW/pIU36GJ2ZrMemkYBQoa P0rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842069; x=1750446869; 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=N/svNuuxjLlsSpnXIsQtll5AlQK2Oa/4goaN4sSAXj0=; b=CjoXg00EsIdLR6k+KvMACFEuLAE5c5atEyGc/aYcWxpnw/S91M93awR4dA8wXQpd3i uRRnOcPrhekJGienG8/TCTfeZuzh3+bq81X1nLAkJ9H60theWfVb74B6xySngYbPzvL5 g3RX6Y8yuDLfzofW6M5bCDx0sNJnUuTpbwL4KIg04MV0LxJgn1oIHbEFWxzpJHgqiIQf YfQPnwj+2up2IulKk9B+HSzb3Kol0jsvy/mtWOo3vaZ9c535fgY6IK/BMLIXdP7/jJSE QtvghdGUy6/tQ1YjgdRAm377TOi3iCKuu1Rh0o30Yc3oJdiyIG96+AzmoDAX2dpnR0gD MtSA== X-Gm-Message-State: AOJu0YwTJ8PlTmKxwpoz7dERvQnmfa97CqXdyLWDJstMAFY2extdnD2D Ye+v13Df2axi57sFpOGxmoXZX0fl8C59zAu4/KUhr1Xz8pU+rqvVQjAdLKcqounvJUVR2Jnd0VO o4g== X-Google-Smtp-Source: AGHT+IFsYD1YyKIZHNpOeAVzaehTtViz3NuufMHX1K/2IHUCVmKQpLnEvTjx4pMeMGAWKjwf/SjSKMjEtA== X-Received: from pfuv8.prod.google.com ([2002:a05:6a00:1488:b0:747:b76c:ab92]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:3a19:b0:746:2ae9:fc3d with SMTP id d2e1a72fcca58-7489cffb6bbmr654798b3a.23.1749842069428; Fri, 13 Jun 2025 12:14:29 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:38 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-12-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 7F20C2BF050 for ; Fri, 13 Jun 2025 19:14:31 +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=1749842073; cv=none; b=BuU4mnGOg9svaWrNrqGovTJkw9Ug9S9gVhXCGtxk9vC1CVQWzRtDb3ckgovQkgxQ5NNvbcK1krAF8DRzqXkiV5APDCSgXNMQ+BhzSN0xrFDDKyy69hJLENr5+bATZpk37AlyDvS1UbrSIR/S+DOghcdvQpth5SjctR81QXtWlEs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842073; c=relaxed/simple; bh=Avxsfm8/t8HpO7whsUccQLtn39Rse70swcdoxot3qwE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=CBLqZLdUiOX0YS7GNZvlB8K3jn3EpVn4/8kdNgPgM057WFFICo3Z82TIXNAfqYZHcG3GFHQEjG2mHjnXzhlwTO5NqJ/ZiBJsFPTAzL59tf9Nt3QaCw3IobyJSKP4Pp07OP+j9TLQN+OeRRkYIfd6p00akZI3C85xtNbyeXyBCKE= 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=IbpG9m58; 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="IbpG9m58" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-313d346dc8dso1663708a91.1 for ; Fri, 13 Jun 2025 12:14:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842071; x=1750446871; 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=HWyVXPzXj5FmoW23l8bdihrPptElHyOfK0iRRuk7KZI=; b=IbpG9m58GDzG07kEvfGRkR2gmK3W+y8s5WCFqMBvz2y787aH1vzyl6fnQret3tMnKE NKh/kKRU9bLbK1LySVe3Jn1JvyMQLlgIpNSzwEl1Kviy8pYgPJkUXIOJi0KSSktqdPn8 8KrbqDcteYMzQ1ysnN2bLRY8+Ieg8KRhTYV9STCG32MHR0rkNQ3YndtqG1XzbgvK1ooF hLvHFLmuyQ7tGcasf/s62FipzJ1hq4KgjEAQy4cmrM/f/5xhSS4qjoQO0g98NcP/dqWr njro5TLPGPZUutXYLs1dnjtl9y92D2a7mXyxmzwZjaewb/9glRiX8MjHx/G7awRyfsTR 42Og== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842071; x=1750446871; 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=HWyVXPzXj5FmoW23l8bdihrPptElHyOfK0iRRuk7KZI=; b=jifBsE++pCmY3z0Wt9PxtSl3sS6jb65ViWHcpic7p3makPcAGFv8PYEMeaH2biKIai UYl8v6+/GbQgoRuz854v5Noat2C0HtM8KT1iGIEuZTcZ5qmrwu+DSTpL1qJ5kcmBSYOD XB5Q78IEuj5i/TLORgNaHo4fOJPP0xvwDQ6kAAW+lhYR7mjbDO/sfAbPy+ga3pqzgwq4 /E+RcQNuhJuLiCeERTvAh/teA2xRtGVICG854qaxFM5czJfe+iqJuPH/8BoITqHJnBuK laZ9RXn3TV/lGHvyYpBf/F5zOg3C96gTemV6AhMW7h0YQELLczj0WpfN+w/0MHLzJMMG oumQ== X-Gm-Message-State: AOJu0YzWTgxNd3Sgxlj9ONl9/vf08Ye8tyBrdmkWUvAEEfDpNh/CvVsJ DUkicUI3M+JvMs60NKGamP0f3RF0QjuWe6ZNGmGCWPjEjIZlStBNS4O7Cz8kVLn8fea5AuYcK5r /wA== X-Google-Smtp-Source: AGHT+IHX4eKa44rIL8nJJ+oGoa5OIlWorBJ8Xw4+PraBFVJeeE4W4BVlN2Ig91BK/T8HjP6pvPBrGzlt2g== X-Received: from pjgg14.prod.google.com ([2002:a17:90b:57ce:b0:2fc:2c9c:880]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90a:e185:b0:311:ba2e:bdc9 with SMTP id 98e67ed59e1d1-313f1d17195mr1148975a91.27.1749842070932; Fri, 13 Jun 2025 12:14:30 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:39 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-13-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 F0F44244677 for ; Fri, 13 Jun 2025 19:14:32 +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=1749842075; cv=none; b=AaXK3j+pjCnCAOgkliRuir5FtzBP6MK+mxe+Om986/gmTypzrxu22Ehk24dlzPgLEPvAZptmeVPwBFyDqxLCdxNdLeIn8YsSAmal2bkgzw6AZvKyj7i6jV4qwbFg19Wdu0npJykDh5BJLb7H+fOpmgataC8nOESSRRwC8NhwDiA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842075; c=relaxed/simple; bh=pj/qOMhLK6l40aZOMbM3JNGNF/LrqZmEzRrypyE+ELo=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=I1bllx6s1hWzt4IL3C80DPW3kjurgJW2612NteHwAtF8OE3av8eUr4A7dgJCENrSk/Wfn3edDEEV11gCfFWNgLqTBM8EjbStErqYB+SOoht3IKiwTM0BGgRXosxILeqzOZXbVNl2oh53EFcKaDaMXBcABR2wi6wch11uJELKaes= 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=c2MGDVwm; 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="c2MGDVwm" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-311a6b43ed7so2068689a91.1 for ; Fri, 13 Jun 2025 12:14:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842072; x=1750446872; 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=NWsrJ5FcIz144D7jrLSABWJGVcBqxCeDWRTmiRMA030=; b=c2MGDVwmLIDSXj/zOG+5uMkHBtOwi3MFwqGj5Y0hugxNY72DeQKf5sKc8oBKpFqWac Kxw7pfFxZPyGtW+xiasfOxRkHHi6lJFtyV1AuVZCof9wCB7xmK/xQh+WfljIfe281fN2 of9e53DnnhupCsShKatN34UDV1svche8zDjeaRA0viyEASpfRKFW3athgYqZXq2mm9Ul iaACyHrYGOP98TkyCsAR5mnagc2YCiVdR4sVDl1np8WovM+22bU+Verhd7SLUbqkue1G QAmmiB5bykaVzlEEbdpk9X1X05tbzvhlpQvSaxVw1xRGiEtycDwe1cobWnNLECKAKXWI Flww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842072; x=1750446872; 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=NWsrJ5FcIz144D7jrLSABWJGVcBqxCeDWRTmiRMA030=; b=RIMqRS4GvJcZYcXg6Zx+8OZ6FHzqT5iFcrzjB3Hei6pfsniNH20LfPsbXwsVxrPflq lg+5Of0VBPjsm7iIBhL/iTc+ymuhAWorW2m2NcYqf6HkJXChhvOJLyGV7EbVUOC8jOLJ 6n5BTMzh77bGcTkBGV0iU7XWb9Dj+lk0ytYIsgc4Kaq8gmWv2Zv3Mn/2ZlWnrtPu0c2U U/kspOLjuv0UNBJYy8UAYbMQGhmesW5t/UXBqKxo/zME+4FcYTG7A56i26YYbbnc9gFp F0vTJGmT56UgFqVY4nhf3SQLkvnQhMiJc282uB/Gxh467znMRZfRZwnux0iFib7pEw8s Ul5w== X-Gm-Message-State: AOJu0Yz/ZdJek0cR8Q+KZV+kMnbMsasLjBc/TwTIJm+jl1fZA0VWl8+F 1GWcOUzMA4kMbPc4bhaUo/bLiQJl98iFupMNEjM8ih3CihXgcLERr35WkBZbLK5q7YemAfWSQxW bKg== X-Google-Smtp-Source: AGHT+IFrd+aIzVsaf5qkQIyyvxXN1hhsyIxmhctqZKZqFajXzX9NhDWDI6pk99SuAT7cgE/hn98xDe6CXQ== X-Received: from pjbsl11.prod.google.com ([2002:a17:90b:2e0b:b0:312:e5dd:9248]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:3d88:b0:311:ea13:2e63 with SMTP id 98e67ed59e1d1-313f1ca12e2mr1094019a91.13.1749842072421; Fri, 13 Jun 2025 12:14:32 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:40 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-14-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 7279B2D12F9 for ; Fri, 13 Jun 2025 19:14:34 +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=1749842076; cv=none; b=A80T4UHjuRRD36xcV2/X7wm+1ORVXVMNjpI70O8BlKNvUdhoHvHwI/eFLQAZVpWUDXrFfKVst2K5DacT+VMD7NzQZhktJpON+/n/TN/Je8yvBxw1bdu+zsZhnxyb9EyDUrGKBh2Dk4EDmyqKbvOVuSY1Wb42vSnrSd3uzkxk+eM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842076; c=relaxed/simple; bh=hswF6lmctPlGxMh6V3bWjkRNpWdm2SovJLGcWUYrYwM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=l+BNOH48TYu1Al+5C0+HLv7NX5XH+h5MlcaqfaVLqwNj+bZkRZZJmXNXDEgpF7XouX7bvAlixmOrvWQa/WbfTFlf1b44l/dPhjxeUu+zdz8kFNlwf94mA/AdT6O+e6pb73BcwD702pTik2uvq2vdO4EEeA6QkzSDoA+OqeTv1bY= 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=vv/e7TKX; 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="vv/e7TKX" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b2fcbd76b61so2299039a12.3 for ; Fri, 13 Jun 2025 12:14:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842074; x=1750446874; 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=AnbSP+D7ZiPpVcXvLT2g1gRVnFtqWS+6/xDCQbiW3Bc=; b=vv/e7TKXltNaUwRf2DwfOS3/6pnJuxFx8OVF/Ud1BqM7lDzYvdJM0DTMCj/oX3iYkR nR3DFoVlyRRaMGRUhzCaa5MWeKy8CHjlugjyiFzg4mjhdeyAdj+UTLfOld6ADJ3AeB8S bfqNu6o7+v+1Jm1Xya2LYSd2s0MW+zt+7SDiXef0vcLyzjKIzgbTGDjZcIk2BUYTKexm HSHLDLuJ0FM1rpb1HxfyHpV+nBcdM6Oqlv3utZQmsPE7h1+PabDa72c1MPBJjwG3CRdk 8o9pE66ZXdhL7zq7B7KWEtWCTbJ7ltMyeQRdnb+frWHsvILvDsazBI+wa3ecV08jpPIg M0tA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842074; x=1750446874; 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=AnbSP+D7ZiPpVcXvLT2g1gRVnFtqWS+6/xDCQbiW3Bc=; b=R4LvYMymHXLcSaj7oAvA/gJcGQFS4nFZk+d2y6mCYktde94lxUcLFDso8lQ7df3sn7 0Hha67lRUhnHopiO0AthEjnj4p9kYm4XIjxti2j+atnA5ViY7QgVU5arH1lcYBdGZGob GkO8QR9hjM2CxToXeyZjCQWqkWE0vxstca24dm+O9f2kNKImwhvtmB6fcVRfBphRFzFK 9cqZIZUm+bNyJRwDGxfu4GuHZOG8GUumWftG9vyz10Smr6HUxYD1mxJpSt+0p7X+y/DL 46uc+710UIYCVWV4ZX8m5g80EvsJ/ZxtCkoRJ2y/T2maZJ7M42WrLIs2v2zI93b0n+/S o/GQ== X-Gm-Message-State: AOJu0Yz1V02kmhT98w7a6woFMsStrVAlThPP4QXZzLATuIQiriK2syws 0KZ6O2twEroDDkWkPhBtKWxZGUxu4YNN8fg+X9pGlEN+HlQ86i0WZWbmq8mE5SMRnp89Pdt5wee etA== X-Google-Smtp-Source: AGHT+IHNH+3GY1JmOkm3+m7YtkR8+qb0XFiWbuv0avYIFVynX/fnoqVeMBVFhzkODxo7JHLUatWXvw6MmA== X-Received: from pjbqn11.prod.google.com ([2002:a17:90b:3d4b:b0:311:4aa8:2179]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:582f:b0:313:bf67:b354 with SMTP id 98e67ed59e1d1-313f1b87a40mr1426294a91.0.1749842073850; Fri, 13 Jun 2025 12:14:33 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:41 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-15-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:17 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 338C42D541F for ; Fri, 13 Jun 2025 19:14:36 +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=1749842077; cv=none; b=lRuq3HHkyWmBYshlgmuSwHiWxYLkzDSRcH4WhQ9Sr0B1Ikc32lWjhMV8VbNlGD9yEkICqXtK7R+U18w/nYhR+nZoJ3IzKSdmcxZGzptXvU9gj7iANT/yqJQjh1BhUCtLdkSalsFvuRt93EtzhRES8ShWpvw2uIyOJm3jpMr1qD4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842077; c=relaxed/simple; bh=XiUCLbM31t3A1Ia7PvUtd8HccsiSwrLOChGJmM4U9ME=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=miPNe6BzVU9x8/9bOC3WomLySAAe/QA7zeddW+AsprgTqQVcxszNXh160Vgvr+jPyagEg3e0OFY+S1qlkWF7YRRUf/nIS7FsgTofGCpatZAOVm6hDpya5lcnRKTFyZXvhN+uWINbm1qeDPCCXVu+6G79juQjGQEwKlYJwKpmftY= 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=vICYqu6+; 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="vICYqu6+" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-31315427249so2484521a91.1 for ; Fri, 13 Jun 2025 12:14:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842076; x=1750446876; 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=SP57h7voyy8pTBZCNH4MEMrCXCzzIc1ZMbh9qeY2Ibg=; b=vICYqu6+M6+2t3YdF/M1am1DaC8J2LrFFbnm+qpeyaTwU6YMwjPlTJ3Wbi8o8/4jZl yOFNDBxtpkB/4rmTJAOyK5jRrGMfp114AQavRcOpPbEZP1CgCh3WyW42Y3UhvFiA0rN1 ohLJ0ZxTPlgjxKJYKr5lwlkUeznmBPwqNrCGv9gJPjAOmPQN0U0zzF9kt1m4z7JoXyV7 bfxyqk1xs/KM9oslN4eH7/rxj/cbMXosuwIiMs/bfxEByq2Bl2BslvimYrZcWDdTCOGG cB/VQty5+ybBX5px9R+6vDPPMb9KV4OWMT9I8eUqd6mPzs1sN/ArwIUDH3LFHs9Wj7aG jP9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842076; x=1750446876; 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=SP57h7voyy8pTBZCNH4MEMrCXCzzIc1ZMbh9qeY2Ibg=; b=dgA58wlUXsWOx3ieG3GSxAX3iw7sgtJXzGULA3Fv3AgCx2v/OVry4V+t4PJofiV+CB vilzF69ijoLc53s00u5vOjjiImONljfB2gr68UrU1Xwublk82eaQSes8dTb4P7mmQ1Hx wN99yDQg0vDPg8DRoYFsUIaIYx4jdnkkQQtq9N4ASOOkhPZJlJv5tHMjb91OJzdm6ccL e345wLlTUNAXv3hfL5f9vfnS2yPAkYK/jduUJSdcKpPiaAADS1MXL6XhJl0kHRwtCMDp yPsMykx/ty88Su89HoR6quKp9dXmv+rYc9GUwQPxhwVUF8wAxhxfbAMF5QWcFXjzpb2M LCwQ== X-Gm-Message-State: AOJu0Yyr5tBFDs3a52106xEJ7DczvzZvSr94vmXtDRUnPzFYresDwyZU ESzOqqBliphdSt1oP7I/4Fj6xpBS6Y0nb0EpR5ZJX4+Bg+9kDJP3El/Hz+uM2NPjbO1KcI8wFZE 5RA== X-Google-Smtp-Source: AGHT+IELUXbtKEDjBs5GY4fdlAQg/ZPL5N4QXKAYA2nCb54Nuv3VGNUPELE6Q2Lncwpw2i1IMtNM9J4b3g== X-Received: from pjf7.prod.google.com ([2002:a17:90b:3f07:b0:311:ea2a:3919]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90a:e7c6:b0:313:2f45:2fc8 with SMTP id 98e67ed59e1d1-313f1d5872amr1337825a91.18.1749842075331; Fri, 13 Jun 2025 12:14:35 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:42 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-16-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 ED6432D9ECC for ; Fri, 13 Jun 2025 19:14:37 +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=1749842080; cv=none; b=pk4ZyeZHNcd1aTXsCppGpTc3aA5AwDTQglxP29Kyo8fs0SZGfrAMFFjJyl+ZZlik7CKVKaxMJUtIBRZQsXcXGFqPm52wsQJzUq1z5HGHEtriQFOQJgVWb4s5WeBMpEv4cbgsAO/bw5WJBwB9l3gmG5EwruuX/DYUoM9HKbHybBI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842080; c=relaxed/simple; bh=NfXzvWPqKpJCBwVoGpTmHOXPaJf8dCByhWwm855UcKE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=N8XI2VJyauzzqeEY5qgDBKJAKgFSTW8oOIoeIl5JM6Hwt4ok5kqY88K87Yk1kYF6jZys/liOM4rD/HMreEMdyEHxDmwvgUhh7tkqFostDq2uEcvZxadO6t38+vHwsWBxVAIm33LLdikk0MEBtVJyyy4OMpNgnAX5QcEYCUHfYtg= 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=Bfo+gP+F; 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="Bfo+gP+F" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b2eea1c2e97so1899316a12.2 for ; Fri, 13 Jun 2025 12:14:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842077; x=1750446877; 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=AayXtPvBMSdt2WCa05Tql7yYrOkVcmKW5+2qawWp58g=; b=Bfo+gP+F8s+T/n3Sc/AYCs45QALbbG5W0g44VeN67lu1vgX9BApc72fN2ODU8brBmW s/8cJCPHnfixcZ7Q9892tRTD88I7bki+g5lfmzUby9YNTN+dYo+PdrvHx20whyT7lnTt F//LvUttlRWlWECdfvmAVeKn9dhjib0muPSC9tGCqKHSb3AaAiaCeb7QgTvEcGtoaj3Y zJlEbbSk3c5iiC9VApTqOQhPY0lUF2kfwLvqoklEdB4kIYK0yYwHPo9SNRSteyvN9xJ1 PLcQ62dOleM90ckAOurr2aW/bTqweqIYA+tjOXaOdbhMkF8nLNWjqztwgiU6rh9aQ35o ppEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842077; x=1750446877; 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=AayXtPvBMSdt2WCa05Tql7yYrOkVcmKW5+2qawWp58g=; b=c4hx14ZmgpTCJGZCJKY61wq/lBBziyayK5q7mSh5ZeCILdTPI6uP177iTByn9oqtcE cuc76LilPnS4UN7uEewBNUO+grQZhmvutjoNnCErfHH50Vvc2kCyoVtEWg/JEgQXxDpO nvmA7k54nXSo5MAHwC82+bg+XDI4CCkmm0lahT0bbjupgMc6oR5vMQnynp/azLunfEBO Fa20ljc9UHBUo1Cso7Z2obBu3q0SzKlan2N9aD/GwF4MLcZKWnDrvQiK1oUEBOKBVLAG HZn7hV3j0GRWLkEejzp1HYTqoOTKMrtHIY6dU4NOaF4wk11jDdyJMv0ox6HoPUUhV0Va mL7w== X-Gm-Message-State: AOJu0Yx3jezvM/Yr2XaGrzZR6pErpZn48ILkPvkEUb4VzoumE/z3eAP/ 1Rkv3m5HH/MozRfWR9L1JwYrf6rS0wsoL5BBfxVpOQCV4IBaQavBZNYW1sTq6L4XQGnmjvB3L0I gxw== X-Google-Smtp-Source: AGHT+IFMQQwycBjQuI0ZdQa3VKNkM7qFrwvWMt48QdqgyIMhf4mOxcRFLjJIsSjugaGsUCEtnzObwvW7HQ== X-Received: from pfbef24.prod.google.com ([2002:a05:6a00:2c98:b0:746:223d:ebdc]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:7702:b0:1f5:8678:1820 with SMTP id adf61e73a8af0-21fbd4c8aacmr601617637.12.1749842077234; Fri, 13 Jun 2025 12:14:37 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:43 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-17-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 3CB9E2D9EEF for ; Fri, 13 Jun 2025 19:14:39 +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=1749842081; cv=none; b=BvgWAZx48zbN4BHrEA8HWsdwqfKjTOiQtqquLcEHBN88Q2zntt8aSnda1YLfalDb1rePcIk437km6p2lJjYw5H6U6eWjT19UQmiZTey8Lxam1jGbx7I1dPA1kekRsYXx2pm2XiRzoiQmgTCH9v0UpsgDl1FLUYkD1DORMacnYkw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842081; c=relaxed/simple; bh=PsBeeG1A8OYyGWHuc0HL/Ka0JLodkH2zEOxDGzqAs1I=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=KDE91qYmFqD9jbMG0XX4uy+moDMJnYopw7xOCpnw91NeEjQtakJ+9CJuw06NdOXS8meGl8Lxdd2gfB5kQ7aAFDjM1n4NBf5R883cksV2B20BHlhLMN2H7UutWQvgKLM1r9Fb5dnrC75wJwgAbog7uweROIBMlzSOsaeYUbv57QI= 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=IapJo8iI; 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="IapJo8iI" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-740270e168aso2107381b3a.1 for ; Fri, 13 Jun 2025 12:14:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842079; x=1750446879; 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=qo77ALWGLlS5a+AOG+Up/vemw+ZwJwTl4/AAZ4FInCc=; b=IapJo8iIMbjPnsYEwd41dWXeJ+Uvztd1PMOfUN6J3KJ8gfzyzJ4HkZW7adbkYwQMMH vzql5eCxXbgaMGC+a+SIHMUqVDYqVXZVleb5ZPmV9okFeWIObYnbAPOw4oegF+ld7usc +v+wgXkgSspwTSZg9CBH5umTznMCJsC9mYETrGj6vnvb1xgTXLRFfbICdzhtAFTuQZz+ KhbpsZYJeZN42FOWB+czStTY04XbKViifPCyVn1IiQ+eicD4VvnVTUBLJMUcti7PXrcX LzwetwEXAFPBSQr24RR/DXiSoIA9FXWEC7BAc61cozWtgadLl6fmGyMjAKtA+yssHPCI f50g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842079; x=1750446879; 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=qo77ALWGLlS5a+AOG+Up/vemw+ZwJwTl4/AAZ4FInCc=; b=COXPPQp2eusukgGoyq64hzRgupTHSPCRqAu+W3wee3XcaqO54U+vyoI3nSlBW8puQR 9lDk/cK6i9ic8igA/XLbVaKlfMSnB0Wte7tFp+694/vKV2rVeaKdSKYNIT8KEaKKS4So lYQ3K7NGJP1PeaqCV4tJE9bby9Qw+9YK34a0h+hj0cXz8G7F50l70GTnVDEf9lMfebeo xv3IMgRhFtfW53uJzFwLtxpI1mhxcYMAUl0KCZm5uL4d+2bm7ag3BKpLglBdLgwrx2qK MrqIZnvhQybWfADQWqPjpfj6dUzEnfQL2v4NhPcMfGxsd/QjCrNFejPUD027T7eIQwOo PKFA== X-Gm-Message-State: AOJu0YwDBYDrQ4pqgsFPZInm+GqIlyVnIFogdY1E+f/UdMVyT2my/c7J qMQiHpKQW6Zu6vQ5+17avXThw4HxXh2FIdLINmJ8Wcfm5ZiPxn9cXi7OHHdUn6xRiFI6okynlGD 7NQ== X-Google-Smtp-Source: AGHT+IHR6daDRKqgwWFjUv4/DXnqJF6kWP1sxIAhGWkf65LPPiBa8mIm2R1Jsf1XRbI1J3eb6vctzbTfHQ== X-Received: from pfug15.prod.google.com ([2002:a05:6a00:78f:b0:748:34d:6d5a]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:7a90:b0:21a:e751:e048 with SMTP id adf61e73a8af0-21fbd666e30mr640030637.35.1749842078776; Fri, 13 Jun 2025 12:14:38 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:44 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-18-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 A953C2E0B65 for ; Fri, 13 Jun 2025 19:14:40 +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=1749842082; cv=none; b=ZduxrnMzWyMDwAo3xFgKSNne7oNlNyzA1MVqQFzqBl3RU+UeZBsoMlocFGs49nAH/S4WgdUJdunR7KavWthMg6sjxDRqL5B1sHreT0GjbLvenyUwu5hKqSpdQOdiomr8RDXhd8q3dBu9e3WpSCLogHBixvbEGLG+L8oInVobT+U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842082; c=relaxed/simple; bh=vkQnGxmnq3FvWRlYyZOPtyDrMgqjYVCxKWTGDV4H4l0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=iFk0L2bOB43Q2XLbAoGhhNdbrh7e+xxfDYdVCzKNMuFdahTaXFqNsh0LgqjMEpVybj6NeM0jAPQyFm94nXv5c8DC1S3Zt6kN2D0SIinw4eSl/HFadN+AVe1DVnNUFUQcuGWnvvg2ATL/6CdPMd8ZBwHVvXYalXZA0nbCVcFtjmk= 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=OlY69zyA; 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="OlY69zyA" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b26e6b84a31so1612861a12.2 for ; Fri, 13 Jun 2025 12:14:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842080; x=1750446880; 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=zFkZUcYMwmohc1Na3cW6XmGA564dj6tHlEnjLwaRw6s=; b=OlY69zyA8JvnJHM0GkCNhfa1WE2HwAAx3flkbQcGFUQXdHBXciTkbKFcouuypk/nwJ 8VQpb1Yn/K5XwCdcz8UpTrMVMh1DAmN/T+CWr9xlWTuIEflRMn6+3P3PkPti4Tu+gkc7 eKf8NixQjOjYZaWNe564TVAL4F0senu2YHcRplegqDKfZgHYBomSTeAKhqN4oY1P3h2S e7XJeDVU9deY8cYM1oCS9A5CFxEJP3ETCRW4qPSUH+8ePLmgNVFSQZpVhxaFp7ec0iXl xolbZTDcl9v+esa0Vg8Bar/DF0nDTuvz+n0ApKkD+92A0RyUDKXBtdi9Gw4thCBD0mIS qCBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842080; x=1750446880; 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=zFkZUcYMwmohc1Na3cW6XmGA564dj6tHlEnjLwaRw6s=; b=sE9dDlor+vW/65bvRalgNJ3tYT8h8o8fyvmHg6VrVRdsk9wFI1H5ZFxblS9FY2Kb6U iPFWTjRc1Cg2P06Z6cMtcsV7M4vXYh1TrY6Th57Ol8vDTMWjTirQ4/InppoVfLNtVsNz OkmTqzIOusWkhfg0HvuCz/eD+xmh8LGDtj7OKSS7JR7CCHRcLqJIOslfBwaX4RZ536uW SjO4Tl1Al+BifkYuImyQu055Ilqx+B/9aOdVZHiPzRxxNEWM57bp7mQcSfgRHF2H+9qS MF7+Pv+jV5RkmWOSm51TkEgnUf/EOJ2dTH06+DXIt6sJfWxSTmcXZZQP3cSqGlvE8K3V VwSQ== X-Gm-Message-State: AOJu0YzefF9MfckdKVDzEsnC9z6/HE+MKrBHScKdjNvuPyWSrc7JcNM3 5ZWGiV/WarGB5Nks8yvrsA+Pu52vx5gaXQH+HFfyweyIuW6jeiGDbMuzzm7hcHnYLl86cdhX1ap thA== X-Google-Smtp-Source: AGHT+IHFucHe7xsJxlONn8CbQPufZ/dQvuLc3jBfr1TAOpqGksCXxRbdNPlYykzSm67XzETVBgDYNOSnog== X-Received: from pgct7.prod.google.com ([2002:a05:6a02:5287:b0:b2c:4ef2:c9f8]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:3289:b0:1f5:a3e8:64c1 with SMTP id adf61e73a8af0-21fbd3d4182mr781718637.0.1749842080043; Fri, 13 Jun 2025 12:14:40 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:45 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-19-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 1E34D2E3363 for ; Fri, 13 Jun 2025 19:14:42 +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=1749842083; cv=none; b=uwGNsbGm1mWHYKmB259yWceT1yJWzpmdbs3sAuFH7HIslCe1oy5+HQ+391RsdTjHK9qLSKrQfH5kgzCWq+aj6lNl+eKgqH7++lCGx4b03XKntcJ6ItZfhACgrIyWIDbb441Cdelmyd+qFhb0PVPib3GKY/qOdqhq4QYwUKYVA5M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842083; c=relaxed/simple; bh=gB7leVldU3Q+/K2dvULRGODaLqYXhPw7nhUc71aLv2Y=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=XVg8EfDN1SqlVJPaVQ85aI4RVA9N4D9qGnO+DEM3VGrP7ntWBFD2QarDOmc8YcY5fZS48hwubBD1TVWHQH8BX6p688HUo59wSsNk6ZSzTC/0pl9Ya9UOs7ytCrKjjQN/WxU52cp6KdXG7C5pCbWDnhvWXbrmqJhxOr62sqPC328= 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=CH1tQ+Dx; 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="CH1tQ+Dx" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b00e4358a34so1595689a12.0 for ; Fri, 13 Jun 2025 12:14:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842081; x=1750446881; 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=9p4glGj+JFvfl5WfXSVa1QcEpc+ehsxYbyir+NTtj2U=; b=CH1tQ+Dx1obdt7QJvYbrt+zwR06qPUcMMXwWvb82HlN0QkGUCL7TW3/DknEZ1HDTe9 gB5n++qW3Z8/e+34rQW5HGbTEA0trGeZ4IBLWOI7UnAyyTazFilIAzaM3Lces7HvVt8l 2XOln7GtFidn9IUopgU1qrcGZ+8+Qf05Signjg1OJbF+HN/V9w6oiQ69YvO7cRyinpGP OSIxyuH9J2nvQtz7lChf/8OMRK8p1RZ3p9+BS5+Xk+uuZxUBwEzbkNVM4UE68Yj4IAzZ J2PMyBNUZYCvT8HVcmhcW3qdalxcTwQsYA56BIUGOsGSzqq/8X8QcGskGlTpsS7EZfL1 VS2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842081; x=1750446881; 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=9p4glGj+JFvfl5WfXSVa1QcEpc+ehsxYbyir+NTtj2U=; b=Rewh150AOaKvDVy7pLoyCxmo4fdbeB9zQP3lW1Mh9bvyC0ItquzLZCQ2wKmHWm+KVD jBoeCzsOpNPChYS/epSjNJJzSAN3OBsWY2IdFbAoExoEGGnpBcL4kQRkXQ3VVX0ajyUJ Sbt6xeOAQeA/bzUyV0Vo+9oS5ctXP0hbn/G9sn366DKPS2SZ95SKNt4qhbqkBbL57Gk9 MPgNNiJ7cgc3U3C5TiEyfwHrY5Z9vRA7GkfeajOVRdiiss2oIk8oqJI+WVg4f3BQdR6p LGC1aXy93FVnen1JjeNGrRKeTNkpmdDXGrqFPyDGhTtbzWdzPlI42LOhM5bGDBJRIFLZ yIxA== X-Gm-Message-State: AOJu0YxJjatChfz7v8Hhb49noWtdpymY/ivEPcKkBmcowsyRzUr2dAVX hxg0XoBJPofF0xdj/xYvBFYQNlUbxT93QRH89+AqOTJdZyp+PmCDMul/yNEOkOy/Zb9gSuAy8g4 TvQ== X-Google-Smtp-Source: AGHT+IHfouRTUogXGPkW4ugX6w/2YUe1t4Q6+8l6WO+bVjHwKE9QByebDntsgccifWGOIya/D+bam5qG5A== X-Received: from pjbsr4.prod.google.com ([2002:a17:90b:4e84:b0:313:2ad9:17ec]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:3d0a:b0:312:18e:d930 with SMTP id 98e67ed59e1d1-313f1d4e217mr956309a91.19.1749842081564; Fri, 13 Jun 2025 12:14:41 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:46 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-20-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 9615F2E6126 for ; Fri, 13 Jun 2025 19:14:43 +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=1749842085; cv=none; b=Z9Qbyo5ESl3RG4NzvyfTv5MHMAzFNj9knTJ9k7+14aM2fo/S+xVAUbJ5i2R1pE9N7jAGZ8quup4aGKUVfuN1x6vHJhD7NdOCMG9mkh2hNrdb1ey9RAnomDmQnJSxjZTx7seNFu/obKJXLTePTBw7HSbo0JSyMjpBgN60fDjsx00= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842085; c=relaxed/simple; bh=Si628ZF6xZn+0lEUbdChfRrtx3LQddm9+0kcT06bBJw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=hgtqyg8LT4iDpNRKDaeW/dIV+xyg0Ec+SWclmLhwMb4NsXTOmJBnKym9PKoOUzAiMI60hW1R5ekcloXtd2ZAY1rBs3JSfC8kRZNfH9enVQs5Snp4xjSzUySmUu1i1T8kvg1vN0/IeSRk5Y++GxpIjb+hpKMNilcDxkfIsbnCWJ8= 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=xI02baTt; 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="xI02baTt" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-311e98ee3fcso3002150a91.0 for ; Fri, 13 Jun 2025 12:14:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842083; x=1750446883; 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=kNxHC47MRamy30edTQ2/Z7TS0MyTkgzXr6gKO99CUZI=; b=xI02baTtBg3Vp86AFgZC0AE0+yTiGCZe/Qe8BnauT0AYOg7DFPSwiZvZ6sArzuwdw4 XbPrIFXNO22wmKQXZSm1owVACzMBX/coat3ap4Eo7C8DwuMcO20c98SdxzPkBoQeFN3T JYEuB9O9M7cvTVpjIhR0AP/sB9zShZbJiK+Ovtoc/y8kDFR9E8g6CGv7gYR14jj7hP0m GYpO3Myv9Lqw2IJdfuQ556WZoLveIR0fCHElTz7YGtaMI68CkvbPAGKCGY90PKz+S9a7 /PelIE5JeqiTmnvlBpAc29iIwHCYElM/CbPQOb9tP8RoHJnGaGMAFNajA+ltous76nAb NdHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842083; x=1750446883; 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=kNxHC47MRamy30edTQ2/Z7TS0MyTkgzXr6gKO99CUZI=; b=eK+FYbnttrdo3BTihNxOrPqVx+aDBHnQkwUGK8Tij1bUBICHw3RywkmQyxZpQMd1As fms2eSDF9j+TV+nPXSrskF2aEFl47A1M+huU7AD3xtWjRbbdA6GHkVmYBdZHNRHxRvyF l2QtP4gmEegsRPo6A1eV2vK57SgTzLghARETKoGxy+C5imp7dqxeNUXqVzWTMQ+iy2Cb NnuM8RoOGJG6X56xULpog2zzrv26symL0+fO7B5/QxELzH+Bu/aQdBsdVaUj5YJPcY9V FeFWpib1ReSAfzJFd/fY9TFcjxnEqS45qYdYCD0ph8x17aF//6WJ5V0fQUrFEXbCcC3g A0rA== X-Gm-Message-State: AOJu0Yw4rdFaXGF2h5Sxmdmthb5MqlM1Nu2I1DmrMu0g5pFLItZYnZAl a9ABpfqAaVcq+ipDHycbIVrt4WO2hZYEC6ACC/1Cg/IsrHKOzk/0eEA/QaDKAo8tqr/YbRF7eyj REg== X-Google-Smtp-Source: AGHT+IFOSI/m+gX9R97dY/cQSKdcl8peNI0MZYBJ+JGRKw/vExof9CTDCaycN+5dWmWHQl7Mc5mFd4dNoA== X-Received: from pjbok12.prod.google.com ([2002:a17:90b:1d4c:b0:312:e266:f849]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4f44:b0:311:c970:c9c5 with SMTP id 98e67ed59e1d1-313f1bff73dmr1095769a91.7.1749842082969; Fri, 13 Jun 2025 12:14:42 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:47 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-21-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 36ACA2E6D13 for ; Fri, 13 Jun 2025 19:14:44 +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=1749842086; cv=none; b=s8IHJzbYja5YvA//0PUGMnSDXNQPSZpLzVU4yzwKOOHR/MqGIO4OJsNAjWyBXBnzQWN88byI3g/X+fiHXqE2WKUzufZaop9srxEoAysJ133z9IhS9EFLQjYLVSXvSqpAr6QP7p8OWPVo8xvqlqcnM1OPfuZtSuYfjgDeI7Ud+mE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842086; c=relaxed/simple; bh=ZDHbd532GCXq4+Wx1lJLULWSC4TyKkWgWdn+qq+pg3M=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Tyn3gSbIk4tyF/xq+Kfa7B2BqQBpvuVWCgq1E6lORD93+9OfNtxyWUDecON1bOJE9fJjEOhOHbtDcn1oPvjCr+7Y/W1hQR/hcDrwq7Efin4+P7oL0EslAvOHPJLtVN1+EA7zg4N2U3M3RCo8mtHjsz1YLkWlbEFlSriYc7L/Q28= 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=clpE+JMA; 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="clpE+JMA" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-234b133b428so17248455ad.3 for ; Fri, 13 Jun 2025 12:14:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842084; x=1750446884; 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=sSem4my8PEVCL1FyWJdYHzfToitzpttknCPI+ZxEpoM=; b=clpE+JMAGI4tNpZIa2F739kls23FI7gJZvNq30Np5mUr5EPCcPpb6ne3gv7Nnb1eS9 3CBzkrVNfhXQr+t/uHGBSz6/9Q/Uv9/3b2tYEAP67R1QKQ0OIx4oQ107j0mxfor49qW3 joG9UxH5dCdb1ybFFOkOTio20+h1Q+Vs9h9uK4etSX9TFjR8VYBk3uA3wWI6QYWhub5S 5BCtqRE5aOsD55Ev7BrLOuVqmBM3T73P06CbEtCP6gOxyJPiwDqm6Kg6c6yV6YwRIqrj N4iqdh04kZLhc0GzN7KBQF4cIJgxKrXhrOTbuR8I9loP62tUot/XRsqxiJY61exWRi8t VJVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842084; x=1750446884; 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=sSem4my8PEVCL1FyWJdYHzfToitzpttknCPI+ZxEpoM=; b=RHSRaEwBb5yQJUMQR30y0fHYWAdThFKcbXZBHN6xwR/bSGpLAD5WSueyMoWY2FAOBr HeACnDN4UzcMC1DXR+ea5MJxfWFlfvnH2GHnGPn0hb+4yGHuwC55UJpr1fednz6Ly9Yk JnyBSfNvd/bMbGGkeGutJuAbtSg/UDIg+VtxrEy5bXxKrMjxZY9Sn/mgqdVn0Wwdevv4 IeJY/Dv/cP8Ql5cCMz5lGbRWx4Gf809eJSrYDfi9yH7zsltuXf+EuDsplNbVzAp3BLC1 uugglMjwoJrwwv91jvLyb1k6mnKVrN6yuWuZ2K73RWvV21zWAYTvFAzoqLtBo3UBKA4X anTA== X-Gm-Message-State: AOJu0Yyxb3Khp/vCOkOlHlieP9yk2q+EygOa1RbsLNl33kYMQlIrtO1A pp16x95aOLLPEskwdjvesZ/saEN85dNjprBF08sb0HofNChhKyEDUUnoZ0IvD95qkfH30FJzzC1 8fA== X-Google-Smtp-Source: AGHT+IHoFi2FEXxt6RGl8CP0XU+1XYYnXNl8HBy73IZAP7OdJlDmHDOpVJoQYvp/U3PxFXoTzi0LO4LOEA== X-Received: from pjgg14.prod.google.com ([2002:a17:90b:57ce:b0:2fc:2c9c:880]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:d487:b0:234:c8f6:1afb with SMTP id d9443c01a7336-2366aeea601mr11815165ad.0.1749842084414; Fri, 13 Jun 2025 12:14:44 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:48 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-22-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 2025 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.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 3D0582E6D38 for ; Fri, 13 Jun 2025 19:14:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842088; cv=none; b=BxuXLU65BqNOfUE3LEXDynP5PjyYzfvs6OIrKBWr+iRUGO8mV+x83/85RZIuPLDCKA+fCop6e/YmVGQinLDtPCknKxrksBQLY9AmMFzZzJFSAfpXzx9rHHpj9C2P4wXZM4i76oXh34jmVzKRQIVdTMlahPQifu9jzbWMBWCsOtU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842088; c=relaxed/simple; bh=9Dhyxu9y6z8ypyUV/rZJRa3YRfbXjiMvoKURtZ/0g3Q=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=p4SxGVOo4VIGhWV8z30mXhUvPB38glx+3mAxKCPbhDy1HV5+yB+zMQ9sVqgVLVjpwNiC4IYBoJyAxI6Xx/NQdag6BU3jvMGIKKxx/SNWBRN+NA58eXxcXBNrTK2slmccLEhizs2u91OBvo7tnkLWLLiAjAoonRhANeiULMe9Evg= 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=nwVtcbfY; arc=none smtp.client-ip=209.85.210.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="nwVtcbfY" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-7398d70abbfso2884226b3a.2 for ; Fri, 13 Jun 2025 12:14:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842086; x=1750446886; 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=FSSvdD2VjdjaMAPdTcVzqxzElUzYCHyaZM5f3exaxDM=; b=nwVtcbfYyRSxAgE18YIPQwlvuWMzUpMUMpwrf0ZoLJ/xqHymi4TmjDGFCDomY1bmPp b03n1FtX/rC4wQG0MAyuhEP4UweTcM/W41lrc9eKkvtoKwy8S2oMj947OHeR5H85KpR7 FgCfrxKWNKb1cTypOYEkgROT+2CrVWVSf8oYzQXaNZ/3bRHhNdEBZJfrTz3c9SguMCmn d49BSUXUwEGAqOsGwy2S7mCJnHsqrFGI699UfxECrGNLo+zceztaTlKjLuURb4q5g38r cUYkWqPZ7OuVPIpbsSPnRq1AnZt9xgqPnySt57gREJIyadCejjVvRK1tSKw27EBh02TK 1tBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842086; x=1750446886; 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=FSSvdD2VjdjaMAPdTcVzqxzElUzYCHyaZM5f3exaxDM=; b=Yl3YXBcbcZa4QpGLYqoqYtJWe0n3CSwmD8NMo4KrF5miKBBdjrrzNKs9pR/po9bPX6 HeSrrjEyGqTkZxYL2FAZVcd5Y2Z+GAyUEMSJZ8SIGtLDH3asYG2RUBRZHGT4RgqDAIpa PtADrxwR3L7gNIpGuZxUUGZKJWV92yTxMsDqpuA/3B2yozzDF0JG9QsCyWcR8KDgrV/X v9T8gGSFo+7nLC2JRsbJh2D/xXm2fNc9u7BKjRbhli/xm6+hbpeLIyiBkAVJ54bSL5iq tQTQJ23pZQ7+CQEdIGcF9Grehln+6j6qX/Lf8ljzKZ2E95N+i1sb4eu8R0JoL1EK2sdm HmFw== X-Gm-Message-State: AOJu0YyiXaj7LPcqk/5Fc70kUsg3JtCaNHBUQGz52l+UpXNWH+KS7jYg pWxtCPDWHBrcRkuaBsEpT2R1CeJQcSw9oslrrfmEWSy1hmhUcugbSgOfmBf84MqZT/x3EjjjNpz SHQ== X-Google-Smtp-Source: AGHT+IG/mGlItoEOzM9fZV08wXO2i3bw8Rka4kckdZJcu/RRgB9LTr7S1p1B5gnmySCNDxf21ePRmLWo6Q== X-Received: from pfoa20.prod.google.com ([2002:aa7:8654:0:b0:748:2476:b25f]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:b4b:b0:742:a91d:b2f5 with SMTP id d2e1a72fcca58-7489cffc1d9mr629556b3a.13.1749842085684; Fri, 13 Jun 2025 12:14:45 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:49 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-23-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 591C92E7648 for ; Fri, 13 Jun 2025 19:14:47 +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=1749842089; cv=none; b=Osb6n4/WqkZ/WxpPDeZAhN6h7r+ft1GXYkH4VTcynSMjvC5yYCh5CZgH06MmjxzYbqId/sSN647ZlnWgGTX70cJUPpt1P43/HR5od1D7+mmKEzR/ZUfWa+CF8JNVSUKGHxIi1z23Gq+AuSRtypyXX4azW0o1qoJZ4nr8XwAZ3WQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842089; c=relaxed/simple; bh=2C+2kEFAidXBdiAmtKQtTcVt8b+ANXwI4lH2Vsd2jQs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=n9+HEBMp/YeDaeS3wy1qr14nI/KiddifUi8YDAhPRjjcqRRjHETHga4H4N7EXnoYpZaluNeA1HYaPkliTf6ddGrP4idrrmNXGL+K4aRll8jm2rc9Q2gFkF4YBU2iG1UVd//19/Rjgs514e6QxxX1z1PafrvA0jkanHT0Tj6LJc0= 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=b+7MZua4; 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="b+7MZua4" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-313d6d671ffso1421916a91.2 for ; Fri, 13 Jun 2025 12:14:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842087; x=1750446887; 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=uFgWYxy267IbL0nQfyQUm4Zewpf7Dgq0ugim9DGk9mU=; b=b+7MZua4+4jvouFkJcrmzltTkJU/YGnYW4eQ4Vp2yKtDZc3nt+b67Fw+ueloDgCQJv 0kwQ2Zu9k7SpEgERx7iea3q8AbcCJRSJMxY19rHxYvDDAGxFnWVABUQLw8tTCRHX3Utf oABHQf62RiPWu1L27qd7wPNRHNtmAHGAuzXnqDhaXoG/xLsbXnPYd2C4wRHPiwlZ9Hgw BRGFl2hnNrkZrfJ6TB4TtqY9G59YmjKuEFSQFU+FHezvP1ayb8SOzRZpw0wskEtfzWFB aKYtiskg15ATnXwJTLUX7es4/vo6nKQk/fDN/lWPYmayk/+IFFrgZc/JpN5ADlgzj96y cnBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842087; x=1750446887; 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=uFgWYxy267IbL0nQfyQUm4Zewpf7Dgq0ugim9DGk9mU=; b=ro7cmC07yx/oWOHdn2NyXPPhekSSB4IOyJPhWqY+cw09bSGb24IDsLG7TY67z9jqKz UjjQ4a6jz6X9BGRRTtvqVpINhsoq/ZVUy/ZDrEHPGS3EET3cqEhH81lNcCaccL7kYOmK DqB7QQQyrSff/3HVulS18bs24Ixv2awn+x5HgOVvTlZM14x22zRgypMXnjRgJTd6asmR HM5RNcxES+02TL8p8Ec8n71tAFI/G4m8bzVPz26UQPYrO51Qnx4NeDUNTQ1OTqNtcAHO li/NsncFCUrwJhWhvKmQf/6ZqmhA6a1F8uzBMezrQD2WPoaPm/NDpBAsqZ4Wg2H74SOV Zb0A== X-Gm-Message-State: AOJu0YzCfBIsfGLIQ0oma/P6MkzkzeCV/6YT46NlmJplDj38LtT0e1en Z65kB9BCku9GvHMLY66HDi7du6Tn+zs8ESL7qPTGxPaEgZUJZjjyajj689NnwLu9bbOpBIQokky whA== X-Google-Smtp-Source: AGHT+IGe15mCwwCd96v7UA/dXYTm8/lCFuStdhYtYkrBVfmMXpizKcKM1pTfsOeUNlOUPPb4xjgZA7gNqA== X-Received: from pjyf5.prod.google.com ([2002:a17:90a:ec85:b0:313:245:8921]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:5241:b0:311:c93b:3ca2 with SMTP id 98e67ed59e1d1-313f1c7dademr1027312a91.6.1749842086897; Fri, 13 Jun 2025 12:14:46 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:50 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-24-sagis@google.com> Subject: [PATCH v7 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 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 ce422da10f50..5903acf0d055 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 2025 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.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 117372E7F1E for ; Fri, 13 Jun 2025 19:14:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842091; cv=none; b=MEf3TC5C14n4DvSH0CjwhpWuFeaPVe5Ohy12eieE2AZAb3eZMXkaZkpHORx3ismgh9V94CA+oUfDnL0z13im2EfOWuVNchlmWUdDsWH9Kow/D7ggg8WJ8qF45AVnENpo/U3W/hraq38Y9s80yHXjjAjaVSkCX00PPoW43aLKGe4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842091; c=relaxed/simple; bh=GI/HRamz0A9nTmhIYaRcUdy+AS0tmF5FHDmDAowKCZ8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=CevofZALP1pSLRRjr9MrPQ/nwdLI5C9CnN3r8dqkbLNdjSKclaovElouirzideohryiBgXwC/AJjQURwpTYjsExv4Az4YNt0GP+pGAunQEOjAf7QixgJO9TGW4Q+WSC7w8uQ8NErtAzqcwRpBaiEVliMBLhEAoARzucPg84vQJA= 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=axNg0GXO; arc=none smtp.client-ip=209.85.210.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="axNg0GXO" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-7394772635dso1855952b3a.0 for ; Fri, 13 Jun 2025 12:14:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842088; x=1750446888; 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=4rMeuU74h5CSIH9hxIbH8mLUTFGAWwn0IzijX0pVe6g=; b=axNg0GXOl506XixvCk1tR/gIgSnng0+i+Ob7J5QoZ7CpayR3A9hMCPzvwx5Aex92d2 QRm4At44RO/jvyTG1r3IkVIkKrq4fb/PsNlzsIwIHbayeTEeJ0ec+wroMuaK9j4v8ZDm Bq67asYaA1BCHdfJ4ZMs3Sz/dAZF1pC36oa8OXX5tso4TtkxAeBzObArLR8FO8JINFE5 pWWEA6Pt70ZyfnIbnY/BZnZlUqhAJQkGDrV6T/fd5ysynhusDac8AiLDKUU4cjssgjZC pHdQDWhkFIRUgMSwNnYErzW5yf0nEuiLwTYhcRXNcQg/8xakEYTk8+GsFTne4TYBK+bt 6XPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842088; x=1750446888; 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=4rMeuU74h5CSIH9hxIbH8mLUTFGAWwn0IzijX0pVe6g=; b=QgXe4ZYdk1w5cI2G2ajRkt8Z+NNyrSYRf5pusRIJMDfs18Ci8Fh0JpmVBqkd9Wa0Hv XBN2rcA4VygkD5l/v2gv8qnjt1ewwLrdWX5nJOWj3ad95W5svddQLPR3NKyvreWbQOyp c64ayZDKD56U+WKQ9iYejXOvvQZIFrmdZf97i+aFfMq2KGadf5iw6C/MY7EDgZcyooSQ SIZ3RXezqWqSLtgJxHH0dqZnMvXfWxw5TTCa7SY33uKmoQXZOE/jT/V7bFI4zU4wAqL4 pec3jVUavzKsTp5vZpSqXGFuCDLIW1pxR1ZVDNTOwQf0HCZ6p+EFpD7rze40635EILtc UrSg== X-Gm-Message-State: AOJu0YzCBzmNU0Ctcn1/j6fZQjwG+N9Y34z3PALMkeSes55yBHVYoMUR O14F13wUBBqpbdM4wdztLsOxG37MbyP+tpcA+yxTbtJlTNblJ7/CxdNFih34HZqRVi2gBKigrxr +gw== X-Google-Smtp-Source: AGHT+IFqmLxnOnp3/LNAxyoARkF3H4GUBwyJGZS70Wxpb4YSbxmlFMrSVaoI9xaXnRVY/6IBtdS3ocCcfw== X-Received: from pfbeb14.prod.google.com ([2002:a05:6a00:4c8e:b0:746:1e60:660e]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:2185:b0:740:6f69:8d94 with SMTP id d2e1a72fcca58-7489cd4987fmr728736b3a.0.1749842088479; Fri, 13 Jun 2025 12:14:48 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:51 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-25-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 2025 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.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 5A5162E6126 for ; Fri, 13 Jun 2025 19:14:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842091; cv=none; b=WpnybSdW2p6ksMK0nEUBGeLPdSIfp4f36DJt6HKH2/SNfjX0+HX7fMnhq3x9St04N/+cuSjNQxJ3zzimT/z0+QF8EBFf+y7HlPf5WI61fkLc3trwVYn+qHc8s7hBJScYnaE76Br8E7Q/hYhyQvoEzmczYVlBUWNGdzKzFG2E6ck= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842091; c=relaxed/simple; bh=EYmmSlBF4C/72f7adu2xrFOYMqAVykY+Yges75e1mk4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=piG6osvPLLCoS6KUZZRvvQxxuZpS2b+Bdng9j64YFMiEaKOK7n6HTIPOmmF6NxdxUOivR95XfMGEXxt8SOWLQ+trTxCGj1uEqzmndBZgV2y50vdYaxQW1gdxnoOpm928k4LeWySaUbAmQdnmLfyeNbzJMBdiYwZ4nlxpNg4/ULE= 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=mc03Tefr; arc=none smtp.client-ip=209.85.210.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="mc03Tefr" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-7462aff55bfso1856311b3a.2 for ; Fri, 13 Jun 2025 12:14:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842090; x=1750446890; 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=uQS9KEcxjrfBhT5g6y6btmmw0Zrm/EBAnz28lESsUJQ=; b=mc03Tefrk34C1Ez1tsp8bzS/pW5L/dgSM+oDnEu8kCEz/Hf89u5nPArn3PDYVLZZwh mHlLRe4CIAVX/6f3Q37gpzPfFUFVhJS3fxHA1fuWIi3xOPTvPG3ZIq7tADUB4UZq/CXd 6/FtXg7QLDu4mJIhfHoRK/IZHUQKK9jsQOx7Ofyv5o5apTWYHMF7Fo+IVtv3se5WUaLg Hduq0xJZBM+yO1JHaTsdyuBtVjbMRWuJDHsNKEh/qcOf1yWXprixmY+PNDqinuSz3KGg Sm1UiRxFUiuW/FlVIOiVpIRFj7rXS4b+Ut+KaH4zCCfPoxJhZwCFCeoviz4jEVFpZ0EH /Btw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842090; x=1750446890; 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=uQS9KEcxjrfBhT5g6y6btmmw0Zrm/EBAnz28lESsUJQ=; b=YWuszAyXE0ADcFZh5+SLWlnQC75xL+HnTZNDhzEYKD46r2HizHT9PhUyWKqwBzb3Sz pL9SJHgu2oiHj8RRSxsMHNzJFya+VXEmoniSpznV6WtVnaxGZ9mHe+Zi7H78lX7aOHg7 zk+bAqh5xdbAnP0iwsaJaDa68MuOeYmL78tuNqyBjn1oUI52hjjHmOlEudM8K4KyZJkO S6eyVU5XjJ4C2vytL4LVySE8jYuaRAalLtXetDEPCR+izrTTe9s9QCdi3NvJYenAJ6fx KP4z4MrLHTcl3PYzWqT6m2PCBPPJbq13TSHL9XxJqdHFxoiykyrpOCesApKJqV8pEh4V v7ZA== X-Gm-Message-State: AOJu0Yxh7/cZA4mGTY9O7ed/qyHHhjmrCVblA33zrdx/pMWGBLyl0+TJ poNNwYAJVgwARrdOojrjsoixxfKrjsbOC1MXE/VrjYKvOp5Ru9l2xhS/pBqDljWTJLtTr8cFRp2 0cw== X-Google-Smtp-Source: AGHT+IEOP4GrUzQcNjvdcHvZ0T90I3oYrH2Eb488bsbJSQug0p1LrqzO/9hpSqb5M4HMhpMKbNB+gqPsIg== X-Received: from pfbhx21.prod.google.com ([2002:a05:6a00:8995:b0:747:a9de:9998]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:2185:b0:736:a8db:93bb with SMTP id d2e1a72fcca58-7489cdedbb5mr672632b3a.5.1749842089751; Fri, 13 Jun 2025 12:14:49 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:52 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-26-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 D13A32E88BB for ; Fri, 13 Jun 2025 19:14:51 +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=1749842093; cv=none; b=u+bHeP750IcMf808hSUjugFQ6c+V940zTk7E8uDfYArOCs9kRMpYN6vuPIItpnmPJev9YFHB/3dVnb3N8bTB1+QMqcXVJbMEiDGqNBvMEQhSR0znMBZsVYNz+dxBIQoQMfIfqzv6jKSu2l6u5FpZxn2PHsMoS9Gg/F5fhQVVhIQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842093; c=relaxed/simple; bh=p5mVv2Pn2uoXBdPztpidNAvEhFnz01TXj3tCpH3ztA0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=biJMr8cI9LPTGUUYJX+3ZBwSiCy91O4ZjRz/u7jAnmPU88NhIFd0mDNLv71BFeGQUaLZO9/pRaACwtMnBfZIc/wKLElf/ovAwOmzSqROAczAm7aZ8JyfEyfe5cSzXchatp+xCiZSembmdj3POvDrSAHXj2Xy7cM4hvfaDOOvJqg= 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=0UJwAMhc; 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="0UJwAMhc" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-7462aff55bfso1856323b3a.2 for ; Fri, 13 Jun 2025 12:14:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842091; x=1750446891; 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=HxHBtKGYFXqL/z5tygWlXIcu0CsriDSTXmUMupVW9L4=; b=0UJwAMhcajYHqz519rNcB9dKPDD3ya+V0QcUzqWKvmEr9w9ME1eIM4vLeriNUhSD70 /B2qXRExMN+yWZ2H1uCPmyfAhKgVLeBevDATocTcTAkbLGd3ZhjYXnF1d52rjbb6OsoM HO1Ue+nPP6Dal37ocZh+TdyPBcOD/Rm4HiegYBnnD0nkwLU6Nwdecrm1OfwSgr6FuooN xkvhA935bmp7i6h7ul/LgTQaS2CXslCtuc+mEuERYg7GK7Y29RSX1pvW1UMZUGgNoIPl jFK0BughxkmTZ3IyNoeFOx/TBFwf5KlWt6GxNoetpttxI78jGPkYLvVYGQpPiXNzGmSr fvzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842091; x=1750446891; 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=HxHBtKGYFXqL/z5tygWlXIcu0CsriDSTXmUMupVW9L4=; b=LRqacUoEoN8jVCBFpKFNrYvQ/IfH/90pbQF+HaDn1FE+ayZrz+z9j2fBr2Fa0YizDG tu0DFyXr2rHxcHNcDJwtqjnR0568fzDdzXtwn3pbTwvgJsTxGQQoi6MizFGNsUhxYq4v PTMNpGYtJ8OW7JDdvT77nuLGa9eEkgOp/O7hiOC41wKKZJ8BBsBkYYYev3PIySpnORlV TdFEMJhuSobe1K5PT76o/l7kHhB+Yy3SumNj9tPcfRbdff4HcIqqFjXJxPFe/h3s0udf TQixBoJDOZcVqwT0JCv3DYObXEq6zE1Gxt7tPb9PFnKf0wwJKhtvh3S6Oyd5F8CvtnhK L1+Q== X-Gm-Message-State: AOJu0Yz9roYEX3U/imoszpkhZsFUrqYVcVIODjgjgkDs/bfDjpreGoy9 hUH7/3LJuiJwrleg99p4FWTwBQEeyCCoXL7k7ID6CNU7uELubgXiEsX5BTfR2oZH/9/R4++NX8f IIQ== X-Google-Smtp-Source: AGHT+IF9SjxAJ1+SnSalJ4CJc1016/+azFzl4bh2ehvVkOztXbbhEGQS0jSxCgxjTy3Ydq+j8SkNUNlZdg== X-Received: from pfjc11.prod.google.com ([2002:a05:6a00:8b:b0:746:2e25:5c93]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:852:b0:736:a540:c9ad with SMTP id d2e1a72fcca58-7489cfca938mr735078b3a.20.1749842091283; Fri, 13 Jun 2025 12:14:51 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:53 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-27-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 62A692E92CC for ; Fri, 13 Jun 2025 19:14:53 +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=1749842095; cv=none; b=ge68Yc9L24uqJXXX/KMkIINDyC4afdPjtWhxlXAk7wRItz5q38E8bfN5FDDY7UwIlrV8l+S1bFTNEwFBzV9dy7Yf2Bd96u3JLmp6fhX6cn5guSsP13HxqCV6uGTXyJ751KbNP/zQ5DK1CrehLKBin3v1IN2iFv2NqEDxFAS+ueU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842095; c=relaxed/simple; bh=hUSC6q/u5XglC1U4gOPTanfZQQlW+0KgRtgJCMI3QJw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Hm97QpHo1Maf6NvVpTSJf/veg70IP9/sRG5BUUuLtKfalGjvumCv1wFuw8P2gOZoplPw6nN3ObvypbheFcCiE5ps+nJh4sYa4Kvq8Rwe91mr459hUttREw8e4onGzJfyoRXXbgVSURZj/ggmH4psUsdFjDBqXdJHdAB1KVZu/Mo= 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=yCRHOpyD; 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="yCRHOpyD" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-73bfc657aefso1834236b3a.1 for ; Fri, 13 Jun 2025 12:14:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842093; x=1750446893; 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=Wkd+oSBsV61vY+nLf2ZlPchh7IouawdO+jqDmSL0Z5Y=; b=yCRHOpyDzyRwIjRhnCofAUxGE1oJK8bjkFT8YmgaeiiU2f1aw4ZYywts/vQLKS7cwu +w38BhgA7BiILlyk4+DFo0JmeiIbE0RqjGq3YpJDCS6H3y91HU1D4PY/eoFRc63N4WmW FCJbUw+8cRSh7KrUAqu7Nid2aTBwN8zo1vHGR/r/TrdIkFUUA/2B5woYilOPiw2DJTmJ 1MDWAN8ExnFvidDL27eBBgh9tY21I6NiG1zK307eJNl01E96eWxggtcy4sW1ehFhDZ5C UdncJwQC0dVg3hvf42MncLA4ug9jXhRamUHVVX/xDG6XozCJsvwaZLcT4MVQ+fCcJQn3 AXEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842093; x=1750446893; 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=Wkd+oSBsV61vY+nLf2ZlPchh7IouawdO+jqDmSL0Z5Y=; b=OJVj95RUYQc1uV/L/d62vWNCvRSXAtYPRspONR0aKAJVKAHEZfWVzts99e8sZcXQbj Xh2AHhkp9BwJiwaLqshlQK4ZHwFDgr2/NTW3uIZvC9pujPSLC7w6tk8WXNgYHrZ4m4Gr pPpRbk4oxuILYc15m4xW9FA35MZByJyVlULX1A0R4WhggbQht0YGkMcrb7LX8RSDYV0j UIrjCGAzIelUxzbwinHYKBfPgIPMU4EzqdlUc8ohbzaLgCq61jXPCDWQKetZOrQ2TC4V Uye2VTJ/YUDfdNxKVFliAB1LMOOWHn798dfMtal4+OvZ8NMttvBCyiin85B2TUZv2Oaf jX0w== X-Gm-Message-State: AOJu0YxMdG6Fs7OIWqM1aVDC8XT/mrvmWjM6Zfj/ofRH41LWMkZYJ2IC xF7ssf2lEKf/b6GkENiMQ4ITODgXWI0NvVrFIrh+CIkYzeD4X/hMvSYGmV3tiF1K7+fqaeeaUZd 4Yg== X-Google-Smtp-Source: AGHT+IEdGLNaT/g5MhxH3XF9cuZPDfuAeWyjHSU8EzljbNMvFxWw7iQfHx3fRbY0rVLIvruilLj4TmF/3w== X-Received: from pfbft7.prod.google.com ([2002:a05:6a00:81c7:b0:747:7188:c30]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:a86:b0:732:2923:b70f with SMTP id d2e1a72fcca58-7489d00631fmr571690b3a.11.1749842092790; Fri, 13 Jun 2025 12:14:52 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:54 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-28-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 2025 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.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 DC3692EA477 for ; Fri, 13 Jun 2025 19:14:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842097; cv=none; b=bR4xQeFczcCpfuL4XkSwyOo2xbS+vB+JBQ3OOmhEQH60smaV6mNTt7FaP9nOo0t0KOe3H4wrODKIo5yP5f8e1oOD+RLUOIlRdIob0C6tzhb/1hZ1GVqm66kJKgwKxS6rqH5DbBaueK0tEmSfBTq5uEHGbcWuWIwbLfdszUzCOiQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842097; c=relaxed/simple; bh=1XbUQTojtqrI8SJOv918HLsAiM5OmDDym8SFwyoCStI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=dp+8u09My1kL13kLCChS89GsGHv10VH1o81KvPKIy2BOI6xZt/axG1whj8FgfqMpCXVrhjpa5GN36lZNtIdMxlPoPNzSOOt80usipBESJ2mOZumtxcNgFxC1OK8xy+b1fdFsXFiJ3tDTRjM0eCg5HmjJ3wa7fk7hBHMxjDC9Bxc= 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=E4VmeJBl; arc=none smtp.client-ip=209.85.210.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="E4VmeJBl" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-747adea6ddbso1970423b3a.0 for ; Fri, 13 Jun 2025 12:14:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842094; x=1750446894; 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=Akpjr827bJq/cVE6NQhFQJoJyM/gV3cxmcmZTjVfLUg=; b=E4VmeJBleygCL8b3GxpKuSiF8CxO4Il9+BrvafIKSIXXFhKKH7ThLQwiINOUD3ykD8 vuaTk511e8iBMcddGv8CMv7naawwnvguSAHTzcXqe8hfItdr/s47hERz494wZBkkiSVC 2PoGHb/zlYZbDvSBrwQRTfu7JHtLscah5fJ4W3mtqEPzw0QUaOWm9d1tUMJHChIudP7k /5D839sjl0TJM/3cqS5C4RaysQD/A3tvwME+MarS0qRhDOFx0Wx6FMC0rFr1gzGwTssB 63PkZLw8rYiVVGQGopFNsnFRDhz68QUdvDq6iMmxv5XBeRW+XXr4nq3t87k+gNMV6m5j 9FCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842094; x=1750446894; 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=Akpjr827bJq/cVE6NQhFQJoJyM/gV3cxmcmZTjVfLUg=; b=XObQZyxG/nWsdO43VPZzcvZtiYfBIdhpEwVESRO0iT0sBCu2v3wemO6SbYSFkbJQ6Z c/tOk9WSsU7OXTWO/ihcNsMJt9Yx+zKl+hOiMInmx/ND1Y97+pB31wLCvR4xjxoApUZA BaNUB099v7uX7lpGv7iLIfhBcpL147rl4UdX4hiXOGo+lnUX+cMd2Irv/+WEzWNnTVv4 ITF/ct4EFps4tfSUlKLccZNBhFwX/FVOkqZmApEgXe+HxpkMWZ1N8pfUtR2dgnLyOB+Y qmRkDv/6rk0X/sF0qYIhwM1Ai/x2cc5hFTeuOpSuW8AQKL/tqyn7qe25X7Xe0W0VP5K9 B0YA== X-Gm-Message-State: AOJu0Yyr2zD44YdLgz5IpcaAr2noZl9Sdwsre+DzKJNWqoLeeHW18Fiv OZoVBG+dpMwEvv2UACni/M3X/I2nCGLGVVZfkbGSzAUnf0P5wg1IJnGrCTNllYPqxnENEh7u5jI tQA== X-Google-Smtp-Source: AGHT+IGxoJH5VlSsY4OI2zMIRRA9IFhtdNsS8XYtVXetDWuQ+t3EZXWW39H7uoDS8/HbEqKDbZ3Tfk3IJg== X-Received: from pfbko19.prod.google.com ([2002:a05:6a00:4613:b0:746:18ec:d11a]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:2f8e:b0:215:e1a0:805f with SMTP id adf61e73a8af0-21fbd57d938mr722241637.31.1749842094065; Fri, 13 Jun 2025 12:14:54 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:55 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-29-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 497D42EACE8 for ; Fri, 13 Jun 2025 19:14:56 +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=1749842097; cv=none; b=jsJO4EhJrCwD7fAWXQPVKzl8Puxjhn/1KQGWEuD1hDk3xD/cNBW3XSY9dReoCoXS1sc3JpmQ+CUvp7ehz/jhdpARDJgRmQj305H7VhiQjKLh9Ze8ojlhrnElqN+HdpmjyQcKlapPGnxjeF5XxjHdvwUdWr4c5z8k+bhVaASdIGs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842097; c=relaxed/simple; bh=D0z2DmoLhUuOHBY22PFbuMZf63gkVoAErysUEUFr090=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=fNYbEthFMmQcZmJgBAdiS8ezYk0KE1Z5rB8WtDjj2ULi7nmORa4uv8qozHv+Tg2kuI414jJWWnJtVQtnj3c+VqQGbMDVQ7fz3yXmHPBH5JDcLr8yxQDbC3kUEXMfKYL4lf7+zx9GqxlazWyTuMjlKhFwsEyO9EgI38jpMFBsMQg= 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=nXIFeuBM; 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="nXIFeuBM" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b2ede156ec4so2828306a12.0 for ; Fri, 13 Jun 2025 12:14:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842095; x=1750446895; 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=kyJaH6uxckiTaiOJ/SEHlmwNe7lEYUELWf4fETCCzOU=; b=nXIFeuBMdPWGeWlpjSWpSU+I5T6ifHfw2SyJr0dIffvo2QE6IYvNKjcsXOKrC35cDA 3wu65gquNMX9egDstEmiPPLgaEIqNYMm4xc9AuFf/vnhICtT/ESGAukDIMBgprqlNOks hiAk/75x+IG5d8tLIpIk5WClrSD8ZbxDXZ8H8YOIpdJjxpLfPyv9U93wtoZ3+P8c6u1c MvZ0GjNYHv+5sYPUuSJfaBPAXCeipyx0CuvWsvoEkZve0tEZ7lNFR3RjKM3uI88RrcER t+hqPT/K+E3Jr18MXaiv+Q7zhpd/jUTkQb36lUycxafAP2a1Spo+tTpXZpJlW7+wug9J RGwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842095; x=1750446895; 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=kyJaH6uxckiTaiOJ/SEHlmwNe7lEYUELWf4fETCCzOU=; b=jhCvgVJZ1/+n4+PGbdpw+e2LvsnyLGTZR1OJY8l0x+hjS0kaUSMqTHlVtUovJ5oaj/ 0UVeaiCtAvCPAqJ7VzAmPRhld1qH/kQKyopzZEWaV/V7H50cbh7ZqtY4lstjRhzY4oDa gDgzYLcrzS5zA7SXdJViGpkzIfteRe4odfy2FF28mtUU8DFKyrJ5KqbHRImFhlPSJD1Z Ta13Mj71k4LESfP4v/pz2CUYpWVZ4+Tjlw/0HdpLVCeYyZkt3wSs55fPaN0yU+W9pDFg CjEzOi0f2qZSte9cJtc1Qd25v3noyyTUUcUbEJNYxdSTO7MtqCrj1Ab2Q+qgZPEpgpR+ bDHA== X-Gm-Message-State: AOJu0YzeD/TEWhgCZ6jND43vkMc3mIGnR/TCt0FqZOt1rxByUvSCU2gd /npkbQuuY40qml7Ynuz0l8GZiqPgm6cWBzSoHV1VgqcEy+F4CywJZDN1BpU6tLkK2epQUTB8103 5SA== X-Google-Smtp-Source: AGHT+IHQezC5oUFrhIim5QwTrv1F2wDGUGY1Dv9R8DZbSbtzmm4PNG9QgKBc2yKOesGF9SSk/0tA6ODxHw== X-Received: from ploc13.prod.google.com ([2002:a17:902:848d:b0:235:54f:4f12]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:fb47:b0:235:be0:db53 with SMTP id d9443c01a7336-2366b177269mr6424445ad.51.1749842095556; Fri, 13 Jun 2025 12:14:55 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:56 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-30-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog From nobody Fri Oct 10 09:22:18 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 936392EA478 for ; Fri, 13 Jun 2025 19:14:57 +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=1749842099; cv=none; b=a56sSaQx+jh4bpqwCNaWn0MVCG1XP78tsvBkaRmkO7KG9qrem50rNOQyYycP8irFHRJkUDENC7a3rgIoVbnRBuLGKDMz106py4mf3JKZ+Hf3kYP+kcTzBbWMmmfVPsiTmxy2YDpN+FnQq2hfneJfUFWBAkNUo8sRSiLKL7oZaxw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842099; c=relaxed/simple; bh=RY9vOJOTnPoQGM71RK4CQ3oaie3GZfCxmMPWtcit47k=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=f78hoy/s1S5R3Bq+cJ4eon5tTdvd5RIb5krnWvPgEkhR/Y8jICsktoTyPm7FRk7RI49GYDlalMea7iNdI5pKPEFiN3puGdxwL9BFxwPswxEdmBLbnrIqTKTap/WI/amBkkY5oM5xMeU+fqWPRpvLciLPbdm6tus4tMkepaiCnvs= 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=PWCKb+js; 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="PWCKb+js" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-3138e671316so1982324a91.0 for ; Fri, 13 Jun 2025 12:14:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842097; x=1750446897; 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=yEGB1XBlJyFOc33mF8HkysHzlE2Wpy4+59tD02EfyJ4=; b=PWCKb+js3f+k1T+cL+SeXTWAXJaJYEvyUOzF0edP/sQOdVA5DpO02easxFkGp8czLB BfsFL4ZvW8soJz+z0kYNCYj3qGuKfFcHfOEvuF8E3v4/inN2I+gzEHRkUiyHWEm0GzF1 Nxc6RtvwYxGkwv0yua3bKg+tyatrmKcjiOXb23wPAAEFNcuQfW6Nh0FtcVdaOFUf4Vqg WUsGESPPMq/HBq5tNbSoHNk8kBD4y6crALRPaefWzMtD6+1Lk+33ZhA33AHjxaz+cFFW hq8o7GDBPYsXgXRBwbjX6qWHfRK1f2J6htuaU3mBGTmoMQozaW5xjQ//6zAwZsYuWTr4 BVcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842097; x=1750446897; 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=yEGB1XBlJyFOc33mF8HkysHzlE2Wpy4+59tD02EfyJ4=; b=ZGD+3JWEAAuzM9nwOUJL4Z+H1zPIC4tvHPdawy54ytg6DbA7JRpn71gwFubN5cSG0l Al73Wb8BMNVoc0vUoTQIU1Ctcrjunqw9X1zibp79Di0DssjjMLn4e2l7mRusqsIO1oOr Kmx/7KnVvrlHGLv6sypTq4ej1mINvGG8MFN4xK09V7w6AbS+1tO5X6A/Cpw2PpwJ30f0 YTlo6SzVRHkXCOG2C/Y8Sfl02HaCC+mkpFxwr19HVvgETGCB1v13RSon+ZCBwcpCRV2w +tCliN/rzSw+ktrEr1QCVWESOo+SQe/9/yJFsVMCs/Dmvwq/9pyYR7yJmWazxkY3hoFZ ZcYA== X-Gm-Message-State: AOJu0YxQM/iqxa5J1RhMZBl3zOAFCNElHMGZcLCBzFhBDCDaFj451qDn Yg0Gp6ObqEL40Kbbe2TbdqKpZt/Y3rqdP5zD/tbaDtkzGXJkDwuFCAAfCFEvuQU/KRptzb3D5fW jKg== X-Google-Smtp-Source: AGHT+IFFuR69PJDd7BsIpTM0aA+lzThoYubZQJbh5cEx7KYbBwGWGloMSfcPdi3XNIgGq89r5XPgiBtCPw== X-Received: from pjyp8.prod.google.com ([2002:a17:90a:e708:b0:311:ef56:7694]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:17d0:b0:313:d7ec:b7b7 with SMTP id 98e67ed59e1d1-313e90c5ce8mr2569833a91.13.1749842097051; Fri, 13 Jun 2025 12:14:57 -0700 (PDT) Date: Fri, 13 Jun 2025 12:13:57 -0700 In-Reply-To: <20250613191359.35078-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: <20250613191359.35078-1-sagis@google.com> X-Mailer: git-send-email 2.50.0.rc2.692.g299adb8693-goog Message-ID: <20250613191359.35078-31-sagis@google.com> Subject: [PATCH v7 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 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.50.0.rc2.692.g299adb8693-goog