From nobody Sun Oct 5 07:26:05 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 150C0273D8E for ; Thu, 7 Aug 2025 20:17:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597854; cv=none; b=teZkQpdFTL1TvTwVdH4Di8uPIQYBNl1rbcphbv6uXgYR1mBCV2CTTJtE1Wc925+45CUkXalj2lNx/5WifKuo/mBW+GjJOtd3CUV+pIAJXU/y+7wDgw7KZNECa5vQh0rNS89cqwD7PArs10/IYPK6cppra34OkYulBdqIzesNErk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754597854; c=relaxed/simple; bh=fGZK/ZXLopkNT4N/Idl0CuDWio5yEH37+0eJsgwxQLI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=G+Hn7aVGaNrEWJYa76rGLPTaWlJ5nO+e6FEf8kKH0MMb3KzsushehaZ6W93HPVbzGoa+oSGVE+v2rVtxSSucWEVW/1BIZ4zyhUc7tyceaCXbwWXooZD/AJWs0f2J6KBu0KMiVRSiFq5x88zBRVcXjnHLD+o6mgIYfHQq44vQA3w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=m9HAWPVF; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--sagis.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="m9HAWPVF" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2400a932e59so20344205ad.1 for ; Thu, 07 Aug 2025 13:17:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754597852; x=1755202652; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=15Qpka96Z78Ss7GgewBHLqp6k9wV1uf8bbKpYv0vf/c=; b=m9HAWPVFoJ9eOzYyuv14HEcy9qu9zqad+8Zjv7rB0TTxkhdOFiI6QlSkqo/brIOb6D ZrNZJJh9qdWrEUCMcr9DAR/prTV9llf1eo1ONkNpDLJfoxstiGU4qa0je5pE5V1gb0uG WENIhuz0gKkkBHepSWMWs0pb/r0ycevtJzhJnY6q8lrwCjOM4L9ACRNCjERhEK9UPb8Z tQTL6am3G3AWyfZuV4vK1RDK74yPAiZohk4W7IdKqB2jnrxVIE3GVt+dnQiArboZmhAg /XqF0pDqU33Q+iSmkROe2f4XWyS1IVhyYs7lpRekjuWrj89FVhHQ+A20lh6L0mW90sL7 Uh0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754597852; x=1755202652; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=15Qpka96Z78Ss7GgewBHLqp6k9wV1uf8bbKpYv0vf/c=; b=n6AOudIXBWON/SEP1VSn7F5Ai5tkvQP3eQ7Do7BxXzTWN9egTeIQ5d4zX+HF2wDYDD uB76ehZZLc5UpKxnmJB2cEUBVmbU+KWW/gRSEykbliUHBN2Uu7B4VMtl0Fcmw0U2dLKF nuCbgo5Xffdyf0Gn6uM8cYYofM5BPkdeY8jaGBPNWw9H7I7WF6bGvhy/qmKslOdfNSaX noeEZKFx00fWiJGA8/UK+Q01lhzqE0XiCXlfsY1xdQZQZSD/7Zst3xSOWwu73xwJ8CEH J+3H5tjPm+mlMyr7CEw36LMzRZp0GcBvqRtyNsd7fpsCv/rvNWR9xS8gzob46uziqQea tM1A== X-Gm-Message-State: AOJu0Yz6+mg42tJhu5g6Sbd1eZwh2vVC/2aBAt+JLk61n2Q1F3llfPA8 aHv1/WJwAlhWpOHlxHgz0qoXpfv4KX1G041XniOrE4kSV78EX3ZzQX1Kf2iZhdGYAomYj33S1Eq VKw== X-Google-Smtp-Source: AGHT+IHCtaiYFn/vLOawALqf+Yv3wNQbooOQ7dEJrMNEqHSOnJMVgt+8XOAAcARXXu+JZtBqaOY3X2QjmQ== X-Received: from pjbsn13.prod.google.com ([2002:a17:90b:2e8d:b0:31f:6965:f3e6]) (user=sagis job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:d4ca:b0:240:2e99:906c with SMTP id d9443c01a7336-242c209fa2bmr4556155ad.15.1754597841757; Thu, 07 Aug 2025 13:17:21 -0700 (PDT) Date: Thu, 7 Aug 2025 13:16:25 -0700 In-Reply-To: <20250807201628.1185915-1-sagis@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250807201628.1185915-1-sagis@google.com> X-Mailer: git-send-email 2.51.0.rc0.155.g4a0f42376b-goog Message-ID: <20250807201628.1185915-30-sagis@google.com> Subject: [PATCH v8 29/30] KVM: selftests: TDX: Add TDX UPM selftests for implicit conversion From: Sagi Shahar To: linux-kselftest@vger.kernel.org, Paolo Bonzini , Shuah Khan , Sean Christopherson , Ackerley Tng , Ryan Afranji , Andrew Jones , Isaku Yamahata , Erdem Aktas , Rick Edgecombe , Sagi Shahar , Roger Wang , Binbin Wu , Oliver Upton , "Pratik R. Sampat" , Reinette Chatre , Ira Weiny Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ackerley Tng This tests the use of guest memory without explicit TDG.VP.VMCALL calls. Provide a 2MB memory region to the TDX guest with a 40KB focus area at offset 1MB intended to be shared between host and guest. The guest does not request memory to be shared or private using TDG.VP.VMCALL but instead relies on memory to be converted automatically based on its access via shared or private mapping. The host automatically converts the memory when guest exits with KVM_EXIT_MEMORY_FAULT. The 2MB region starts out as private with the guest filling it with a pattern, followed by a check from the host to ensure the host is not able to see the pattern. The guest then accesses the 40KB focus area via its shared mapping to trigger implicit conversion followed by checks that the host and guest has the same view of the memory. Finally the guest accesses the 40KB memory via its private mapping to trigger the implicit conversion to private followed by checks to confirm this is the case. Signed-off-by: Ackerley Tng Signed-off-by: Sagi Shahar --- .../testing/selftests/kvm/x86/tdx_upm_test.c | 88 ++++++++++++++++--- 1 file changed, 76 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/kvm/x86/tdx_upm_test.c b/tools/testing= /selftests/kvm/x86/tdx_upm_test.c index 387258ab1a62..2ea5bf6d24b7 100644 --- a/tools/testing/selftests/kvm/x86/tdx_upm_test.c +++ b/tools/testing/selftests/kvm/x86/tdx_upm_test.c @@ -150,10 +150,10 @@ enum { * Does vcpu_run, and also manages memory conversions if requested by the = TD. */ void vcpu_run_and_manage_memory_conversions(struct kvm_vm *vm, - struct kvm_vcpu *vcpu) + struct kvm_vcpu *vcpu, bool handle_conversions) { for (;;) { - vcpu_run(vcpu); + _vcpu_run(vcpu); if (vcpu->run->exit_reason =3D=3D KVM_EXIT_HYPERCALL && vcpu->run->hypercall.nr =3D=3D KVM_HC_MAP_GPA_RANGE) { uint64_t gpa =3D vcpu->run->hypercall.args[0]; @@ -164,6 +164,13 @@ void vcpu_run_and_manage_memory_conversions(struct kvm= _vm *vm, KVM_MAP_GPA_RANGE_ENCRYPTED); vcpu->run->hypercall.ret =3D 0; continue; + } else if (handle_conversions && + vcpu->run->exit_reason =3D=3D KVM_EXIT_MEMORY_FAULT) { + handle_memory_conversion(vm, vcpu->id, vcpu->run->memory_fault.gpa, + vcpu->run->memory_fault.size, + vcpu->run->memory_fault.flags =3D=3D + KVM_MEMORY_EXIT_FLAG_PRIVATE); + continue; } else if (vcpu->run->exit_reason =3D=3D KVM_EXIT_IO && vcpu->run->io.port =3D=3D TDX_UPM_TEST_ACCEPT_PRINT_PORT) { uint64_t gpa =3D tdx_test_read_64bit(vcpu, @@ -241,8 +248,48 @@ static void guest_upm_explicit(void) tdx_test_success(); } =20 +static void guest_upm_implicit(void) +{ + struct tdx_upm_test_area *test_area_gva_private =3D + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_PRIVATE; + struct tdx_upm_test_area *test_area_gva_shared =3D + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_SHARED; + + /* Check: host reading private memory does not modify guest's view */ + fill_test_area(test_area_gva_private, PATTERN_GUEST_GENERAL); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST); + + TDX_UPM_TEST_ASSERT(check_test_area(test_area_gva_private, PATTERN_GUEST_= GENERAL)); + + /* Use focus area as shared */ + fill_focus_area(test_area_gva_shared, PATTERN_GUEST_FOCUS); + + /* General areas should not be affected */ + TDX_UPM_TEST_ASSERT(check_general_areas(test_area_gva_private, PATTERN_GU= EST_GENERAL)); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_SHARED_MEMORY_FROM_HOST); + + /* Check that guest has the same view of shared memory */ + TDX_UPM_TEST_ASSERT(check_focus_area(test_area_gva_shared, PATTERN_HOST_F= OCUS)); + + /* Use focus area as private */ + fill_focus_area(test_area_gva_private, PATTERN_GUEST_FOCUS); + + /* General areas should be unaffected by remapping */ + TDX_UPM_TEST_ASSERT(check_general_areas(test_area_gva_private, PATTERN_GU= EST_GENERAL)); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AG= AIN); + + /* Check that guest can use private memory after focus area is remapped a= s private */ + TDX_UPM_TEST_ASSERT(fill_and_check(test_area_gva_private, PATTERN_GUEST_G= ENERAL)); + + tdx_test_success(); +} + static void run_selftest(struct kvm_vm *vm, struct kvm_vcpu *vcpu, - struct tdx_upm_test_area *test_area_base_hva) + struct tdx_upm_test_area *test_area_base_hva, + bool implicit) { tdx_run(vcpu); tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, @@ -260,7 +307,7 @@ static void run_selftest(struct kvm_vm *vm, struct kvm_= vcpu *vcpu, TEST_ASSERT(check_test_area(test_area_base_hva, PATTERN_CONFIDENCE_CHECK), "Host should read PATTERN_CONFIDENCE_CHECK from guest's private memo= ry."); =20 - vcpu_run_and_manage_memory_conversions(vm, vcpu); + vcpu_run_and_manage_memory_conversions(vm, vcpu, implicit); tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, PORT_WRITE); TEST_ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offse= t), @@ -276,7 +323,7 @@ static void run_selftest(struct kvm_vm *vm, struct kvm_= vcpu *vcpu, TEST_ASSERT(check_focus_area(test_area_base_hva, PATTERN_HOST_FOCUS), "Host should be able to use shared memory."); =20 - vcpu_run_and_manage_memory_conversions(vm, vcpu); + vcpu_run_and_manage_memory_conversions(vm, vcpu, implicit); tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, PORT_WRITE); TEST_ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offse= t), @@ -322,17 +369,19 @@ static void guest_ve_handler(struct ex_regs *regs) TDX_UPM_TEST_ASSERT(!ret); } =20 -static void verify_upm_test(void) +static void verify_upm_test(bool implicit) { struct tdx_upm_test_area *test_area_base_hva; vm_vaddr_t test_area_gva_private; uint64_t test_area_npages; struct kvm_vcpu *vcpu; struct kvm_vm *vm; + void *guest_code; =20 vm =3D td_create(); td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); - vcpu =3D td_vcpu_add(vm, 0, guest_upm_explicit); + guest_code =3D implicit ? guest_upm_implicit : guest_upm_explicit; + vcpu =3D td_vcpu_add(vm, 0, guest_code); =20 vm_install_exception_handler(vm, VE_VECTOR, guest_ve_handler); =20 @@ -373,15 +422,28 @@ static void verify_upm_test(void) =20 td_finalize(vm); =20 - printf("Verifying UPM functionality: explicit MapGPA\n"); + if (implicit) + printf("Verifying UPM functionality: implicit conversion\n"); + else + printf("Verifying UPM functionality: explicit MapGPA\n"); =20 vm_enable_cap(vm, KVM_CAP_EXIT_HYPERCALL, BIT_ULL(KVM_HC_MAP_GPA_RANGE)); =20 - run_selftest(vm, vcpu, test_area_base_hva); + run_selftest(vm, vcpu, test_area_base_hva, implicit); =20 kvm_vm_free(vm); } =20 +void verify_upm_test_explicit(void) +{ + verify_upm_test(false); +} + +void verify_upm_test_implicit(void) +{ + verify_upm_test(true); +} + int main(int argc, char **argv) { ksft_print_header(); @@ -389,9 +451,11 @@ int main(int argc, char **argv) if (!is_tdx_enabled()) ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n"); =20 - ksft_set_plan(1); - ksft_test_result(!run_in_new_process(&verify_upm_test), - "verify_upm_test\n"); + ksft_set_plan(2); + ksft_test_result(!run_in_new_process(&verify_upm_test_explicit), + "verify_upm_test_explicit\n"); + ksft_test_result(!run_in_new_process(&verify_upm_test_implicit), + "verify_upm_test_implicit\n"); =20 ksft_finished(); } --=20 2.51.0.rc0.155.g4a0f42376b-goog