From patchwork Fri Jun 13 19:13:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897200 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 01C2623C397 for ; Fri, 13 Jun 2025 19:14:14 +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=1749842056; cv=none; b=VirNEs/uniMBFUDQrHVmVl6SJgh8PU+nq88GwvhEerF0avnaKWclzGVCe8jWyIrUrs3CmB40I2vPpPXWVODT7i4sqnFPZMIlogtJPLw2JVVs1r09z4wZNjWBmpnvLtUDpBPPBy0YFCpzIzd+bQtJ2rkmcHdgSnDhWhNo9Ccjxkg= 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.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="wUCMjW9H" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-745e89b0c32so3896717b3a.3 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=rfJtugEKxEi0ksS8U5FI3zTztKjDMOpx9fjiETiVkiBN0t9/qZSHiljt5OpucsVCi/ RCu6yuf+urE+bNbBZaILDF0UgELeABxioUI52THf5zRtPYRZyI7cdl8PPMy/APdXSWsW hH3NRpnNPvbLOPr+hr6/Kxdul2u8ikYYVPGX9BfCzQxvT+QNUddEwD2SDMnlpZHB9hkl dPxnPMaTQV5TUJlovMQQZuMh2FYVo8lDhkyR0huBQX0SgOm5aU0hKsIv7wFotfUtXUMe PjxWYwKhfuTZtLbfpOk2BXicOTyzBIIpMFo362rNyF3Y0zhyMbgL4nLAXJJCNG4kC5Wz zYjA== X-Gm-Message-State: AOJu0YxLsC3J4bPDTp93mDghS0Ii1wB1FYoZeIVWBfvibMntDGWKSMG1 FIYpwKgf/g/y0mZ4aFbqpsxE7KZVqKEAJNEAI8TcDx7OxKyZvp0ZcAvr8xUEUWIkQCCZSJnsZSp zPXnU77Wo6SaOyZQ9lHM72+/4iUihDZDOYJnBAkH2x8uSsyhk39skoIFEdVY3nrSjIrWiqH9s7w G+hWAvi/9W6agOqH6c4yVUOK9kqK9gG2QBGQGKYfIBLCU= 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-kselftest@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 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 sz, 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/selftests/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, size_t sz, } 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 = (sz >> vm->page_shift) + ((sz % vm->page_size) != 0); virt_pgd_alloc(vm); - vm_paddr_t paddr = __vm_phy_pages_alloc(vm, pages, - KVM_UTIL_MIN_PFN * vm->page_size, + vm_paddr_t paddr = __vm_phy_pages_alloc(vm, pages, paddr_min, vm->memslots[type], protected); /* @@ -1492,7 +1491,7 @@ static vm_vaddr_t ____vm_vaddr_alloc(struct kvm_vm *vm, 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)); } @@ -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 address + * 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 = ____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; } /* From patchwork Fri Jun 13 19:13:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896550 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 8911A242D64 for ; Fri, 13 Jun 2025 19:14:16 +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=1749842058; cv=none; b=qgXYTtDGcpqRBBTjVgEA56+AMUQxpazYk9GWnYfxWOgGQJumvpn9Cn3foakQHuRYiv/N7rGL2wGJp8vc4IOkUuvxOnD/c0+GZ0zQnxOs8t2OF+Xn4RnK1Wkxa9oPQXmoobx+tUEJUW3ZhtFnpTKkacaMvv0UBrVyQVAYn0bwOXc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842058; c=relaxed/simple; bh=y/hrB1WH2W68tURtle+cVWCtRB2T0n9nfcp8qRvBYpI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=YpA0hJDnDSSan3IunJ5/+J2Cf4ff6WA2p/ICqDEEzU4h+UqKMRdEmrQyZjW0VpHfxc2ayMdrigcdxEpKijOrurj/E3n4xVjuLLoBhJJ6dNWx609Jke4TnYDo+3ghTjLKW/1/krkMNobcei53D0yiOF2Es+xEh1w2h3gpnwvsm8g= 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.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="xHlTAdJW" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b2c00e965d0so1582647a12.2 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=qyJ5NjV/sP3MSCpA0KT8CZ8nvaIZeblal27kk781NqfimiPB1qXi9e8+UAQko1++Pv +Ro8mY6sOScxUpsaBmFcc4z/K1nagiZWoiGojmLXPFu1L3MxMp0Rt3lTlS3LSSv50NzO tpmQKUFQgDtlFDUbY4HsslzBzajjtcsto3kYYnaC/ngXB2NuVTa1Dl6L1DkJqPyXxLgG BolF71f9Du0hKJU3X66t96JCu5QagMpNBUlB5UEb6MJWVBH/gno0Bo6LrFC7aWiCvrrM toUkatwZMB6gQZAZQzsOyOvB2RFgm0ybPQLqQZQ361Hv8V/avLKJZ45H7y7K5PbKdNLg UUiA== X-Gm-Message-State: AOJu0Yx9DruArZPFbsM7q+n/uCoMhO3AAfMpbSSlAadwLd/oVWzZA4kd DhyePiqtpNh1M65BAbtz6zCZsWlHtklk5bjywkKlO/7+5JkvXsjYcYBBC265VDg4OtKCFgPI0kI cN0uqnmcFLpTrJLz1kO3m33pIBekkkR1fbdYtjlyndb68E8vk4OzG9sJD0cZfJL7OFm6Z6rvY5i 9a34W6zbECgXjviiofyAXJeVv/z9Iga2XAckkZJJ4OYVc= 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-kselftest@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 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/testing/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) } 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); static inline void vcpu_get_cpuid(struct kvm_vcpu *vcpu) { diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testing/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, struct kvm_segment *segp) segp->present = 1; } -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); - /* Set mode specific system register values. */ - vcpu_sregs_get(vcpu, &sregs); - - sregs.idt.base = vm->arch.idt; - sregs.idt.limit = NUM_INTERRUPTS * sizeof(struct idt_entry) - 1; - sregs.gdt.base = vm->arch.gdt; - sregs.gdt.limit = getpagesize() - 1; + sregs->idt.base = vm->arch.idt; + sregs->idt.limit = NUM_INTERRUPTS * sizeof(struct idt_entry) - 1; + sregs->gdt.base = vm->arch.gdt; + sregs->gdt.limit = getpagesize() - 1; - sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG; - sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR; + sregs->cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG; + sregs->cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR; if (kvm_cpu_has(X86_FEATURE_XSAVE)) - sregs.cr4 |= X86_CR4_OSXSAVE; - sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX); + sregs->cr4 |= X86_CR4_OSXSAVE; + sregs->efer |= (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); - 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 = vm->pgd; +} + +static void vcpu_init_sregs(struct kvm_vm *vm, struct kvm_vcpu *vcpu) +{ + struct kvm_sregs sregs; - sregs.cr3 = vm->pgd; + vcpu_sregs_get(vcpu, &sregs); + vcpu_setup_mode_sregs(vm, &sregs); vcpu_sregs_set(vcpu, &sregs); } From patchwork Fri Jun 13 19:13:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897199 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 F102C23ED5B for ; Fri, 13 Jun 2025 19:14:17 +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=1749842059; cv=none; b=UNpn9fxMmnMbt94M7cxIc4sddZbJArlFUsoAt5m8KX3g1eTdOd7AzyhEV1sASwQ7W9Yf6p1Kwuxb9Jj12DISO4vGYNvDsyWvAqSJmXQGSVpabFVHZGEJE1qju9tjTk+dvBVs8SieBhp6e+Bc1yoMS/3UcSOYpUHwRkGqL2tL47w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842059; c=relaxed/simple; bh=CZWxcHUWIhBEiyWiB8Z0zKn1NDMKTAMio7jW/0D0t28=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=YtpYFXUc2wVfGXN9APGZciOvDmbXIVL1j0ZbYVTBrC198Dci1FJsX0GFNHLAiGi6pPFMhTX8JFW/VvsepGxjDKf+M275Hu2fuYViKBESsV/kjD9KlxVownX9E+tmA+nrjInZR8cHwZdzBTkCF6j3NltLaB/PeBBgfZwUd/+Go94= 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.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="xWzCelGk" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-3132c8437ffso2697127a91.1 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=oN0mstwJv8HLMRkTLwd2r/VICCH5SD5HAaisjG3aIVgwjymsWZ0HzdKwuXYwbQEoH7 A2DIkXhGImpFrekky939r4lTpK9pkPdeKseWG54GiDG55isXvOMBPjzGdUeyJ121q5R+ 3yTmeFWNmDqx7Gre9ufI1vrgRhBbuzAjbF+VxlT4mJjBKNz4LVLvXU4cJfSgLiQf1G6/ 1HDgoKhS+dXdoZxOcWJ24ZLcDG8dRPSdrtfB9FCroToK9CEHFr/Cx6KJSSwbh7rZfaFV EXDL5912T133LgM8TeeFBiHLPBUk+5Z8BbPDiVxtd1a4dN1z4NySzU0CZwakw8b+8xhK rSEA== X-Gm-Message-State: AOJu0Yw7iG89ezjQCuwUbY81kUiHFQcagfdM0ioCCTHJSjn2LhmqgmYg rQKzfyQDTBPNfom4+v0wz7Uj8YGyd2d7jNQ60IHTi7zH2908mDnhLV0I9qZ2bTzZWtDCYsN5vIj d6eko/rDvdMPFx4JNIHgkSRyRy+MpvjCeaoibnhY+KuF83cy4TRhfOW0G0S7p+6jfmzgrvHux09 q7/yBLd/kQRzvrQa/VqMP10ZdNt3VGPkdj7Xf86L/am9c= 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-kselftest@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 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/testing/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, uint32_t vcpu_id) vcpu_init_sregs(vm, vcpu); vcpu_init_xcrs(vm, vcpu); + vcpu->initial_stack_addr = stack_vaddr; + /* Setup guest general purpose registers */ vcpu_regs_get(vcpu, ®s); regs.rflags = regs.rflags | 0x2; From patchwork Fri Jun 13 19:13:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896549 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 404B824C664 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-b2f02cd1daeso1712004a12.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=ARygrkgPQvxtculnp6iuRNpAnqdURU5qMaHF0kzMKniuNjxdcMDSgfdnVAaf42vGgE ZIPtTfSYMhx0mDUfBkv4Q2gQ0iOuc/lfYNmxHjiXAviDgQSFdLgjlDwbuPLWpG81YXmh zwCvpXLIvvPm0MskTHqnYPEWEuPgG9e48eCL8ZyvNCXYiCYFJwLkSkSbvLYTfIEuQwfS JLqop3BC/9yQWGM1NqVjet8z1zL+G94d06g3jM7xQ/CADwEIP8+9sw0d0mmbRRNjdEO9 CBqj0qANHTYnlkPjui9oJ6HGk0ZQ0iz8ZX/+jDuKl0X429nGe6JSbcJZWoAn/FUq5fNl Sopw== X-Gm-Message-State: AOJu0YwEKyVcczXEBgomEL1WykoVyOgqmWxxywL3O8rqv+75YKdW1INS hsk8va2qy3o1goFaboi3MepmvSYPuDUdaPhpfA9xIbcL+rop+JXPpskEqYSA8JvqURqGZM16Aki iPMGKl3L+yf1oR/o1ye0z8ORSYLEz6S1y0fMn18uwgrQs9TdNRc5p3uQBZTc/YlMB5CuHFKTKyD nLL+2uyfwa93Mf3mNTpXWEGkA+Ub1urw24U1o5wmGlWqw= 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-kselftest@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 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/testing/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; }; +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 *)); diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testing/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); } +void sync_exception_handlers_to_guest(struct kvm_vm *vm) +{ + *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = 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 = 0; i < NUM_INTERRUPTS; i++) set_idt_entry(vm, i, (unsigned long)(&idt_handlers)[i], 0, KERNEL_CS); - *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers; + sync_exception_handlers_to_guest(vm); kvm_seg_set_kernel_code_64bit(&seg); kvm_seg_fill_gdt_64bit(vm, &seg); From patchwork Fri Jun 13 19:13:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897198 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 AB921255F57 for ; Fri, 13 Jun 2025 19:14:20 +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=1749842062; cv=none; b=dpzmGzI77LSHjeDXc2Tx2FD9LvMIdCrskjxxBSSdbaodbl0MLpJ2uJtjkVg90zByzeQOyVu/9kPuHd17d9buzpE3ypc3XEtctSwI1XMj9aBiNb8z8ZARwt9UZ61LHtsiaynARjH16rm4Sx/dULAu8GXTeUx8v6UJgU488gJuC3w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842062; c=relaxed/simple; bh=WuNQeIEjxP0MpZ43wQJ8QH7/E4ptzd6ZC4ALnAIRTio=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ICm/6f7RtFKQHpNGCaQqQYqjmcmcedcrTF24SzkHhMLa60igolDZwTX/lb/nxGceuL9lT15ONiSN9bt/HWQHHhs4X7oRBxGPr1Yc9SvvUx+cx9zoqZ8r/+g74dyswXqwPTJUD+PqbCSs2QONNOlhBQ3zUak8X5zARRrGzvcEoY0= 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.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="Kez1Vmlu" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b0e0c573531so1438797a12.3 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=jjcxvgqJOFheJTwCzGZH2qW6rM3lm0KvOqMSpK9fhN44FN5I6nsnf6AbVg3kNCd2Ir KSl0X5FqAXDlXgn8JhJO67W39URNP7GN8HSGWyr9RllRrvBKojFoqjPa53gyRk3GwVVU KwyK05goRzEpXZY2Xv47QBcOkZxc/R5L8bdDBOniIt01/eW7/Kul9t8noEjBctZ/t1Ie Ka0gRLeZdQO0EJfGP6n4fTHqTDn1Pal7xSnYY7REyaEL/ahgMPdL+6BN+5++SgxsECut GWjj4KRdQoStUK22r1I9avYtomzixc0yg97tW8FHmeUo+31RRA8GjZF4tprdJ+MlX06t b96g== X-Gm-Message-State: AOJu0Ywxx2OmXatxYCFnuJb7vAuHKsUks7G0aVCrwRW0dlDNQkbmtX5u 5vntk4/NlnkC6RxHr2fOwr3AenEhoHuSuJ32jcVUkck6nceWksPUNZ0fNedRdzw1rnLSZKnL3Ll wUOpbL/FO31K5Y61w7YXzYYguX+gtJ9J9XZ/OQj36L5xRhuMpxbWp0HgvG5Wd3trS2oFuaMz4lT qXp/NiMTkTd9k+s461sDrtKi+UU5/ocZ6C9H/05atK5fU= 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-kselftest@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 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/testing/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_bits, unsigned int *va_bits) void kvm_init_vm_address_properties(struct kvm_vm *vm) { + uint32_t gpa_bits = kvm_cpu_property(X86_PROPERTY_GUEST_MAX_PHY_ADDR) + if (is_sev_vm(vm)) { vm->arch.sev_fd = open_sev_dev_path_or_exit(); vm->arch.c_bit = BIT_ULL(this_cpu_property(X86_PROPERTY_SEV_C_BIT)); vm->gpa_tag_mask = vm->arch.c_bit; + } else if (vm->type == KVM_X86_TDX_VM) { + TEST_ASSERT(gpa_bits == 48 || gpa_bits == 52, + "TDX: bad X86_PROPERTY_GUEST_MAX_PHY_ADDR value: %u", gpa_bits); + vm->arch.sev_fd = -1; + vm->arch.s_bit = 1ULL << (gpa_bits - 1); + vm->arch.c_bit = 0; + vm->gpa_tag_mask = vm->arch.s_bit; } else { vm->arch.sev_fd = -1; } From patchwork Fri Jun 13 19:13:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896548 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 5FDA423CEF8 for ; Fri, 13 Jun 2025 19:14:22 +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=1749842065; cv=none; b=OBp06o2DmE4Fm7CNaXt65KkdkXhN7s6sNLWkCMn1rOqSD5SeWVnQ0fW/Zv3+jC+XXVvm9sXwJRIHcLj2cyxC2DraGA/Gt4uwJ3sin5q22q0c+X76I+DXRicsuGti6RfyqQuOIPzoljNuSzNWzLz0yiQV3WFp71Nf8BGIq47S7es= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842065; 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=YfCUxgoS+k8vYcvThQ0Or6574kY0GcyZKYU7nylO/40Y6USYkXnh12mhKkqEkpl81Gq3B40YivtsiKF2NsxOsgbmBgIDg7jnfVwWgHxFmy86XEIXoICAsHZ/tCbyL4UiZZH48J74+IlK38gVg9wHmAscr03HnaiQ0ATYbZW63yI= 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.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="JVsc0EWi" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b2fcbd76b61so2298898a12.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=bhbCTd3cdpIdtjWuXkYn4EEctM6d0d3KeSkyf9OpKi/Ys2IjKhOz3r5AEme8TRxTtG g6p/FHXMKkh3SSkx1mX4psc53Ktm+x5N5E7xdg54NLe4yxUMD0ndZHg1cY9R4PLzeCTt Gud/55SjWE2sFOw+7/cjzHK9kAkBBfX7eh7A84oT3UG4aqwWMJpIuj+8ppVW9592MKj2 pPmiXhKEovLKE5SkzU1KGbcBvvY2bayuLHoZPISw0vAWZ/T2Posw0SYPn8tkGTSZd4aB 2/Mifhnrc0hGiWpdYKNSfSpqubd9JLPUlzFxLFHLTuUvZAYsgac3WlgrvegcRWSja7Wv OLsQ== X-Gm-Message-State: AOJu0YycDIcbYEE6XhRVFcM+Xg60ij7Rk8V2QDTT0bxaT2Q4AShjPy9p 42k+jlSed2hP3hdfsrIfkogwZYD385GZn6aGzPFPAWQiPrRULSAfUx+3MTO41oEympyICVBgT9a cgzPphVNELeHAMtfhZEGqO8ngjYHuQlnw9AAuzCW3W6TdwqP5SCSnJXYErbO1Mqt07W05uk6EQ9 o22JFg/qLymMj56fAYJg2VtrM+xi6LBXpC4xY3EtYMV7E= 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-kselftest@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 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/selftests/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 += lib/x86/sev.c LIBKVM_x86 += lib/x86/svm.c LIBKVM_x86 += lib/x86/ucall.c LIBKVM_x86 += lib/x86/vmx.c +LIBKVM_x86 += lib/x86/tdx/tdx_util.c +LIBKVM_x86 += lib/x86/tdx/td_boot.S LIBKVM_arm64 += lib/arm64/gic.c LIBKVM_arm64 += 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, }; @@ -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_guest_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 kvm_vm *vm) */ void kvm_selftest_arch_init(void); +void vm_init_descriptor_tables(struct kvm_vm *vm); + void kvm_arch_vm_post_create(struct kvm_vm *vm); 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/tools/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; }; 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 below 4GB) + * | Boot code | + * |___________________________|____ td_boot will be copied here, so that the + * | | jmp to td_boot is exactly at the reset vector + * | Empty space | + * | | + * |───────────────────────────| + * | | + * | | + * | 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 the + * 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/tools/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 such + * 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 *guest_code); + +struct kvm_vm *td_create(void); +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); + +#endif // SELFTESTS_TDX_KVM_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/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; } -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 = vm_guest_mode_params[mode].page_size; uint64_t nr_pages; diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testing/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)) = vm->handlers; } -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) vcpu = __vm_vcpu_add(vm, vcpu_id); vcpu_init_cpuid(vcpu, kvm_get_supported_cpuid()); - vcpu_init_sregs(vm, vcpu); - vcpu_init_xcrs(vm, vcpu); vcpu->initial_stack_addr = stack_vaddr; - /* Setup guest general purpose registers */ - vcpu_regs_get(vcpu, ®s); - regs.rflags = regs.rflags | 0x2; - regs.rsp = 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 = regs.rflags | 0x2; + regs.rsp = stack_vaddr; + vcpu_regs_set(vcpu, ®s); + } /* Setup the MP state */ mp_state.mp_state = 0; diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/td_boot.S b/tools/testing/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=4G. + */ + 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/testing/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[] = { + "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 = ioctl_no; + tdx_cmd.flags = flags; + tdx_cmd.data = (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 = _tdx_ioctl(fd, ioctl_no, flags, data); + TEST_ASSERT(r == 0, "%s failed: %d %d", tdx_cmd_str[ioctl_no], r, + errno); +} + +static struct kvm_tdx_capabilities *tdx_read_capabilities(struct kvm_vm *vm) +{ + struct kvm_tdx_capabilities *tdx_cap = NULL; + int nr_cpuid_configs = 4; + int rc = -1; + int i; + + do { + nr_cpuid_configs *= 2; + + tdx_cap = 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 = nr_cpuid_configs; + rc = _tdx_ioctl(vm->fd, KVM_TDX_CAPABILITIES, 0, tdx_cap); + } while (rc < 0 && errno == E2BIG); + + TEST_ASSERT(rc == 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 = 0; i < tdx_cap->cpuid.nent; i++) { + const struct kvm_cpuid_entry2 *config = &tdx_cap->cpuid.entries[i]; + + pr_debug("cpuid config[%d]: leaf 0x%x sub_leaf 0x%x eax 0x%08x ebx 0x%08x 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_capabilities *cap, + uint32_t leaf, uint32_t sub_leaf) +{ + struct kvm_cpuid_entry2 *config; + uint32_t i; + + for (i = 0; i < cap->cpuid.nent; i++) { + config = &cap->cpuid.entries[i]; + + if (config->function == leaf && config->index == sub_leaf) + return config; + } + + return NULL; +} + +#define XFEATURE_MASK_CET (XFEATURE_MASK_CET_USER | XFEATURE_MASK_CET_KERNEL) + +static void tdx_apply_cpuid_restrictions(struct kvm_cpuid2 *cpuid_data) +{ + for (int i = 0; i < cpuid_data->nent; i++) { + struct kvm_cpuid_entry2 *e = &cpuid_data->entries[i]; + + if (e->function == 0xd && e->index == 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) != + XFEATURE_MASK_XTILE) { + e->eax &= ~XFEATURE_MASK_XTILE; + } + } + if (e->function == 0xd && e->index == 1) { + /* + * TDX doesn't support LBR yet. + * Disable bits from the XCR0 register. + */ + e->ecx &= ~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 |= 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 &= ~(CPUID_EXT_VMX | CPUID_EXT_SMX); + entry->edx &= ~CPUID_PSE36; + break; + case 0x7: + entry->ebx &= ~(CPUID_7_0_EBX_TSC_ADJUST | CPUID_7_0_EBX_SGX); + entry->ebx &= ~CPUID_7_0_EBX_INTEL_PT; + entry->ecx &= ~CPUID_7_0_ECX_SGX_LC; + break; + case 0x40000001: + entry->eax &= TDX_SUPPORTED_KVM_FEATURES; + break; + case 0x80000007: + entry->edx |= CPUID_APM_INVTSC; + break; + case 0x80000008: + entry->ebx &= CPUID_8000_0008_EBX_WBNOINVD; + break; + default: + break; + } +} + +static void tdx_mask_cpuid_features(struct kvm_cpuid2 *cpuid_data) +{ + for (int i = 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 = tdx_read_capabilities(vm); + + i = 0; + while (i < cpuid_data->nent) { + e = cpuid_data->entries + i; + config = tdx_find_cpuid_config(tdx_cap, e->function, e->index); + + if (!config) { + int left = 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 &= config->eax; + e->ebx &= config->ebx; + e->ecx &= config->ecx; + e->edx &= 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 = kvm_get_supported_cpuid(); + + cpuid = allocate_kvm_cpuid2(KVM_MAX_CPUID_ENTRIES); + memcpy(cpuid, tmp, kvm_cpuid2_size(tmp->nent)); + tdx_mask_cpuid_features(cpuid); + + init_vm = 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 = 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 = 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 = KVM_TDX_MEASURE_MEMORY_REGION; + struct kvm_tdx_init_mem_region mem_region = { + .source_addr = (uint64_t)source_pages, + .gpa = gpa, + .nr_pages = size / PAGE_SIZE, + }; + struct kvm_vcpu *vcpu; + + vcpu = list_first_entry_or_null(&vm->vcpus, struct kvm_vcpu, list); + + TEST_ASSERT((mem_region.nr_pages > 0) && + ((mem_region.nr_pages * PAGE_SIZE) == size), + "Cannot add partial pages to the guest memory.\n"); + TEST_ASSERT(((uint64_t)source_pages & (PAGE_SIZE - 1)) == 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 = kvm_check_cap(KVM_CAP_X2APIC_API); + TEST_ASSERT(rc, "TDX: KVM_CAP_X2APIC_API is not supported!"); + rc = 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 |= X86_CR4_MCE; + + /* Set this because UEFI also sets this up, to handle XMM exceptions */ + sregs->cr4 |= X86_CR4_OSXMMEXCPT; + + /* TDX spec 11.6.2: CR4 bit VMXE and SMXE are fixed to 0 */ + sregs->cr4 &= ~(X86_CR4_VMXE | X86_CR4_SMXE); +} + +static void load_td_boot_code(struct kvm_vm *vm) +{ + void *boot_code_hva = addr_gpa2hva(vm, FOUR_GIGABYTES_GPA - TD_BOOT_CODE_SIZE); + + TEST_ASSERT(td_boot_code_end - reset_vector == 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 = ¶ms->per_vcpu[vcpu->id]; + + TEST_ASSERT(vcpu->initial_stack_addr != 0, + "initial stack address should not be 0"); + TEST_ASSERT(vcpu->initial_stack_addr <= 0xffffffff, + "initial stack address must fit in 32 bits"); + TEST_ASSERT((uint64_t)guest_code <= 0xffffffff, + "guest_code must fit in 32 bits"); + TEST_ASSERT(sregs->cs.selector != 0, "cs.selector should not be 0"); + + vcpu_params->esp_gva = (uint32_t)(uint64_t)vcpu->initial_stack_addr; + vcpu_params->ljmp_target.eip_gva = (uint32_t)(uint64_t)guest_code; + vcpu_params->ljmp_target.code64_sel = sregs->cs.selector; +} + +static void load_td_common_parameters(struct td_boot_parameters *params, + struct kvm_sregs *sregs) +{ + /* Set parameters! */ + params->cr0 = sregs->cr0; + params->cr3 = sregs->cr3; + params->cr4 = sregs->cr4; + params->gdtr.limit = sregs->gdt.limit; + params->gdtr.base = sregs->gdt.base; + params->idtr.limit = sregs->idt.limit; + params->idtr.base = sregs->idt.base; + + TEST_ASSERT(params->cr0 != 0, "cr0 should not be 0"); + TEST_ASSERT(params->cr3 != 0, "cr3 should not be 0"); + TEST_ASSERT(params->cr4 != 0, "cr4 should not be 0"); + TEST_ASSERT(params->gdtr.base != 0, "gdt base address should not be 0"); + TEST_ASSERT(params->idtr.base != 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 when + * 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 *guest_code) +{ + struct kvm_vcpu *vcpu; + + vm->arch.has_protected_regs = true; + vcpu = 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 = region->protected_phy_pages; + const vm_paddr_t gpa_base = region->region.guest_phys_addr; + const uint64_t hva_base = region->region.userspace_addr; + const sparsebit_idx_t lowest_page_in_region = gpa_base >> vm->page_shift; + + 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 = (j - i + 1) * vm->page_size; + const uint64_t offset = + (i - lowest_page_in_region) * vm->page_size; + const uint64_t hva = hva_base + offset; + const uint64_t gpa = 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 = 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 = { + .mode = VM_MODE_DEFAULT, + .type = 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 = round_up(TD_BOOT_CODE_SIZE, PAGE_SIZE); + vm_paddr_t boot_code_base_gpa = FOUR_GIGABYTES_GPA - boot_code_allocation; + size_t npages = 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] = 1; + addr = 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 = kvm_check_cap(KVM_CAP_MAX_VCPUS); + size_t total_per_vcpu_parameters_size = + 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_backing_src_type src_type) +{ + size_t boot_params_size = td_boot_parameters_size(); + int npages = DIV_ROUND_UP(boot_params_size, PAGE_SIZE); + size_t total_size = 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] = 2; + addr = 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_type, + uint64_t attributes) +{ + uint64_t nr_pages_required; + + tdx_enable_capabilities(vm); + + tdx_td_init(vm, attributes); + + nr_pages_required = 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 = 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); +} From patchwork Fri Jun 13 19:13:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897197 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 BF9C2275B03 for ; Fri, 13 Jun 2025 19:14:23 +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=1749842065; cv=none; b=FCFbaBwDfvjuBk62V8ryMI7fp/rIuRjR6Qc6+VMLc/OpNZ9khOq1qGbPAUynQ1/J+kDjyAtMETH7X58J7J37RHF39FfBT18pnsOBCivID9vLkOrYmWgH/hu+H+cekERuvvD0ekzAiCGuRFUjfgow6nB2kmFOlqBjGwDzZe0Qmqs= 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.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="jb/G19Au" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b0e0c573531so1438822a12.3 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=ayoOt/mgQ6ep9J8h8JAzUxhsUkZTYZ8rwFJ/1F+OXpdsK7dpkI9NyUiK80riCNkRcF /AuRHpyB522+CqGUgK1VURaas8qKUSgAfa9bE5Yro873Vtwm1CGkMfE3bDSWEE2cLdxy WDrU53coTFNKpGRLqZJX6hwLVawFGgbm075Dhxb8dg0WanK1ZMv1dTSIVSzJvcK2Vz6E xgpewpJjZyFmU94wXwvTvYJkX1fQuqFLzTdwOadPrFSdQ6vnHxig6jWZsTiPJx8wCufw pxtFg+5sMJSZwNnKIbpaabigB1kBo9KvOwMPrFFoT+vFVfg9/wsxfD326OwK5gHy9Jbb Fe3g== X-Gm-Message-State: AOJu0Yw2452PTImmdLPRlGqnn6uXnXd+vGei2lI4I6drZCEw9Sr23KWr 7X+QHOZRgwJkEUjrX1jlByePfQTxKsSHsmtf6F2YG2mLBeZt0ROJP0zjuLGbRzlXu5aLc2Sl02q Jqv/CXGzBlNphbSh6my9G7BRb3sx8eb9/Jf00Y73S60yhk+2wIrV/tE1aY7ZRd2Nr4qENpNLd+u kM2QaBHhTIpfxg49/GID69V8CxWzuL7I/xsKvwlyspL9Y= 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-kselftest@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 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/testing/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_cpuid2 *cpuid_data) } } +static void tdx_check_attributes(struct kvm_vm *vm, uint64_t attributes) +{ + struct kvm_tdx_capabilities *tdx_cap; + + tdx_cap = 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 #define CPUID_EXT_VMX BIT(5) @@ -256,6 +271,8 @@ static void tdx_td_init(struct kvm_vm *vm, uint64_t attributes) memcpy(&init_vm->cpuid, cpuid, kvm_cpuid2_size(cpuid->nent)); free(cpuid); + tdx_check_attributes(vm, attributes); + init_vm->attributes = attributes; tdx_apply_cpuid_restrictions(&init_vm->cpuid); From patchwork Fri Jun 13 19:13:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896547 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D29C293C47 for ; Fri, 13 Jun 2025 19:14:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842067; cv=none; b=XDQjSXxKKEx6xG7mK4TZ4DftuktOs88pnMI2MW7UGGitcCoaRpvzl5V/ArZHom0g6qezZTomZZuzBJEeY54SYcIdqEflW/oIkauIMp4wDcj+YrirHpgkFZFaIyZOPxDEovUyfNNo0j3fUQWcSyZCe/6P5f9R93DQeXBKUfwhZRE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842067; c=relaxed/simple; bh=KcVmSP1z2F1a4ltip8O2m08swJFdtWWy+j4vG4u1hDQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Ic9qR34PWNSevsLeluwsxvCd8Z1hWV5DqBWShJ1aZyCVMzG60Da7f7yvCUI/Wdc4PsS9ZpB5+NCDrCsaKyfXC3IV40hOE6O82FFyv5Lm9hYMCZvKtq+Hp67JWNcfRkG28E9mBa//sSj+3/EWjpfKlpe8qCkYk+zeyjxmjKvzslw= 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.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="T9mgj1L/" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-234f1acc707so19994925ad.3 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=ZmVimVnDbapqWE9HzMCNQQcrjpi79LyK3FOgPV4p2wQwZTTKMtSnhYTMAiRotIgNFy NbGLvi9/E32LUUTUdW5sIeaklMJ6khCAnJc3Xx6QPYOn2Ly+6NkeyuMkxEO91BO0A6Yo Mi9/3nyPHnuTBlSJV6lp9ihI1aJNJhuhE29LWjfa7nrZIG70I1y8g9q/4vYaOw77u6T3 aCSy/NzpNYKbf/vszsf2Dz4PvwAVP3YbR0LbbbUrBZA6Nb5Cmasn3w+Lc8BToenxwh54 BGBW7ighfNvi1uMstq2kgVhhXPFwc9dQ+VQ7S40zdsRUjzvTwh9KEg11SIRQ+AACaU4a zw7g== X-Gm-Message-State: AOJu0Yxh25H1RHMGp5G1MrUIcJOg0hDjDwCPzt8Mp03MSkTjWOnnRdWy 3r5dIQlm/ItQ9MGljpgVRvdYUM7ks/gqA6uOoJr/weFFEZuTTWLLeF88M3cvf20m4Xt5eJabRb2 qGHgGldFTQ9E9l6uMnD6rU4TdBrcUqN5JEHeTxVHosbeFnd7zRvC/5K7DbixHlM60FqIA8hDNJY DmCuH8yoC6q7LkonmIZ8t6YfpkdwVQ50X2Gn4KjXXevaA= 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-kselftest@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 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/testing/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); } +/* + * 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; + if (region->region.guest_memfd != -1) + register_encrypted_memory_region(vm, region); + sparsebit_for_each_set_range(pages, i, j) { const uint64_t size_to_load = (j - i + 1) * vm->page_size; const uint64_t offset = (i - lowest_page_in_region) * vm->page_size; const uint64_t hva = hva_base + offset; const uint64_t gpa = gpa_base + offset; - void *source_addr; + void *source_addr = (void *)hva; /* * KVM_TDX_INIT_MEM_REGION ioctl cannot encrypt memory in place. * Make a copy if there's only one backing memory source. */ - source_addr = 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 == -1) { + source_addr = 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); + } tdx_init_mem_region(vm, source_addr, gpa, size_to_load); - munmap(source_addr, size_to_load); + if (region->region.guest_memfd == -1) + munmap(source_addr, size_to_load); } } From patchwork Fri Jun 13 19:13:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897196 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 DD50E275AFF 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-747d394f45fso2140326b3a.2 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=LHxb9zaX30tf9y0TP3u1PTKtbfCKmWzp4ZAApd9c/w41OXfrCVCsSsHpIB0QVkT5HA yAaIJyyfdv9IvyKM2EdDThpa4eTUGt2zyqiByFtACEPu5Mv+Lpils3rhEfNol0gjI/Y7 5B7nMpaxMrg20ok7cC1vBhQIHt2SZEtdrXHRakVt+Q8/5nEwaXlMJtja6vEMBXHCGyso jjlUs5bYkIcjPixXK6oBZq/sY2X01pBI2OG94n1n909vJrUf3uROYSzmNrpIiMCWYi7v KX4pEkwvhuw1ZFbC7CjutQEtapi8POd5iNcyhQKqFm5RvRRJZrhFkQmcSyyX8i2rKper Abxg== X-Gm-Message-State: AOJu0Yy86tviSqe8bczK5+cZcvTbINrJNQqj0a5ZdU+Ln/5IrDs6hZUX PobrJ9owD7SbBBdRBAG9YNzt/kXLOIvPSb/jlyA69sMRlKsmrqva+csR2jma4XlDcr64qiFMyKB Aj13sz/s66eBvIeSgAfdUK3QA7H7ShFU+0Qj0Yib0fLiuWDf36fanzgOHjsJv4DtsCALFhid/PR TEv25LGSBj64dHrKvx7P+mUFDeaGx9g+gd0/svN8cQCVs= 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-kselftest@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 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/selftests/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 += lib/x86/ucall.c LIBKVM_x86 += lib/x86/vmx.c LIBKVM_x86 += lib/x86/tdx/tdx_util.c LIBKVM_x86 += lib/x86/tdx/td_boot.S +LIBKVM_x86 += lib/x86/tdx/tdcall.S +LIBKVM_x86 += lib/x86/tdx/tdx.c +LIBKVM_x86 += lib/x86/tdx/test_util.c LIBKVM_arm64 += lib/arm64/gic.c LIBKVM_arm64 += lib/arm64/gic_v3.c @@ -148,6 +151,7 @@ TEST_GEN_PROGS_x86 += rseq_test TEST_GEN_PROGS_x86 += steal_time TEST_GEN_PROGS_x86 += system_counter_offset_test TEST_GEN_PROGS_x86 += pre_fault_memory_test +TEST_GEN_PROGS_x86 += x86/tdx_vm_test # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86 += x86/nx_huge_pages_test diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdcall.h b/tools/testing/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 ABI. + */ +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/testing/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/tools/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 process + * context and wait for it to finish or fail to prevent TEST_ASSERT to kill 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 in 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/testing/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 >= 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 = { + .r10 = TDX_HYPERCALL_STANDARD, + .r11 = TDG_VP_VMCALL_INSTRUCTION_IO, + .r12 = size, + .r13 = write, + .r14 = port, + }; + uint64_t ret; + + if (write) + args.r15 = *data; + + ret = __tdx_hypercall(&args, write ? 0 : TDX_HCALL_HAS_OUTPUT); + + if (!write) + *data = args.r11; + + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c b/tools/testing/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() == 0) { + func(); + exit(0); + } + ret = wait(&wstatus); + if (ret == -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 = 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 == KVM_EXIT_IO) && + (vcpu->run->io.port == TDX_TEST_SUCCESS_PORT) && + (vcpu->run->io.size == TDX_TEST_SUCCESS_SIZE) && + (vcpu->run->io.direction == 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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; +} From patchwork Fri Jun 13 19:13:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896546 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 C1CA02BF058 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-31220ecc586so2370007a91.2 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=U1JJGYqI1SQ0dKD+vua+ijlrQJGHrkrUfP6ItUlOYk9mxOWF5hegzQOCOmBznnF+OR k36nC0tpBB3t1JM6sVPvMk1x8bDbXgQ5n7jeTQqLcM3QaIp6+PVKB6zfUhDjk28wSmMV qjb7z9HYwzC1vl9SpK7oudr2vU+6KeV2Pp5O5hNJoMgV3AhctoPs+aVnw2LpprajD55B hX1yINd6YN2krk3yxJrBj/TA7p8KkFR59mX+0aqe6ytwuFjXdovtJVuCQNw8ZWNMqh2O ax1d4whvqZwF5W+SINWCY7OROcbwMpnmFioDg0vhDSR+esSowT/jDc7XzqYikAsvLtiv R2CQ== X-Gm-Message-State: AOJu0Ywu8Pdm4naHCBLOwIP/1Vzlsv1fOS3W0mGmr3t1aKF9s9tHP4pD /UJY0G5/acTn5oiy3PxB6DHE8AUMJ+RPkYgrddvDEW2JUds5GhVgl+g786OWnyBGS6WqDhyhvxD Vk0LPc64HnMoP+PeCjZCkck5dfCzW4F7t1WZf/D+QUA/qWih6Ww9EXD63Ed2wj7kylFoTeQwXrc rCMu/BLU5wHNTMTycWM2YyOjsS6eUQQ4LnHWZHO9Fzufg= 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-kselftest@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 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/testing/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 @@ #include +#include "kvm_util.h" + +#define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 + #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); - +void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_gpa); #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_type, uint64_t attributes); void td_finalize(struct kvm_vm *vm); +void td_vcpu_run(struct kvm_vcpu *vcpu); #endif // SELFTESTS_TDX_KVM_UTIL_H diff --git a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h b/tools/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); +/* + * 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 +#include + #include "tdx/tdcall.h" #include "tdx/tdx.h" @@ -25,3 +27,19 @@ uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, return ret; } + +void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_gpa) +{ + struct tdx_hypercall_args args; + + memset(&args, 0, sizeof(struct tdx_hypercall_args)); + + if (data_gpa) + error_code |= 0x8000000000000000; + + args.r11 = TDG_VP_VMCALL_REPORT_FATAL_ERROR; + args.r12 = error_code; + args.r13 = data_gpa; + + __tdx_hypercall(&args, 0); +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c index 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" uint64_t tdx_s_bit; @@ -603,3 +604,8 @@ void td_finalize(struct kvm_vm *vm) 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/testing/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 #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) printf("Verifying TD lifecycle:\n"); - 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 = 0x0BAAAAAD00000000; + tdx_test_fatal(err); + + tdx_test_success(); +} + +void verify_report_fatal_error(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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); 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897195 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 4CB012BF077 for ; Fri, 13 Jun 2025 19:14:30 +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=1749842072; cv=none; b=X3/P9ZcX+l2R2PggZcE40Y3aFTjLkUvkrwC1ji546ua0k1HPTl3tvhtR0YuRfKm41TWSzw+frvjH+5fdYmD5EI5HFqXmeCIdPNFelcc3RjVdJ5Q9jzdZZ03qVu5k7wZQowHjQ/HgF0orxJA4i17/aZ766LqtUQWDulAO8bdlJzg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842072; c=relaxed/simple; bh=uqIxOmX3BYXbbCv1CMHqHbbyU277l6eBkNwagdau+oY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=LM92Gi9nCyWyEiYEYEjL3W7Ft0htBJjnysrYAui++wUBXZvV01RCCSctaBqTA8FVjqfZ5ImI37mAvKjpmq1sbu4dkoyP2pA02YWiiKVV3lFFc0lVTTdBZ9uUBlES3077BtXw+cKy3zEfrhG2yYJp92+zY0YPCWAk+Ixu60ymuMQ= 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-7489ac848f3so422192b3a.1 for ; Fri, 13 Jun 2025 12:14:30 -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=t0uqqntIiiTKWMEBajtE9pwTZR647AOFX+zF50Asbn3EakdXESUHCsugPcy9r89OX5 iO8VauNzJutPJhsLOfZeYB3s20SP0A/9/HDiOJeMqrWGFKqwqVR1ESnYjHQG0JUc3a86 fC/18+C/emxl90npZTiN5cKLGdD5dDnvaKAPbkr6jHPJQauddWDkk5F0VxP+50RnFVoJ SpnLJIdmFDbfeXW3uxUy6FHq5k5UMsGPd+euX/9vXlrVtmMgH7TrBLgRBsJnGDXNny2V +TZKIbBkWMI7n6WtokcgSMm3de5+0sLb0WC/t/rqoep+wT7dYi/RYNoWhSQle+8w7if8 TIcA== X-Gm-Message-State: AOJu0YxV4FkHfoMB//yZ6CVVu2d+La51dCY/RgQTMCYXE3KBV1xDbUSc MmnG8HVzkNSrW0x6maNoGVZNvCcaMsq/tCVSEqLFpaZngmJJMYjKYWso6m0Aw3UOn1tp/3sEX9K Uyo1Yb7jKlRiZiA80jS3eKjUgaxfqrXwsYxMTe8jebwUT2EW6kLPcyi+TgpZVQT9ytZyqXXl/8d T5/4zS5+eTTvl9oC8XG14XQR7dWkOS2fF8zTLTCfAdm6c= 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-kselftest@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 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/tools/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 +/* + * 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, either + * 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); +/* + * Assert on @error and report the @error 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_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/testing/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 @@ #include "kvm_util.h" #include "tdx/tdx.h" +#include "tdx/tdx_util.h" #include "tdx/test_util.h" +void tdx_test_assert_io(struct kvm_vcpu *vcpu, uint16_t port, uint8_t size, + uint8_t direction) +{ + TEST_ASSERT(vcpu->run->exit_reason == 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 == KVM_EXIT_IO && + vcpu->run->io.port == port && + vcpu->run->io.size == size && + vcpu->run->io.direction == 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 == 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 #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) printf("Verifying TD lifecycle:\n"); - td_vcpu_run(vcpu); + tdx_run(vcpu); tdx_test_assert_success(vcpu); 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); - 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 = 0xAB; + ret = tdg_vp_vmcall_instruction_io(TDX_IOEXIT_TEST_PORT, 1, + PORT_WRITE, &data_out); + tdx_assert_error(ret); + + ret = tdg_vp_vmcall_instruction_io(TDX_IOEXIT_TEST_PORT, 1, + PORT_READ, &data_in); + tdx_assert_error(ret); + + if (data_in != 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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 = *(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) = 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); + 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896545 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 ADCC1242D9E 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=1749842074; cv=none; b=U9x36CVEuNqcg3JKSoRnCDKS2EtfZdJ+v2M8SooP4kb27r7KFq/2NPFVuB4AsYJATNh8g7Q4rmv5rzSoskIKXjLGUdDcAERTxMalCN9FzLQkwNY1t3aQeZuZJHooy53J23vcesNRcVDNoQbaiMka/LhTPwfEt6KnQimI79z7ufI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842074; c=relaxed/simple; bh=Avxsfm8/t8HpO7whsUccQLtn39Rse70swcdoxot3qwE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=IvEsfvPZHaT4C18iIFnqXyHPbTFzfLyPvew1sfCBdtJ7I3lcZznD9FXy88MidKqyGkf3IDybW4aQrd3pPsqEbQ7EAgfW9mWps9n6/jOYW50NSfpZmO/gWpNiO7km1YE45B5+GLaQEb6SbUNluOss2gWHLDViKuXCpWa72Pi+Bwc= 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-3138c50d2a0so3428914a91.2 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=O1fYap+u3sopz6aDWIalKoEnxjJhjVuqxMQCSytGX+X+CLCSSullZEuXkgbPH8l/oj GgQRnxv8b+SVqQ0+kkfVhgUVVbXwNrSsmKDWYbziCo86rB4QboUD9zrxcF1Eo2SJWA+i 2INFq57cf+CenHZPHedBELkBudzk3IA5vHP4L15rxUUJ88hyI6LZ55jJnkNXbv2sJdBy IgpCx52yX6G7QsNEDA7mZYDNyBb13XCo+c6oCrYTTt/LWpOsWMOy/2+UGz8HDn69Iru5 0bxEwhkjBdhDhGVIYwxZOGOjpJ3NzrSMDXvNqe7twL+CXeTKfADCGko7vIn66QHWdleU MuJg== X-Gm-Message-State: AOJu0Yya+XmjTx53r0QhY6GFDcgRfGUn59MXxfRsKpQ+Scw8/9y1mQgm CtygJ6aSGDzvmY3IsiofCDRdvg4b+gBil9Fh44SzVjNF2Y9dZm6z2ft4/Nyde4CiEMujKrx7pnB pOH+4nEXqV5VLeTeaagS6uKgL7jpZNPu/6oxUuFNjr2hLUbAJowg09gJc4sm2R6pEz6gQ2B4F87 D91bMIs0SwQzPIFsA7d46UTnNlVyge+Y/Tr64TjoP7uQU= 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-kselftest@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 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/tools/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 +#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, uint64_t data_gpa); */ void tdx_assert_error(uint64_t error); +/* + * 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/testing/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 = 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 = *(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 #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"); } +/* + * 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" + : "=b" (ebx), "=c" (ecx) + : "a" (0x1) + : "edx"); + + err = tdx_test_report_to_user_space(ebx); + tdx_assert_error(err); + + err = 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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 = tdx_test_read_report_from_guest(vcpu); + + /* Wait for guest to report either ecx value or error */ + tdx_run(vcpu); + ecx = 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 = vcpu_get_cpuid_entry(vcpu, 1); + TEST_ASSERT(cpuid_entry, "CPUID entry missing\n"); + + host_max_addressable_ids = (cpuid_entry->ebx >> 16) & 0xFF; + + guest_sse3_enabled = ecx & 0x1; // Native + guest_clflush_line_size = (ebx >> 8) & 0xFF; // Fixed + guest_max_addressable_ids = (ebx >> 16) & 0xFF; // As Configured + guest_fma_enabled = (ecx >> 12) & 0x1; // As Configured (if Native) + guest_initial_apic_id = (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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897194 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 474E82C08DE for ; Fri, 13 Jun 2025 19:14:33 +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=1749842075; cv=none; b=BQzg92jjoYqJIgnjvaZHgnQNTDX3PHhJeSmPN8vnFVDz/u1S0XkXdCJm8JVXIPtgXG6TmGU+W6vBFl2H3AyStP3tvQQDN8W5W4dW6HbpdFoRQ8UWbHpDCwsO8aL6G6XpEfjDchOinwVoJZ4Ik1Kt5mqnKrcqP/9XdpL+0Izppxc= 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=kJLkAW6V; 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="kJLkAW6V" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b3183193374so70405a12.1 for ; Fri, 13 Jun 2025 12:14:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1749842073; x=1750446873; 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=kJLkAW6VbFebg3k5pi8JdbgI29Q3rw02zJLjghNnVrk8Kn+YUGy5d5f35qmEWGUphl wR11VGblPPywuITUE0y7wkKqJgSN2cqtFrHKfVo2a7mV5+KyQaoIZjyGAJrrYDpAvr6H 3IX2BIgVFc3I3si7ZCtn6k0TkxOs+yr5tagyIjAUioA26pXmu4MYsY5ZUy+NP/11eSPl aW0PzvmExQjtz1EQL1X5E5GfsaSLJkuBZVgQR6vSYTNSp9Usa6Tw8IxHiNUeOiJMgBC1 eiUGMZG83eWziE3ZzFrGLcVpQWwA2q3bC9y5d7vrzH9h6mFIQ1g987Ct+AzQQfglzPKV tKsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842073; x=1750446873; 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=HGXQtKpfCJxr2tDfErwZLuVxqCreXLmGR10Qr5WN8a3t0vB4uM1qJ71ELG0tDbi1+G WzWFYQ8SLz1oaYXBWnGni7neFGuGA+49pE2n84SStAEEVRGiDeCh2QSTCk+GCgDVQwi2 A3zHp3hZnSJUH8Y01ZjqbORwuxEj5hm10LwNohvjAVP8p9TV+QskM52keeAHxJuu1xt1 iwWfRE6pUH5maDw2UAeSp/EGuZ7S+dQEo3oNkBO9mzctRsmlBy/09kYyKIYjp+5Gb594 Nf7bX2x97vLL2adMVuY8Hx4b/Jb8yExyqRif4yUXAy55PayLwoJN2PxzmWhlbTCpDlIj dsMQ== X-Gm-Message-State: AOJu0YyJ5zGrQTVttVIXHYLjN5HZTBRujDR22txeSl66adqrqFgiY0R5 UA5XaUJcknkGdCgR5HR7G10s8rz2dOSsuaoiQn6l7+jMmRhuS3fUOlzsulyKClDFQrjkoaJ/MD1 efclDtIl+qkdHDbOFwmTxsdv2haKgwXOVI5Xvt44iUPjFQeZOdSq0SDK2P3nREcPgbjDF6z41mK d/hHfn76PX6qiGbV0M2Yzx5oyCtQa9G+vhUy2YullD23M= 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-kselftest@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 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/testing/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 @@ #include "kvm_util.h" +#define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 #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_gpa); +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/tools/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 @@ #include +#include "kvm_util.h" #include "tdcall.h" #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); +/* + * 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) first. + */ +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_code, uint64_t data_gpa) __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 = { + .r11 = TDG_VP_VMCALL_GET_TD_VM_CALL_INFO, + .r12 = 0, + }; + uint64_t ret; + + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (r11) + *r11 = args.r11; + if (r12) + *r12 = args.r12; + if (r13) + *r13 = args.r13; + if (r14) + *r14 = args.r14; + + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c b/tools/testing/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 #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_vcpu *vcpu) return res; } + +uint64_t tdx_test_send_64bit(uint64_t port, uint64_t data) +{ + uint64_t data_hi = (data >> 32) & 0xFFFFFFFF; + uint64_t data_lo = data & 0xFFFFFFFF; + uint64_t err; + + err = 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 = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + vcpu_run(vcpu); + + tdx_test_assert_io(vcpu, port, 4, PORT_WRITE); + hi = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + res = hi; + res = (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"); } +/* + * Verifies TDG.VP.VMCALL hypercall functionality. + */ +void guest_code_get_td_vmcall_info(void) +{ + uint64_t r11, r12, r13, r14; + uint64_t err; + + err = tdg_vp_vmcall_get_td_vmcall_info(&r11, &r12, &r13, &r14); + tdx_assert_error(err); + + err = tdx_test_report_64bit_to_user_space(r11); + tdx_assert_error(err); + + err = tdx_test_report_64bit_to_user_space(r12); + tdx_assert_error(err); + + err = tdx_test_report_64bit_to_user_space(r13); + tdx_assert_error(err); + + err = 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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 = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r12 value */ + tdx_run(vcpu); + r12 = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r13 value */ + tdx_run(vcpu); + r13 = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r14 value */ + tdx_run(vcpu); + r14 = 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896544 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 726DF2BF054 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-b16b35ea570so2476276a12.0 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=WHrmxJc9GUq3Xye30xmBBjxBdkuntF6ZokIofdSDdp/f/72571/wpi6NKZaQLx7dZa ZbMfyLPkiwa65YSJ36N6CffgaKROzv+wR189ly+W9q4pQ6DrJTNF9nAoSjjgCIVqX6Ux gP8wihTcZJ7Qqo8vfqHxq2i46mfCRVFNDxjD/w2LwQ4JEtsmrxm1oi9Y+fFtXeBxxbCv gt4YjkJOyOUbFVlsk39oyeHEAgwbZyLiWp7Ub/mt7JTMZDQ1mV3BVd0Uk3pSc2IfXzVV N6siOaT2h0rmGe3FCmXA7wlJxpmwRkkgR+haUjV4uisb6+z0rO+7ZZi1ZmgeTQFXLmGC fPWQ== X-Gm-Message-State: AOJu0YzV7n3zngZtEe4YnokjwJMGMOP3muoFMnfP7L56XCXluzTfdsoQ u0rD0BX8N7t2mK14RrRj9xX7JqT3/Cq4qsSxacaAl9BqqorsRnUfYXTPJlzokVjU2BBZ6RGBk9k WXry3jeLIWBKM1lxyYVanPkA0RVkJrP4hVsU6I7OWHCvfIm4zuY9FsygVJzhV96GNPsexFHce9A 2zts/tbP1UyHz3Hj8CwczOONMBcHSuTIPcNy21tTve+xE= 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-kselftest@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 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/testing/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 +#define TDG_VP_VMCALL_SUCCESS 0x0000000000000000 +#define TDG_VP_VMCALL_INVALID_OPERAND 0x8000000000000000 + #define TDX_HCALL_HAS_OUTPUT BIT(0) #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"); } +#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 = 0xFFABCDEF; + uint64_t byte_2 = 0xABCD; + uint64_t byte_1 = 0xAB; + uint64_t ret; + + ret = tdg_vp_vmcall_instruction_io(TDX_IO_WRITES_TEST_PORT, 1, + PORT_WRITE, &byte_1); + tdx_assert_error(ret); + + ret = tdg_vp_vmcall_instruction_io(TDX_IO_WRITES_TEST_PORT, 2, + PORT_WRITE, &byte_2); + tdx_assert_error(ret); + + ret = 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 = 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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 = *(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 = *(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 = *(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_OPERAND); + + 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897193 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 52FDE2D5C79 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-30a59538b17so2364301a91.3 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=N213o5psn6fQRRZiU21TuaWo2YOBP++s2ACx746tuscK4EhehS0ACI8v9cSuTNUV4n m1fp1Nkv4ooE3IC8JrvA2sUver3n0VDEKrmUdRfV+jO7q1CaAbQnK65J82uHAp7swfUJ RTce/9PNLTUbuIhCEFBdTbqtvLz+YQkoQ90gYoFwxG8kAQ1SAmouoH0WV/XRETkG+/AN n0b8/PtqEELpm5FNXvpcaCYc5nJfcJ40kZ9/4R4oQ+dUM7FPiJEoSdV1xdk47lh4gD55 nWukTlyvDnDnGzq/lmns+eacb9RA0u2s67Xrkipy1t6x5OvjwHFGP2uihPfg8nGJsOKL 5SiA== X-Gm-Message-State: AOJu0Yw2zK3FuCVx8LKckfDsb2PJvw6zq7u6+qdYf+0OsMUV/9XRaXhX Cu239SwRmHBZBPdbOOhLSpyW29SESPw18YkDd9Ysm5tqnobfBiXR8dsaE5O6/3Qagnm1WEHXSt7 mJzMMPfKSJgG50yp9jKyxug07z+t3rskqlFZ4MgSODbdIiR2jz07YYXg2+6gtVPdwHbZ1POd6cf HQOMv2xc51ZpwcGTrYitGJbK4Etlf3dgX1k9ZFfJLTxns= 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-kselftest@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 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"); } +#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 = tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 1, + PORT_READ, &data); + tdx_assert_error(ret); + if (data != 0xAB) + tdx_test_fatal(1); + + ret = tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 2, + PORT_READ, &data); + tdx_assert_error(ret); + if (data != 0xABCD) + tdx_test_fatal(2); + + ret = tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 4, + PORT_READ, &data); + tdx_assert_error(ret); + if (data != 0xFFABCDEF) + tdx_test_fatal(4); + + /* Read an invalid number of bytes. */ + ret = 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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) = 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) = 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) = 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_OPERAND); + + 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896543 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 D51C72D9EC8 for ; Fri, 13 Jun 2025 19:14:37 +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=1749842079; cv=none; b=DMu/gQQVICmDdAzkft+InqjI2qU1XgK9blVlruDuTu1IhNXWhxQqVAP4SlvAdjTyGMd53QgpbdZcZOiKtyzn6o4ZSuSiJuqQKSoMtJ/995ep+mYVB+Vt5XdsygQ6hSMXALVwpMKUK7iBthiT7shk3iGHEeagulQo1SxhEAOfBgE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842079; c=relaxed/simple; bh=NfXzvWPqKpJCBwVoGpTmHOXPaJf8dCByhWwm855UcKE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=fGaVWKzO6vxqc09hoyJj1x9EwKx/jVDdxmSePtTgzT7VVLvTL3RSH9rP2Cb1qPGXVYNaJzBelPcQwUQ0aakUaWv3rRlqWfpY4P7ri2SbOnwuhvcea4JI/SKmaW1y5llGyph/xFu/Xp8YXhkL3Dn8PkOO9sAH/TldM64XR2dtY/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=Bfo+gP+F; 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="Bfo+gP+F" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b2eea1c2e97so1899323a12.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=t6HA4KKW/BlNrCF06ynPIemAagde4LkG5y/HXKhPj+2l6r2QAxnwiUQY8I50Yz0wfM WBNzFkIYZk/6aFg66h4o8hVal//bKRMzsJFAy8lDium8J7SMxO8xMk/jcO/dQ73vZUMb f7cRN/8wyQKi3lVJ4bI1a7frDfmF1Dan5UCKcwOZC41eV6cvu3zP2KVvifGheDDQ5IbJ dH+wxjDlPCP/E16GRyfAyb8kC2E8iQdhXELbFwURDopC/y2MnpAWuqY0MQFGDm9ywqRh HWXDg2W8m+wo9A/oeEQfLcZBG68WfJUAX5/ceLaJU0HYJ+4a2/oxtrI8C+WAhq/b/J9+ kqOg== X-Gm-Message-State: AOJu0Yx4qyFFnlGGjvU0r1M1y1f2GYav2YmvaZRDlUuPH0bOzb3TnRzn sbWasOKBh+yzCufydSjH1v+U6DX16LIX/TeJcElO7EEw1LIIJPwiytqb1ABz+LsjnyChOcKZbTi SWGjJxpCG1IsaKqDnto1vDh3OJPnjDTYvqOjMKmZbt4oKiWLQJ4mPeggTBIMZL9WfyLKhG8hz4Y uypp1JyTbXTSEfsMpNCiK0GldLN6s/Ly4+4+oB8j97yiE= 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-kselftest@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 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/testing/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 #define TDG_VP_VMCALL_INSTRUCTION_IO 30 +#define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31 +#define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32 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_gpa); 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_value); +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, return ret; } + +uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t *ret_value) +{ + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_INSTRUCTION_RDMSR, + .r12 = index, + }; + uint64_t ret; + + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (ret_value) + *ret_value = args.r11; + + return ret; +} + +uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value) +{ + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_INSTRUCTION_WRMSR, + .r12 = index, + .r13 = 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"); } +/* + * 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 = ~0ULL; +struct kvm_msr_filter tdx_msr_test_filter = { + .flags = KVM_MSR_FILTER_DEFAULT_DENY, + .ranges = { + { + .flags = KVM_MSR_FILTER_READ, + .nmsrs = 1, + .base = MSR_IA32_MISC_ENABLE, + .bitmap = (uint8_t *)&tdx_msr_test_allow_bits, + }, { + .flags = KVM_MSR_FILTER_WRITE, + .nmsrs = 1, + .base = MSR_IA32_POWER_CTL, + .bitmap = (uint8_t *)&tdx_msr_test_allow_bits, + }, + }, +}; + +/* + * Verifies MSR read functionality. + */ +void guest_msr_read(void) +{ + uint64_t data; + uint64_t ret; + + ret = tdg_vp_vmcall_instruction_rdmsr(MSR_X2APIC_APIC_ICR, &data); + tdx_assert_error(ret); + + ret = tdx_test_report_64bit_to_user_space(data); + tdx_assert_error(ret); + + ret = tdg_vp_vmcall_instruction_rdmsr(MSR_IA32_MISC_ENABLE, &data); + tdx_assert_error(ret); + + ret = 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 = tdg_vp_vmcall_instruction_rdmsr(MSR_IA32_POWER_CTL, &data); + if (ret) { + ret = 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 = 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 = kvm_check_cap(KVM_CAP_X86_MSR_FILTER); + TEST_ASSERT(ret, "KVM_CAP_X86_MSR_FILTER is unavailable"); + + ret = ioctl(vm->fd, KVM_X86_SET_MSR_FILTER, &tdx_msr_test_filter); + TEST_ASSERT(ret == 0, + "KVM_X86_SET_MSR_FILTER failed, ret: %i errno: %i (%s)", + ret, errno, strerror(errno)); + + vcpu = 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 = tdx_test_read_64bit_report_from_guest(vcpu); + TEST_ASSERT_EQ(data, 4); + + tdx_run(vcpu); + data = tdx_test_read_64bit_report_from_guest(vcpu); + TEST_ASSERT_EQ(data, 5); + + tdx_run(vcpu); + data = 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 = 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 = tdg_vp_vmcall_instruction_wrmsr(MSR_IA32_MISC_ENABLE, 5); + if (ret) { + ret = tdx_test_report_64bit_to_user_space(ret); + tdx_assert_error(ret); + } else { + tdx_test_fatal(-99); + } + + ret = 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 = 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 = kvm_check_cap(KVM_CAP_X86_MSR_FILTER); + TEST_ASSERT(ret, "KVM_CAP_X86_MSR_FILTER is unavailable"); + + ret = ioctl(vm->fd, KVM_X86_SET_MSR_FILTER, &tdx_msr_test_filter); + TEST_ASSERT(ret == 0, + "KVM_X86_SET_MSR_FILTER failed, ret: %i errno: %i (%s)", + ret, errno, strerror(errno)); + + vcpu = td_vcpu_add(vm, 0, guest_msr_write); + td_finalize(vm); + + ia32_misc_enable_val = 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 = 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897192 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 9B5B62D9EF7 for ; Fri, 13 Jun 2025 19:14:39 +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=1749842081; cv=none; b=uMtAAaBg3Um5309Z4PmO23mXOd9ziGl9oh+K8m1pL5mZ5Yo9EgXH4Ospp15MuJal2mk7LnmeqV9oskfoiD0Y5prgHgIjvPSX6mNyisY9J1X6kcAboLljZPLgbjfe23tA8WuQZQFm6L4cHJp/Jz8vXcK6HeDdMgfDLXpjhrt/Wfg= 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.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="IapJo8iI" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b2c00e965d0so1582816a12.2 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=nZ/C9pC5tgcJ14we2QNIN6AaqRFeCjqZdn2BYtBNRXcZVupPhF2u70llQ+IjaWx4A4 CDRvNWf843vMHnn3oc730lnLU9KwDwP9bB4eeT0jRPsKrn//t4fvnJ1hLL775AZGNyK4 gSy3bcT29juYp0I1xTC5DkROoLAPS9O5C3X4MtzkFdbHJxYOivkyxzMU1z5ortna7uSV VpHmH1Ed9+dBqqaHSBVASCxkk1MchRrvjLUHXweTUPJPHjv+nQLp4Ame9jG/4vj9UVsn wn36uWZXrgRa1lhMXMRU8iXll5BcaKw4XtEkyqUO9AAfnsqf0KhH3FbMFpnaRipa9UUZ NTPQ== X-Gm-Message-State: AOJu0YwuTLRdfCBKVt9wg64JSAT+LxdpJlFG7S4GUVbFZpbZXheO1Q7W mbYaPeSrvQitpkYEiNgKPpopinViMpFyui/pWOpsZHxnz7Oj4IeYEE56W67pK4DW/08niEkBtED cToxuKSe0BA+QO43lIFDGwCxHdTORAmf8CpkaT55nbVus8ovfe0vTDIv9mnnohapszbrutd/VV/ cDRkC0olwy1AwHq182AJaszt1RMQT/yWrOnBqGlBzOXg4= 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-kselftest@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 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/testing/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 +#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_value); 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) return __tdx_hypercall(&args, 0); } + +uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag) +{ + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_INSTRUCTION_HLT, + .r12 = 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"); } +/* + * Verifies HLT functionality. + */ +void guest_hlt(void) +{ + uint64_t interrupt_blocked_flag; + uint64_t ret; + + interrupt_blocked_flag = 0; + ret = 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 = _verify_guest_hlt; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + + TEST_ASSERT(sigaction(SIGALRM, &action, NULL) == 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 = KVM_MP_STATE_RUNNABLE; + vcpu_mp_state_set(vcpu, &mp_state); + return; + } + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896542 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 D244B2472B0 for ; Fri, 13 Jun 2025 19:14:40 +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=1749842082; cv=none; b=bPNHPjhWsELLS+Su7GP7B3f7EsHNyEoF5RSEpGupNrN1+dq2pB35/B7xufvMno0cLYycgyVTFm7A7IZBSz2oEFaKfLDxvEHsnoX2NA+1pGfGUk9qdKAXw7tKeTf3xgNXh2++X1PbjyAV9mksUQI3fSMrqi29liaoc6jMv0Fj8ng= 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.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="OlY69zyA" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b2c38df7ed2so1784906a12.3 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=wB3MJxNvsyB9BK3odovucHFpZOAbA/VdrKuDA7RbpgyCkDC0L6fjLsT2MVj+nTL9e6 TD7LZa2CfyrR8+c/wVl/h2T+IV9Gf5TWd5IV9T5UqxMF0Dap1WX9H8HUOFjPduGpJMQF PBwwCfhGe9kSYS/K/y5YO/7iuWn7vkLxatkYz8e5G1wyDY/0dm6dh5blnuNB9YqHuMjB 2qyNDgDHDXTvOzo/bHuP2SF9EPNIlAFI/RyYAt/QBfUiC+wTHwHxIvbB92+Dq6+NS5rT H6WqHc77h3yvDfHHMe5C2zON1t1Mde3Aoip4pqOzz4lLOFtQa6389JlxO6z65E1sGiDS I0Tg== X-Gm-Message-State: AOJu0Yyz4Ny2bY0bOs17h0QgV/jy94kzwcg242JawXyl91A/eFNlLhpT lS3AFqz0YcFWH5yw5Ij70+rGE5cBUwURz8iIT4CIFS12oedX1skQxKkab8QBMUdtkxSnpLBJio5 pU2309PUil6DMRInaCs++Mz6a6Afajm7V+AAHH8tTHyxL/B2d9aY+5XhIWGe2lT0uuElxNUREld V5i3qTZjFz+cYyzuB6cNcrr6dam6+riuAdy+h4mOtgwdg= 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-kselftest@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 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/testing/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 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_value); 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 size, + 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 @@ #include "kvm_util.h" +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); diff --git a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h b/tools/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 +/* 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); +/* + * 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, either * 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 @@ #include "tdx/tdcall.h" #include "tdx/tdx.h" +#include "tdx/test_util.h" 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 interrupt_blocked_flag) return __tdx_hypercall(&args, 0); } + +uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t size, + uint64_t *data_out) +{ + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_VE_REQUEST_MMIO, + .r12 = size, + .r13 = MMIO_READ, + .r14 = address, + }; + uint64_t ret; + + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (data_out) + *data_out = args.r11; + + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c b/tools/testing/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); } +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 == 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 == KVM_EXIT_MMIO && + vcpu->run->mmio.phys_addr == phys_addr && + vcpu->run->mmio.len == size && + vcpu->run->mmio.is_write == 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); } +/* 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 = TDX_MMIO_TEST_ADDR | tdx_s_bit; + uint64_t data; + uint64_t ret; + + ret = tdg_vp_vmcall_ve_request_mmio_read(mmio_test_addr, 1, &data); + tdx_assert_error(ret); + if (data != 0x12) + tdx_test_fatal(1); + + ret = tdg_vp_vmcall_ve_request_mmio_read(mmio_test_addr, 2, &data); + tdx_assert_error(ret); + if (data != 0x1234) + tdx_test_fatal(2); + + ret = tdg_vp_vmcall_ve_request_mmio_read(mmio_test_addr, 4, &data); + tdx_assert_error(ret); + if (data != 0x12345678) + tdx_test_fatal(4); + + ret = tdg_vp_vmcall_ve_request_mmio_read(mmio_test_addr, 8, &data); + tdx_assert_error(ret); + if (data != 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 = 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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 = 0x12; + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 2, MMIO_READ); + *(uint16_t *)vcpu->run->mmio.data = 0x1234; + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 4, MMIO_READ); + *(uint32_t *)vcpu->run->mmio.data = 0x12345678; + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 8, MMIO_READ); + *(uint64_t *)vcpu->run->mmio.data = 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_OPERAND); + + 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897191 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 AAA67247DF9 for ; Fri, 13 Jun 2025 19:14:42 +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=1749842084; cv=none; b=ZouglpDFi0JmVhn6pzMgtH2CXWaPFtVsAmMKVZamTN4B1+GzRRt8nv2/eQfJ7rYGHWHg3KEaGJKRRALNH7i+kCLhxHvVyMzJhzhaxjfPkB5qOteQaHugB0N7WdyZLRArGSF+UYCUxChA86RUU4a+ugIEfmALf4LrY4LphlGZYpc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842084; c=relaxed/simple; bh=gB7leVldU3Q+/K2dvULRGODaLqYXhPw7nhUc71aLv2Y=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=RESBchPahkV8jqh0BLQ/EEh1B9T3Kp92+D2M7anIj9z0w7JWV/RUK19k8dCh1UkhvL7gVjmlKsBpkSMJuGHpDoMEVaoEZWnREl3edAJumTnkHPs6blL+I2MKStRIsRDrUu2PctEBYfiBDTyvGQM4AVUk+PC/JrS628htUYrfq7U= 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=RUIUECsU; 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="RUIUECsU" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-311f4f2e6baso2330949a91.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=1749842082; x=1750446882; 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=RUIUECsUkDzwt1KwDHpgZflwJwJyMXEEAuPOORenD11INmelQOySk5/MWVurRPYICL PovOKopH9LERkfsK0acF7tbiUMIYSgiiNTeDPAW/fXnw16DctjAuoYBz6GOYQKde2i4q uyrKvsPb6H/z2yXididisDZhCV+gFFmKRSk9cDo95YLxnshRImWiWOoCj4rJjYCN6voM z9jBS1qAUem2evZraZlhrNThwx6hLTlR/YeFK4SC8cSjr9tgdeJuJ13WGmNDlle8lFDA 3alhS9RiKCq3DgyIHaIZB+XUHU4xfb2x8YIfufRrtSZ+UxmL0NaHSLD5xoE/w8ZS5nFi WdiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749842082; x=1750446882; 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=B5AiCuYn80TXeIRGG7DJ6MCzEbvYztmNZBPkgQzj3HXQPEOWK2MaJ0pdWXPMGYiK3q P9+AVUb9Zm6/6+4MTGltt/nD9n8fJiSasH9sAPv1/kiCaZjzOhhGMLrUSLbPWR+uoYu6 8ki3zLG7uQAI9UhTTp7/Eu4UYPgMiITgGwtmDD5jcpPDkXY2N8NwxYDgn+xo8o84vBgL 6M6uYEJEH+egbLIVfPL8188fIZ8PW1X8Sf/Za0tmO2KnOdyTWMmit3V+pCxGIBpA5P7N BlFcMDD7csUsUtnN1Z6HLtRkYhOoi/LlCItxb2TUpTP2ihsqeJy5gLPUhgJ2d4WR0L60 IzAg== X-Gm-Message-State: AOJu0Yz0Zalsc0YCSuTrt9BBdzH3jOrgYVAzCM5jEKycWH/y+tGtPLQo 4lrw5lwVNqXiUr3YXhMiic/quW3UfNGed9Y7wewUKMIe1y7W5ABK+U8IpEOqd9MJfnVaHtkFDu9 rWeemw6YyQRINZn9RsYLtjwTtHdhrhCkxV0s4eTPjitNB+/1+8pFo2tG14K+sB+u3URKmVa2D28 Sib0QsbRn7TDfGrORPqQ+MboWGKquuytG11iqWlwvnGKY= 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-kselftest@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 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/testing/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 size, uint64_t *data_out); +uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t size, + uint64_t data_in); #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 address, uint64_t size, return ret; } + +uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t size, + uint64_t data_in) +{ + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_VE_REQUEST_MMIO, + .r12 = size, + .r13 = MMIO_WRITE, + .r14 = address, + .r15 = 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"); } +void guest_mmio_writes(void) +{ + uint64_t mmio_test_addr = TDX_MMIO_TEST_ADDR | tdx_s_bit; + uint64_t ret; + + ret = tdg_vp_vmcall_ve_request_mmio_write(mmio_test_addr, 1, 0x12); + tdx_assert_error(ret); + + ret = tdg_vp_vmcall_ve_request_mmio_write(mmio_test_addr, 2, 0x1234); + tdx_assert_error(ret); + + ret = tdg_vp_vmcall_ve_request_mmio_write(mmio_test_addr, 4, 0x12345678); + tdx_assert_error(ret); + + ret = tdg_vp_vmcall_ve_request_mmio_write(mmio_test_addr, 8, 0x1234567890ABCDEF); + 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 = 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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 = *(uint8_t *)(vcpu->run->mmio.data); + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 2, MMIO_WRITE); + byte_2 = *(uint16_t *)(vcpu->run->mmio.data); + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 4, MMIO_WRITE); + byte_4 = *(uint32_t *)(vcpu->run->mmio.data); + + tdx_run(vcpu); + tdx_test_assert_mmio(vcpu, TDX_MMIO_TEST_ADDR, 8, MMIO_WRITE); + byte_8 = *(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_OPERAND); + + 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896541 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 BCD832E613C for ; Fri, 13 Jun 2025 19:14:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842085; cv=none; b=OhcTOxsGHzDc6TwUJGiTYPux0qs3T2vvBxLgZOoeb5P6HjnXkmKGuxaMPymE7UEM/fz4KijsSHLQ+rHGPalOeFWDjP+nf7SXQl806fa9a91+UKVN4Ukr7BqSWEJlztE5FG0DEcam4akxX3i/kvZuQN6Vm6yLrYyMLJJfS60Oc7A= 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.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="xI02baTt" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-311e98ee3fcso3002151a91.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=WEHZFaAuH0MLW4c1prG9xMdWgkHcVFDf4KN+JbYN9ls5OrLCHbLTMBrcCjwaGNqcj8 7Fgf8+/FDATRRaSGBo8Idb4/q5j+N/ebzcAVykp+DhzqyOUx0TEicZvweBWivKSKd4Oa GoCzhXNuRWpycRIVfM+2J+DeRwEa0xnG6riFYEtqWAgVomHWJPm7jTYl5VygVPAXIvwN zH6KY6LJVT7t31lEqf2qq7rTD9T1Zu9dRZjAZZCT2pu9chY1BLGT6+1Z3sYbgd8ecaQB /vXhUkh2nPKElrxzJVtwAUlUwDDpNcgNBm/tmRx4rBmg5ZP/v0mTj6+X+U0fYrKmqvXg 2lgg== X-Gm-Message-State: AOJu0YwZXaAJuIwg/RA2+2mE9mx0xARPStXv5vAedipdLS/e9b6IUGn1 nz4wVCK2C0j6WgYvJmS5iweDnVilWMyqKJzboG80k+OTrotPZmDymrB0kt1zXLqzcdQDeQYUoI2 sEbhlaf3VTSQAy2no1dE4r6LEw+LXfykGuL4eyzYAoNrlXk5IZW8NsRIxknhBoHppjxA5iBWeNT qXeFDXa/myIIE6F4oWU1ybvHMeyHHc4W5bhMvHhub7By8= 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-kselftest@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 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/testing/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 +#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 address, uint64_t size, uint64_t *data_out); uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t size, 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); #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, 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 = { + .r11 = TDG_VP_VMCALL_INSTRUCTION_CPUID, + .r12 = eax, + .r13 = ecx, + }; + uint64_t ret; + + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (ret_eax) + *ret_eax = args.r12; + if (ret_ebx) + *ret_ebx = args.r13; + if (ret_ecx) + *ret_ecx = args.r14; + if (ret_edx) + *ret_edx = 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"); } +/* + * 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 = tdg_vp_vmcall_instruction_cpuid(/*eax=*/1, /*ecx=*/0, + &eax, &ebx, &ecx, &edx); + tdx_assert_error(err); + + err = tdx_test_report_to_user_space(eax); + tdx_assert_error(err); + + err = tdx_test_report_to_user_space(ebx); + tdx_assert_error(err); + + err = tdx_test_report_to_user_space(ecx); + tdx_assert_error(err); + + err = 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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 = tdx_test_read_report_from_guest(vcpu); + + tdx_run(vcpu); + ebx = tdx_test_read_report_from_guest(vcpu); + + tdx_run(vcpu); + ecx = tdx_test_read_report_from_guest(vcpu); + + tdx_run(vcpu); + edx = tdx_test_read_report_from_guest(vcpu); + + tdx_run(vcpu); + tdx_test_assert_success(vcpu); + + /* Get KVM CPUIDs for reference */ + cpuid_entry = 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897190 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36CE42E6D14 for ; Fri, 13 Jun 2025 19:14:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842087; cv=none; b=u+Yb3mgxkzKB1VVlbrDmXpI9XEbZynXch3PJZ6KRrHePjaUCTv1Zylc9nNSdNNLlDI1/tQB+uYbb/748+bD1Yhuw/wusOMJIyr/NQ5tse7JxDWMNGtPW75FgWn1yYSROLZ+ygDUjL8uw6SiUJjzFaFGK9curBypY+ZyUutw2zMY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842087; 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=hVI6Aw2DC1uJvzAwt3HGAI8XzixndLKJtqFEGvxHbityqI/C/qya4GUvH7ZAEoDdPIhajpakh890RP6k/3+ARezNhn+FJdakOYUf/99lFh1/tjdpw6tMBMsMBOGcWwj05tBegfSGEYyaAqG8Vq9r6xs4h2KBNOg8mvF5NseftOE= 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.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="clpE+JMA" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-234b133b428so17248475ad.3 for ; Fri, 13 Jun 2025 12:14:45 -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=YvwdDEUN6xe5k78OkuCujaLaCmIIk2XfRhNNXqjj9OBop9jFyz+7vwAO4pZWcLB8YY wnP9qc+FJYMwYxlhiIaVZu2IXI/194ijybmbFN/M3Rcmp+K+o7Xye6kVY8wEAKpcaOMR mjVPn/pLgVXweQ/sbnVHcVpIdhBIxim4ldMQPFUuW37BkwxGxIl/1h0aH2r2+b8xec7p zFrSsfTBTdCWqfvEEJOXTikBgwKmz9IwoqbwSbLf9hcHxki10XNvvmjyi1Sci7lfhfMs FmzsA+ThPn7ZYAcRqIvxBQg0UZtaNE3hYhQkIxkstZV9ZQPOVqhGyTXPPqM/hT3aAQup g8Rw== X-Gm-Message-State: AOJu0YyssTrJn4ZofTG30cA196zVNh93Yu9gxtZdv/MbhLssE6Nxe2B1 2OzyI56mwUpnEb7Oes35FXmAlq4nyewN+pEKAuRQwBS8MpLIgkoM0gn5ujIyisXgWQTTtHJY/tp 3yGFbh1MGvm5rNP0IWvcLs2XtgpkyaNhzGky4uLH3Nqaz5EhWcWqvf2XxenKHc9AXY7DmosSliS lq0SQmPdrZUBK+4XVx4q8e0/uWf8XNnE8lI+K7SfLdqx8= 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-kselftest@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 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"); } +/* + * Shared variables between guest and host for host reading private mem test + */ +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 = 0; + uint64_t ret; + + /* Set value */ + *((uint32_t *)tdx_test_host_read_private_mem_addr) = 0xABCD; + + /* Exit so host can read value */ + ret = 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) = 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_host_read_priv_mem); + + test_page = 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 = 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 = 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 = *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 = *host_virt; + printf("\t ... Host's second read attempt value: %lu\n", + second_host_read); + + TEST_ASSERT(first_host_read == 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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896540 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 421CC2E6D39 for ; Fri, 13 Jun 2025 19:14:46 +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=1749842088; cv=none; b=pf8iqKQ7MetPn7pMAE/tCrJ0kEszI4gTRyV/Wchase/6xvdl/VkG1cw4n+CPFFAsG7sClZyezqioNR5qOc4vGjGdMbKoxW8usCTqqrU6lke9EukcSyaBGcMntGzg7KwTy1E6tTFLcSrQ6tmCsi9NST+ELhJ90/6drED8wNvydks= 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.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="nwVtcbfY" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-7489d1f5e9fso146980b3a.0 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=dLk3SmQpe021d5DgG1vINGV0nvYinBASIbSmu6JB7EgEndUtA0LT2rw1sdVa3Z4MHW 0GkmgHjq0wl6ksJByNVKfNLtN1nXbfSAs9CE4XiK/fNGkJ3LMBprES2TK0703+3i2Qq8 IUpdceFIhw137BDV/imnkJB4rRnsralV2Y5zlMs2umjoODIWxooR+UfpHn15A/DgcXtm TzvYzWsNgzcdBoKvPfTmxK1JcjZ+U9IwnwaPcVd339Ddw3QWDK+LN+G8Er7IXbMLJ37U TQjg5yKxUVTFYYCIJhaNUULvX+K50B42Gw0oDPfzCoG6vzhJMAjNL5trSI7pIt9NUb3M hqoA== X-Gm-Message-State: AOJu0YzqJWh46jjPl5dRXLApb4TBNV76xrXsHp1f2byOkwfjQbcmpzgM EOxq/eIMcVMr92ti7PN6Vib/d5Om26sPjm9WURwkOq4VhM1P5MNMT59RKXuFUX3eyH+tv0H2xUD nn46A2mQ4nwxT7x6rQMZRwZ73nIc6Cd83RUxkXFWjz5og6PL6jbnRYl3Lv3oQwYZKrNRedsiHwa YheQXySuosESmJuphQZAXL1NpmY5Bvlk0jmhoaUiGMO6o= 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-kselftest@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 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/testing/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); +/* + * 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 ABI. + */ +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/testing/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 @@ #include "kvm_util.h" +#define TDG_VP_INFO 1 + #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 @@ -31,5 +33,8 @@ uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, 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); #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdcall.S b/tools/testing/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 +#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 != 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, 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 = __tdx_module_call(TDG_VP_INFO, 0, 0, 0, 0, &out); + + if (rcx) + *rcx = out.rcx; + if (rdx) + *rdx = out.rdx; + if (r8) + *r8 = out.r8; + if (r9) + *r9 = out.r9; + if (r10) + *r10 = out.r10; + if (r11) + *r11 = 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"); } +/* + * 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 = tdg_vp_info(&rcx, &rdx, &r8, &r9, &r10, &r11); + tdx_assert_error(err); + + /* return values to user space host */ + err = tdx_test_report_64bit_to_user_space(rcx); + tdx_assert_error(err); + + err = tdx_test_report_64bit_to_user_space(rdx); + tdx_assert_error(err); + + err = tdx_test_report_64bit_to_user_space(r8); + tdx_assert_error(err); + + err = tdx_test_report_64bit_to_user_space(r9); + tdx_assert_error(err); + + err = tdx_test_report_64bit_to_user_space(r10); + tdx_assert_error(err); + + err = 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 = 2; + struct kvm_vcpu *vcpus[num_vcpus]; + uint64_t attributes; + struct kvm_vm *vm; + int gpa_bits = -1; + uint32_t i; + + vm = td_create(); + +#define TDX_TDPARAM_ATTR_SEPT_VE_DISABLE_BIT BIT(28) + /* Setting attributes parameter used by TDH.MNG.INIT to 0x10000000 */ + attributes = TDX_TDPARAM_ATTR_SEPT_VE_DISABLE_BIT; + + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, attributes); + + for (i = 0; i < num_vcpus; i++) + vcpus[i] = 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 = 0; i < num_vcpus; i++) { + struct kvm_vcpu *vcpu = vcpus[i]; + + cpuid_entry = vcpu_get_cpuid_entry(vcpu, 0x80000008); + TEST_ASSERT(cpuid_entry, "CPUID entry missing\n"); + gpa_bits = (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 = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report rdx value */ + tdx_run(vcpu); + rdx = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r8 value */ + tdx_run(vcpu); + r8 = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r9 value */ + tdx_run(vcpu); + r9 = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r10 value */ + tdx_run(vcpu); + r10 = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r11 value */ + tdx_run(vcpu); + r11 = tdx_test_read_64bit_report_from_guest(vcpu); + + ret_num_vcpus = r8 & 0xFFFFFFFF; + ret_max_vcpus = (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 = 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=%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"); - 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"); ksft_finished(); return 0; From patchwork Fri Jun 13 19:13:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897189 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 9FBD72E764D 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-31315427249so2484693a91.1 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=P0HJ+dmJdca9DVPSvGrgXPi9eCqiX3T7YnOUt+VbGn4MQaiskSGC2aZUxTuI1x4T2U iG93002ElHCAtVTKpbagh/ZfjCjTQ7AHIRpcl3Qvzc0x3/fC4zti33UuQxBYpY8+q4fe nsujd/ccQZQY2BiBWVipe7eeo1CUQbDtog0BB0mBiIDKaYOrCAbUOFfYK8VMN9bvjWPY hal9kDO5UCZguSf1CAeGMo0w2F+gzlSEPwOlytXQeAH9z4M8pLN44rPT5CLoK0Z9QBfw RabnnwId7/nDa+9VZBlEuvyaga6jCFUfJVEgUnXh4/SrOmQOOmRNib0+M370TsJ0hjwm BpdA== X-Gm-Message-State: AOJu0Yy3u3j+AV+TvlPuqNrb/7sNWpkYURwIWw+hRKn7jLvyMsCTxqub 6JJD5O1BrANU5FBbI8zzEqTvhVeIPgZ2mVbedZI4mnJSxSQntdC1jIER62EH6sG9NqfexecdntG 5eorrqzlZTNfKwb2WWQ/E0B4PQLcMdyDz+aFUwtxUFoMslFT131544HTeiRRkpzuAIoZqt9JdkN mvPvqciMehcOhunaNsX5ScxWfQsxSbOMPVo70tOruNrIE= 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-kselftest@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 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); 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, uint64_t vaddr, uint64_t paddr virt_arch_pg_map(vm, vaddr, paddr); } +/* + * 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 paddr); + +static inline void virt_pg_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr) +{ + virt_arch_pg_map_shared(vm, vaddr, paddr); +} /* * Address Guest Virtual to Guest Physical diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/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" #include @@ -1621,6 +1622,39 @@ void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, } } +/* + * 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 = vm->page_size; + size_t size = 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 += page_size; + paddr += page_size; + } +} + /* * Address VM Physical to Host Virtual * diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testing/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 *vm, return pte; } -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 paddr, + int level, bool protected) { const uint64_t pg_size = 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 |= vm->arch.c_bit; else *pte |= vm->arch.s_bit; } +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); } +void virt_arch_pg_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr) +{ + ___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) { From patchwork Fri Jun 13 19:13:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896539 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 5D8032E7F26 for ; Fri, 13 Jun 2025 19:14:49 +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=1749842091; cv=none; b=ortDMOMQZzjNiEUVD4STQA3PTjw44h3lQ0nmxwqxVHihOWWPgjGIPw4TDphNv9S2iJCYuwDKSI7LPtGxe9FBH2o/sEdIrEWNJM1hrq9xdovepgrXYd+GtV/uXgF6cMYFcyYECUnC/SANTBApHUradC6dKqrwrg780lEjZXH+gaE= 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.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="axNg0GXO" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-7394772635dso1855954b3a.0 for ; Fri, 13 Jun 2025 12:14:49 -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=Hrdjp3Ag5V/PwUcbth1dwH5ly0H1wXeqIK42rguodn/b0ZoKsm028uir/NAwN0bZKM lZkFioKPchQCodE0IZcL5aVTLwrbvY3t5rEt4HCoVkDo2/99eRndsJDgEZurrWmW0/g3 Xh1UBzWgp7ojNkYy5fyJGvK7F1uPMYosAIxdCA3NX0mf1uc6Iglq+tYAHhKbFdeHNrGD 8WnXK3CMS1UKOYpLFFDu5p/c2gVjRFf6SRagdytG82nS40B4k/LNWbXYnP1XSGBDKzzO qvwyjzahhtVps5smHdpAVuSkDQ5WR58oYqa+P4NWf/JUUmSpkNsIlyMaS4brK7nWmEX/ mKTA== X-Gm-Message-State: AOJu0YxTMPSF0OyxOB3Mzq5mSmRVgcVcrtwnl7GT58D01/zGgc/8VNeU VswSQt56zth+HL+cAVCQ6VEiLCFx5sWARXEWKkCmbAGfl7Lzdw4cCVGjM35/uRv22FGfE6EIzpw L0/XuSX78cAyJhh5Ti5zAK62zKkHo9E3ozl920BsJDMuL94UdgNfWGe3H+as45fwHK+7xiy746i pb7qgxha3WvE1dylQVF37KqoUD8Q+brcflJrxivJrYeKY= 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-kselftest@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 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/selftests/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 += steal_time TEST_GEN_PROGS_x86 += system_counter_offset_test TEST_GEN_PROGS_x86 += pre_fault_memory_test TEST_GEN_PROGS_x86 += x86/tdx_vm_test +TEST_GEN_PROGS_x86 += x86/tdx_shared_mem_test # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86 += x86/nx_huge_pages_test diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h b/tools/testing/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 #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 #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 +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_gpa); @@ -36,5 +39,6 @@ uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax, uint32_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); #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); #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 +#include #include #include "tdx/tdcall.h" #include "tdx/tdx.h" +#include "tdx/tdx_util.h" #include "tdx/test_util.h" +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 = 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, return ret; } + +uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64_t size, uint64_t *data_out) +{ + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_MAP_GPA, + .r12 = address, + .r13 = size + }; + uint64_t ret; + + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (data_out) + *data_out = args.r11; + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c index 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 == KVM_EXIT_HYPERCALL && + vcpu->run->hypercall.nr == 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 = gpa; + range.size = size; + range.attributes = shared_to_private ? KVM_MEMORY_ATTRIBUTE_PRIVATE : 0; + range.flags = 0; + + pr_debug("\t... call KVM_SET_MEMORY_ATTRIBUTES ioctl from vCPU %u with gpa=%#lx, size=%#lx, attributes=%#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 = + (uint32_t *)TDX_SHARED_MEM_TEST_SHARED_GVA; + + uint64_t placeholder; + uint64_t ret; + + /* Map gpa as shared */ + ret = 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 = TDX_SHARED_MEM_TEST_GUEST_WRITE_VALUE; + + /* Exit so host can read shared value */ + ret = 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 = 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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 = 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 = 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 = 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 = 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 = 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_offset), + 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(); +} From patchwork Fri Jun 13 19:13:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897188 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 86FB82E8890 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=1749842092; cv=none; b=jcwQExGqwOxSbDkaKkfbTfsUJmbjxRmGhjBwU5v/qqy1g7q/PaselKqbLHKRn06jmGZsdfiQUlqdHyM34/HH1O1joNyYv/Xjbc/0oM3i1ImGdUjhgLw6DbPypQUI89A5/V3Qv2DaepaNciM03c69gCfS4+xh+dpHmTR3Dj78Abw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842092; c=relaxed/simple; bh=EYmmSlBF4C/72f7adu2xrFOYMqAVykY+Yges75e1mk4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ZjuR3tHW4UbRHmDUuP83CRb3INtowqW8eheu5t/iNnBEHtd2n9EEqhj4UlCNA2KLouNGYXBQAEYjxJCMmcqdL/evfYSwvwLj6VgE2pr7ZTUs91QZe4ZeWwQsC49kgbt0swJZTUGYtHC0H0TUglBvLC+zro6ueuGgSlpBNLrfLTI= 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-740270e168aso2107435b3a.1 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=lZskw1b3BqMdqfWc2oFdrwaGYsgyI6EwG73ljSQZK1sQRvSD6mJFDWiSE1jq0c0JmY 1w+YWoHLa52LuFz+28xK6cCJkqMaJ8E8Rxesdo0Co0mI5C95nflNSRd/RizARunwNI3B LVjEfhEl3eNgBgR2Czyn6V6RletU1KNTKi10EjwAAkABzK/4ns0kAUg8K3EEzq5uUt2j LJH87kYZWCdHNdEvU+J7NoWL7o7tweaQA9o6mBQbQ/uSe/UfXzy1bxK6knkXkYXshFIh CdJAh0ULDDxDloalPyXT8k4j500Mov33RhGEvWXOoGKmTMipzXOZspU6Wn8y1NIgWMSR JPzQ== X-Gm-Message-State: AOJu0YxnvtofBsCWP/JRg35tIIaM5vApulN51NQYCvZ/MD3XBBAz1xZ7 t6KmdXyQ8rnNbRmKW/4DX8T+ld4RAyiAqQ+6zDmqUaa2NDHm6boeCXUPZ2x8PgfUjMG6Em3zGqZ mwQMklTHKdqlPV7LJCmJmAtrrcte42GRSrKITl01FiNMxj1fc2x7Vr4zg9cXPdjS4bk4rcfih0j U3CrGxg8BTbjLYdYRGVyWLgLgLpcjs8SJhgEfSMQDu0EE= 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-kselftest@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 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 sz, 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/selftests/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); } +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 address * of @vaddr_min and backed by physical address equal to returned virtual From patchwork Fri Jun 13 19:13:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896538 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 EAE6E2E88BE 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-74880a02689so2602049b3a.0 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=qtjJ2VdUo0R1Mw9febekKinuCqKBqWXtnV0K+bcYDw4X6o78dvP5hmYzn6YMVn7q4u Cn4+wpdtBHh3dVywh4jD6rApN/E5VfIJ+MQ9QX5rSFprtXx7DnTbQ4dg5DGg9/ZykrAK UBIY6+p1gZFewbkR0e/qPB1sUmFGEE1GMrlxgi4yDywBYDzeNlorhmTGe/8xbO7WzbXA kQZxIPcchNTW43O+TVedvHTMFXf+/PmNPN8Y+4QNVuKd9/HW+LgWhR4rAbV823Ri29V1 YqgwJW1TFFXS3wHuHiVN/7gUyDlC3Qw9gfS6OmgCf7NQD+cvvWo5ntKZJQneZA3W5QlM ryNQ== X-Gm-Message-State: AOJu0Yx7OmQmqaZWN03llQlYpi2s4BzQ/wxSnpvmcfI9hmAUiwydjy/a Oe6vCEulu6W3nPwcXQsyejNl7SlNPqQvwmiR9ci81+/wm8OFsIlmAbiaOnTa6uUEVIcCpwhhDHp NlV1Hv4QRISQXBpKfuq1R5d35BlvvKHsiQAyBu9o2OkqKIWya2L0LO0Rdyh98Pl/FOV8eIL3w5p MLU/8piayo3Mnwy3N9ebLwPabSZhtTFsBBIJh58YURVoE= 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-kselftest@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 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/testing/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" #define TDG_VP_INFO 1 +#define TDG_MEM_PAGE_ACCEPT 6 #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); #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 +#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 = 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); +} From patchwork Fri Jun 13 19:13:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897187 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 DC2F224C08D for ; Fri, 13 Jun 2025 19:14:53 +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=1749842096; cv=none; b=GVJzdIQHPM4mKUJwg16gcXG7OCir2GSKybFksIJxladEohnrj6O0NBT7vorT54pQ5Fi7TX54PqAU9Czu2mbpsmYfOSNqborCsUL2vrdU1zAHWTL9zAq8xfozuO8boDgyYvhpz//TaRuwaQBBzq+l982u+UMPfop2BYbOyQll6nA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842096; c=relaxed/simple; bh=hUSC6q/u5XglC1U4gOPTanfZQQlW+0KgRtgJCMI3QJw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=oupVJLKaHmV1akNsTXfY4yUqTo8fqWVA3DjnHz5xBaC1wQOFPTTiUAvCTTewOtjkyHuLc3ILhzWC61G6W0hFc4swrauIA+ph97Htl1ikw89jER5Pyl1Zpc9CevIRIAb/jcmWf2vDWYUKGu9fzyeOoAHpiDuFWPSMt8x9kxC8eUc= 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.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="yCRHOpyD" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-74858256d38so1851880b3a.2 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=oeBEgnrIo0ad+U8NfCujKF7rRUf8iob2vvyGcJyLB3FYGRFuamaAmNkK9DXfnezRKq +rpzNLJ4mgd5zWTV2nyez0CyHMxCFAxvH0x9bk7tBcTY1vL6gL928lDr6G6PR8q4KJga LYipcxAAKtVeWjduTBFUSJXx2+QJjQW7hSDidmTLRDn4mzTAS7esXCponN3VpTboUW6u NDgEiRGThgbV5GlWHgMVuH7Mxs6Z3zzcQraOJU9VbpMdmFfzatFTsyXaqTfiIpfcD43S 5UlWEEA7tvyWxNT34bSFvdHHk1n9g2WqfR2uLiIcCZq6ajGY4ZqHzTwbiTLehlxj2FdV R86A== X-Gm-Message-State: AOJu0YywoS2DVGDkZ6HoNEaaDwMsPRU+6yMgFQaKoiWkpeiLfKn7VBqI HQUmNjGJkqrcZdKB6h8a7YhnE2FykeNg9bOC6ukewa5c1I3FR9KKBO3GBDqXasfko3yuiSTzaa5 Nsvkn7BGvWm25NL02j6t6IcafC1u5FDHTKP9KSmxRf/3gbzXuYEWKl80fGd5731V/gAbwKcShsJ EN4C/Z33IuhkKX3ebwX4EYb96g8ODyl/N3EnzyjsZGpGQ= 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-kselftest@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 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/testing/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" #define TDG_VP_INFO 1 +#define TDG_VP_VEINFO_GET 3 #define TDG_MEM_PAGE_ACCEPT 6 #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); +/* + * 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 level) 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 = __tdx_module_call(TDG_VP_VEINFO_GET, 0, 0, 0, 0, &out); + + ve->exit_reason = out.rcx; + ve->exit_qual = out.rdx; + ve->gla = out.r8; + ve->gpa = out.r9; + ve->instr_len = out.r10 & 0xffffffff; + ve->instr_info = out.r10 >> 32; + + return ret; +} From patchwork Fri Jun 13 19:13:55 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896537 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 DC42A2EA478 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-74868e73f4fso1933135b3a.3 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=QWxncaqYC0W3P5NLdg3m4j/NMl8WQ2skiH7wqHG2NknJ/xdJImfXgJyxkivG69FGqu eS/FNlROnH1Ffoc4ECrgChUtK1pzKDdW55Dk355eQRf8qCTNIg3NXc4I7RQsPayUpz8F Stl0p6aans1rgscWNniwAX3yRJH8pIa+prYnqEGTERViwYv854GI37sWarYo+OSCiIAE ExQd46XHoAM2wTJIs1DxrwbpyQJjTOTUs29UJ2AM6sddOYJoak4Gh1C46xdYljgUVuog YV+iTYi6nxPul+Q/GZKY9nyXw/g/A7bNviXpTHnEqUFKyx6El4gO1bnHx7JjJ6SXGsBR 2BFw== X-Gm-Message-State: AOJu0YxuEVzKTkIc8giZqPoibo9QunmbFHBEVf6mFCjS18YFYFK085ZA bARoRhSANS1+ggJFCC2NiklHTVaooR1cQN5JEBX/iIWufCI+t8fpoKiFbkrrxjDUcjur4ZLDySn mJNkP2QVT7bA6J5x1btWsUIf0CCJ1tHAE3kurjIiKn0ot2KVx49ei+CP2NtqJpMh1xT05RytCKr Rm0H6WxyHxPUkFwEnnE1vyZzi2hQoPb8NZitKPENHzywA= 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-kselftest@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 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/selftests/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 += system_counter_offset_test TEST_GEN_PROGS_x86 += pre_fault_memory_test TEST_GEN_PROGS_x86 += x86/tdx_vm_test TEST_GEN_PROGS_x86 += x86/tdx_shared_mem_test +TEST_GEN_PROGS_x86 += x86/tdx_upm_test # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86 += 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 the same + * as TDX_UPM_TEST_AREA_GVA_PRIVATE, but it should not overlap with selftest + * 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, they + * are not expected to change throughout the tests. The focus area is memory + * 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_pattern) +{ + size_t i; + + for (i = 0; i < size; i++) { + if (base[i] != 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 = 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 == KVM_EXIT_HYPERCALL && + vcpu->run->hypercall.nr == KVM_HC_MAP_GPA_RANGE) { + uint64_t gpa = 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 = 0; + continue; + } else if (vcpu->run->exit_reason == KVM_EXIT_IO && + vcpu->run->io.port == TDX_UPM_TEST_ACCEPT_PRINT_PORT) { + uint64_t gpa = 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 == 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 = + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_PRIVATE; + struct tdx_upm_test_area *test_area_gva_shared = + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_SHARED; + uint64_t failed_gpa; + uint64_t ret = 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 = 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_GUEST_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_CONFIDENCE_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_FOCUS)); + + /* Remap focus area back to private */ + ret = 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_GUEST_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_AGAIN); + + /* Check that guest can use private memory after focus area is remapped as private */ + TDX_UPM_TEST_ASSERT(fill_and_check(test_area_gva_private, PATTERN_GUEST_GENERAL)); + + 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_offset), + 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 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_offset), + 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_CHECK), + "Host's view of private memory should still be backed by regular memory."); + + /* 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_offset), + SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AGAIN); + + TEST_ASSERT(check_general_areas(test_area_base_hva, PATTERN_CONFIDENCE_CHECK), + "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 <= addr && addr < (uint64_t)hi; +} + +static void guest_ve_handler(struct ex_regs *regs) +{ + struct ve_info ve; + uint64_t ret; + + ret = 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 == 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 = 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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 = 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] = 3; + + test_area_gva_private = vm_vaddr_alloc_private(vm, TDX_UPM_TEST_AREA_SIZE, + 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 = (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 = 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 memory"); + + sync_global_to_guest(vm, test_area_gpa_private); + test_area_gpa_shared = (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(); +} From patchwork Fri Jun 13 19:13:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 897186 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 2FD712EAD05 for ; Fri, 13 Jun 2025 19:14:56 +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=1749842099; cv=none; b=k1VdvHDseysMDry6lLr9RLW7N+BGuUR3A4MI03+ot1q16Rgr1N6lxQJV0YYrzVC7PHDI8aF2JogFtbHNJ0efbgOH4Yxl4fy3VYllXplEbO0BdTr+1LAMhXOtvnRU01/MXwQcYlyHcJofYNdt2k5kVnYb55x6OB/Y2kUV2gGa0QM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749842099; c=relaxed/simple; bh=D0z2DmoLhUuOHBY22PFbuMZf63gkVoAErysUEUFr090=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=CfBkRYa6ZbFjI9PmGwr/BoUv98WxXdrQtIpY1xk3oQosxaTAygqbED8MULfbkzdaC3RwlzF3LV+EFOGsq1ZBK63MHBfzrlsjmknH78KhcA4O0h/t9JCu3gJvG2wHIi+St1Qau1FhWjs/5ylUbBQTbjs538KUanDcPsmC9h2pE2g= 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.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="nXIFeuBM" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2354ba59eb6so37193645ad.1 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=gj94DNE32UMnnVXRUQeFGr+nrjChoON4Vluu3674TLAh6nE8M+avCheZ4FLsnSuVQ/ 0F3OPMviZyRG6gzpNzyXHcX0PSqH1lqp/0PhY0bfsAgE4kNZRyIl+nn8X/7b4rdu+8cw MfOjKrzjoqJ1CdjIU62tQDyMKgSpqopa5hzTLDpZ2wYIhy5UieV3IEtvLhYEfmjZyHd5 sa659d25hH1QJ+zuQ2wj0YrUmFmBs0I4yLZy8NlrnyHkNWXEGCpCuuY/x9qu3qIo+nbx MqmiGSq/7AMJKTuIYHW+kqQY4p2js+gKaPpB5VMkBXkn7nPXWAYyqm/KuxouxjX1HEgI 3QDw== X-Gm-Message-State: AOJu0YzxmpQ568+jK3a2jSyrg1mPhIqLDmXDZntHf9ufSTyPeDVwJuet 2nuCUVTqb+WR7qs4pKiExMCli/yNOAgjc4ERmtgCH5inZgW+lL7Hdg5bI5LugoKnUgWjnSqO8fP hXIYzqdBjBwWSRBh9ja3vIMC16Jp4/vFqknQQx7/ESOABkNuxFmMmLZIfkbusvQCLBvTNyMH5X8 FRSHtTEPxA4e+1iuF6gAD6bz6bQoDcgnHcagbq9bt6+Uw= 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-kselftest@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 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 == KVM_EXIT_HYPERCALL && vcpu->run->hypercall.nr == KVM_HC_MAP_GPA_RANGE) { uint64_t gpa = 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 = 0; continue; + } else if (handle_conversions && + vcpu->run->exit_reason == 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 == + KVM_MEMORY_EXIT_FLAG_PRIVATE); + continue; } else if (vcpu->run->exit_reason == KVM_EXIT_IO && vcpu->run->io.port == TDX_UPM_TEST_ACCEPT_PRINT_PORT) { uint64_t gpa = tdx_test_read_64bit(vcpu, @@ -241,8 +248,48 @@ static void guest_upm_explicit(void) tdx_test_success(); } +static void guest_upm_implicit(void) +{ + struct tdx_upm_test_area *test_area_gva_private = + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_PRIVATE; + struct tdx_upm_test_area *test_area_gva_shared = + (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_GUEST_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_FOCUS)); + + /* 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_GUEST_GENERAL)); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AGAIN); + + /* Check that guest can use private memory after focus area is remapped as private */ + TDX_UPM_TEST_ASSERT(fill_and_check(test_area_gva_private, PATTERN_GUEST_GENERAL)); + + 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 memory."); - 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_offset), @@ -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."); - 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_offset), @@ -322,17 +369,19 @@ static void guest_ve_handler(struct ex_regs *regs) TDX_UPM_TEST_ASSERT(!ret); } -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; vm = td_create(); td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); - vcpu = td_vcpu_add(vm, 0, guest_upm_explicit); + guest_code = implicit ? guest_upm_implicit : guest_upm_explicit; + vcpu = td_vcpu_add(vm, 0, guest_code); vm_install_exception_handler(vm, VE_VECTOR, guest_ve_handler); @@ -373,15 +422,28 @@ static void verify_upm_test(void) td_finalize(vm); - printf("Verifying UPM functionality: explicit MapGPA\n"); + if (implicit) + printf("Verifying UPM functionality: implicit conversion\n"); + else + 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); + run_selftest(vm, vcpu, test_area_base_hva, implicit); kvm_vm_free(vm); } +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"); - 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"); ksft_finished(); } From patchwork Fri Jun 13 19:13:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagi Shahar X-Patchwork-Id: 896536 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 E2323239E7A 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-311e98ee3fcso3002295a91.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=gFyiJN5IkrOIwe+V9C/kevvKQ6FtcbT5MMphkmleoeKmSzgp09lGqYKB0HCyN62LhF FL8fGFahqDasoCQGzzVUURCUiHoBM7Bb+UQVw7YCr4L6iJigv2ipEtge4TxmzJJcEfhC AkerSibYSZv2OLtjZE4GEwImZixjCZMXR8rP2Ib5h4i0oGRs29L5maH1dVzC6uGCkNtu 7dEe/fijjj/zuOYYKyDrK6yRS80fSaZ0yKfPWNEw/0JQRKo6YxVkgfo18hlB8ALTyJfM mplVY/PeBmafcWEX4t6An9TU5vmz20byaOo301XUzd+IWcmpBYIZOappInqjIoER9vHy Ezmg== X-Gm-Message-State: AOJu0YzVzoobzSDcAZWOHjUsyP44mFw+ykAMLPcS2VlMLhLbOAY7B8Gn E0Ka31xsNQ1axiURC9nxKrSb0HksM8zQuXQ+jwTday94WoQBNw4g7Vu4yVTL1Xot/nVUl8r+Tkw dQ+vpD4jCzFisxxlIMuM+ut7tjf0qUMwJtM+r98nXjl2xKVAUVFxF05arCUjsC/oKeoYf633EzY FuFCbDLFPyhXke8Gsjkg1IbLLdEJJ4xUlAEgKAkm8RxWk= 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-kselftest@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 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"); } +#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 memslot + * 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 = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = 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"); - 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"); ksft_finished(); return 0;