Received: by 2002:a05:7412:798b:b0:fc:a2b0:25d7 with SMTP id fb11csp679345rdb; Thu, 22 Feb 2024 16:45:26 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUEocwVtG0pO3w7ddkHjLMBxG26I5Sf0JtHyCqEuhBQykL155KcSkiqIovj5EOa1LdTKl3FXivMo+LHGVOkvuvjSIqFrQtoNkjkL+UP5g== X-Google-Smtp-Source: AGHT+IFdZwzNtFYjeSbGr6rzjdsMZHzTzjxeqlidtK8wlMWG4a4aZEv2FMNinYflGeAO9aKg5bET X-Received: by 2002:a05:620a:2051:b0:787:2f5e:a217 with SMTP id d17-20020a05620a205100b007872f5ea217mr628167qka.45.1708649126204; Thu, 22 Feb 2024 16:45:26 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708649126; cv=pass; d=google.com; s=arc-20160816; b=q+cRqkbReUlnX158cazL6Y49Zl2LfcBP+fhRt/nQZtF/RGqA3A6fXmwZNReTGTlVnw qxNOVn/EEuO/qYu05DwsfPOTD5CEoFe80/H650PAo/xcbeYSAXc8NobmMWNhxKSGz/33 xtMXMo3Fp2Z3ReB83ZmrXt3sVa8nZYISVTOKbO67G9QfWUw2zOKy2A/qLaEvdztPIdST wIj4UhOhCJBAAkA8+h+aZ5w+wcWoL64BQkvW8nTMXeG3h9vpuVqp1F9LPmjAE+0GF2V5 9BjcccEnJDAL53gCc4GSqp5+P4pDFc7a8sQlOmzXF1MzHWvGAJObAgIqZ4FEFARoyyt1 19yQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :reply-to:dkim-signature; bh=5xSck0kmkPmdifT3b5IqGmDzhnUFDNPygC9r66kostc=; fh=E+BtDPhSBKYKA/vtrXMZ8DsNYLpjIWE8uAtwHC2CsXg=; b=aU5yEGZQ+z2seHhFW4eD8xafOrxDYZBEZyP7zEANCGl6IZL7yggK1q6PLvTDX3/dLQ PNQX960niLP5Qbm87ycW3FNj6Lbt8YmLgrt14b3vCvgsJ6+2TB4TG6xxaEabuzxeghyo cychvWcOANvqiD9YIjEpkTtyNhXcvGIvnvxQQBJQpwuQP9p0LINSlgEynm1Pyco4Nnvh Tom89EyavdHQQlOoEPOlz9yQbXQQ5r6iu+tO/FV6gfn1S0Z+gyWT/LaTuI4rfS3/BsDO CWjjgYSZMxuQKY+pbmDplKL5nEY3E2HZxgdLYKxKI6Jl98+dhFAKoWiepXcw9lTBUYG2 sh+Q==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=TLHF0+dY; arc=pass (i=1 spf=pass spfdomain=flex--seanjc.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-77588-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-77588-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id dt43-20020a05620a47ab00b00787a74f4888si1653225qkb.165.2024.02.22.16.45.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Feb 2024 16:45:26 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-77588-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=TLHF0+dY; arc=pass (i=1 spf=pass spfdomain=flex--seanjc.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-77588-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-77588-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id E20FD1C20E1F for ; Fri, 23 Feb 2024 00:45:25 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BBEB712B8F; Fri, 23 Feb 2024 00:43:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="TLHF0+dY" 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 DC94511706 for ; Fri, 23 Feb 2024 00:43:15 +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=1708648997; cv=none; b=u3+VPBEX/3TOAJxtb2d4TSqFlxXIEYW7IeLejxbnLGqrL+bqJL7KGwUo+iGtxPi1zYBQPgPuiFlkpJLjMc5Z00P6fYTtCqiJrjOf6NuGqyIHxphcNQu8XeoNXqJx1ZUxrFa+DjPcWCxJ8bvIiVHZYyHM0XYqPnJaiiy9i+vXYYU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708648997; c=relaxed/simple; bh=lmObn+99bRFIPg/jYAV295z2lJEvLtzb/rpu32UHeHI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=rro+XfvARgZtw78pap2n7F2K4uxc3pMi7k0JD7OR6e1rmvaJ6QhOq8mEM1CXoXNNu8miTFFeTj+3to15vPXkmOFAhkmo0+j10lT5eIuISwryhV0yNfni6CtZ51HqgWSFcXAXdxxP1eXIouR9gaB11BtmRbmPGtF2tz1LbgsauNo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=TLHF0+dY; 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--seanjc.bounces.google.com Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-6e4cce1df30so150877b3a.2 for ; Thu, 22 Feb 2024 16:43:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1708648995; x=1709253795; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=5xSck0kmkPmdifT3b5IqGmDzhnUFDNPygC9r66kostc=; b=TLHF0+dY1tlKySZoKw8EtlsyocNA2eHRoxtykNArX4ohS0YBrSeOshMf8QwDEHzRhw 96GawnInAnQH+OQuK4neFpdIitiYrfytJ1fjV799wKbZMjA9iGsN+CJibBU20lyJodkJ WqWah5xB6D71N/vHUa3XKOHl7opo1RbTLEsR1fFTEzUw/03EEdNi3F1dnTkX5/VY4BcQ cdmFX8K+SqJjLLFIc91x1ISVwp8X0SNyK+9Q6TrfcKXbFKRRn0et8hVBKubY3Xv2FwTS TIZjk5QQWpR6iQYjo0RczepaWWp6VmHhoyoMBDildJr6JAV81MpgnWRGy6zpyqPU+mWD IjxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708648995; x=1709253795; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=5xSck0kmkPmdifT3b5IqGmDzhnUFDNPygC9r66kostc=; b=kkMPINshM4sxBuW+8cbwLjBotfSkZEdJ3C8SKhJ8S1CS3QBjsMWDh2VerC08etD1vH Tc7KTGKvOM1oAl+qaQpqjbipKoMcrpUeStE+K97lcrpU+jeA6wGWCd8dvKHN8VAIHzqa HqdHobFsCPBlMG7u4841lScS7L/h+6+e86gTN/tqsMaEFqv8z/Ee/eBmHhx3wdGvnCUA 2JcUzEGO46e1DijVuJZpAwRtZ1RlFfozbVH6JDfjJWoproiN9lR4cWITQTgautBXsLrw H2lBtktU7U3THaKJT3R8l97K0KbOybIqTcVDZhLhUsxzM96XOuiPMw+Sviz2BMNK3cPH evIQ== X-Forwarded-Encrypted: i=1; AJvYcCWS6dH+9kj/7hA94oNdTmxmpTiPfwiub7E2btd23O7IsbC+de4zJUGQDQS6YsY8gxKRJv8h9hMqTY8KC7nup3aeUFiJQuX2Kd24D8J9 X-Gm-Message-State: AOJu0Ywuoci7uTccnNqCPQODIXjvvI3ynpgE9L5NzoVv4/zNzIYI9urv 9TJJR4H4BMAX/mQTfelQ7KEd8Ed49ePU//JCzEblZizRKc7jHy5/P18AoxMZmmoYyv6oNuZJikG 9Gg== X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a05:6a00:23c7:b0:6e4:d2ba:b4c4 with SMTP id g7-20020a056a0023c700b006e4d2bab4c4mr40112pfc.3.1708648995172; Thu, 22 Feb 2024 16:43:15 -0800 (PST) Reply-To: Sean Christopherson Date: Thu, 22 Feb 2024 16:42:54 -0800 In-Reply-To: <20240223004258.3104051-1-seanjc@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240223004258.3104051-1-seanjc@google.com> X-Mailer: git-send-email 2.44.0.rc0.258.g7320e95886-goog Message-ID: <20240223004258.3104051-8-seanjc@google.com> Subject: [PATCH v9 07/11] KVM: selftests: Allow tagging protected memory in guest page tables From: Sean Christopherson To: Paolo Bonzini , Marc Zyngier , Oliver Upton , Anup Patel , Paul Walmsley , Palmer Dabbelt , Albert Ou , Christian Borntraeger , Janosch Frank , Claudio Imbrenda , Sean Christopherson Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, kvm-riscv@lists.infradead.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Vishal Annapurve , Ackerley Tng , Andrew Jones , Tom Lendacky , Michael Roth , Carlos Bilbao , Peter Gonda , Itaru Kitayama Content-Type: text/plain; charset="UTF-8" From: Peter Gonda Add support for tagging and untagging guest physical address, e.g. to allow x86's SEV and TDX guests to embed shared vs. private information in the GPA. SEV (encryption, a.k.a. C-bit) and TDX (shared, a.k.a. S-bit) steal bits from the guest's physical address space that is consumed by the CPU metadata, i.e. effectively aliases the "real" GPA. Implement generic "tagging" so that the shared vs. private metadata can be managed by x86 without bleeding too many details into common code. Cc: Paolo Bonzini Cc: Sean Christopherson Cc: Vishal Annapurve Cc: Ackerly Tng cc: Andrew Jones Cc: Tom Lendacky Cc: Michael Roth Tested-by: Carlos Bilbao Originally-by: Michael Roth Signed-off-by: Peter Gonda Signed-off-by: Sean Christopherson --- .../kvm/include/aarch64/kvm_util_arch.h | 7 +++++++ .../selftests/kvm/include/kvm_util_base.h | 13 ++++++++++++ .../kvm/include/riscv/kvm_util_arch.h | 7 +++++++ .../kvm/include/s390x/kvm_util_arch.h | 7 +++++++ .../kvm/include/x86_64/kvm_util_arch.h | 21 +++++++++++++++++++ tools/testing/selftests/kvm/lib/kvm_util.c | 17 +++++++++++++++ .../selftests/kvm/lib/x86_64/processor.c | 15 ++++++++++++- 7 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/kvm/include/aarch64/kvm_util_arch.h create mode 100644 tools/testing/selftests/kvm/include/riscv/kvm_util_arch.h create mode 100644 tools/testing/selftests/kvm/include/s390x/kvm_util_arch.h create mode 100644 tools/testing/selftests/kvm/include/x86_64/kvm_util_arch.h diff --git a/tools/testing/selftests/kvm/include/aarch64/kvm_util_arch.h b/tools/testing/selftests/kvm/include/aarch64/kvm_util_arch.h new file mode 100644 index 000000000000..218f5cdf0d86 --- /dev/null +++ b/tools/testing/selftests/kvm/include/aarch64/kvm_util_arch.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _TOOLS_LINUX_ASM_ARM64_KVM_HOST_H +#define _TOOLS_LINUX_ASM_ARM64_KVM_HOST_H + +struct kvm_vm_arch {}; + +#endif // _TOOLS_LINUX_ASM_ARM64_KVM_HOST_H diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index cb3159af6db3..4b266dc0c9bd 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -18,9 +18,11 @@ #include #include +#include #include +#include "kvm_util_arch.h" #include "sparsebit.h" /* @@ -113,6 +115,9 @@ struct kvm_vm { vm_vaddr_t idt; vm_vaddr_t handlers; uint32_t dirty_ring_size; + uint64_t gpa_tag_mask; + + struct kvm_vm_arch arch; /* Cache of information for binary stats interface */ int stats_fd; @@ -605,6 +610,12 @@ void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva); vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva); void *addr_gpa2alias(struct kvm_vm *vm, vm_paddr_t gpa); + +static inline vm_paddr_t vm_untag_gpa(struct kvm_vm *vm, vm_paddr_t gpa) +{ + return gpa & ~vm->gpa_tag_mask; +} + void vcpu_run(struct kvm_vcpu *vcpu); int _vcpu_run(struct kvm_vcpu *vcpu); @@ -1114,4 +1125,6 @@ void kvm_selftest_arch_init(void); void kvm_arch_vm_post_create(struct kvm_vm *vm); +bool vm_is_gpa_protected(struct kvm_vm *vm, vm_paddr_t paddr); + #endif /* SELFTEST_KVM_UTIL_BASE_H */ diff --git a/tools/testing/selftests/kvm/include/riscv/kvm_util_arch.h b/tools/testing/selftests/kvm/include/riscv/kvm_util_arch.h new file mode 100644 index 000000000000..c8280d5659ce --- /dev/null +++ b/tools/testing/selftests/kvm/include/riscv/kvm_util_arch.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _TOOLS_LINUX_ASM_RISCV_KVM_HOST_H +#define _TOOLS_LINUX_ASM_RISCV_KVM_HOST_H + +struct kvm_vm_arch {}; + +#endif // _TOOLS_LINUX_ASM_RISCV_KVM_HOST_H diff --git a/tools/testing/selftests/kvm/include/s390x/kvm_util_arch.h b/tools/testing/selftests/kvm/include/s390x/kvm_util_arch.h new file mode 100644 index 000000000000..4c4c1c1e4bf8 --- /dev/null +++ b/tools/testing/selftests/kvm/include/s390x/kvm_util_arch.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _TOOLS_LINUX_ASM_S390_KVM_HOST_H +#define _TOOLS_LINUX_ASM_S390_KVM_HOST_H + +struct kvm_vm_arch {}; + +#endif // _TOOLS_LINUX_ASM_S390_KVM_HOST_H diff --git a/tools/testing/selftests/kvm/include/x86_64/kvm_util_arch.h b/tools/testing/selftests/kvm/include/x86_64/kvm_util_arch.h new file mode 100644 index 000000000000..17bb38236d97 --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/kvm_util_arch.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _TOOLS_LINUX_ASM_X86_KVM_HOST_H +#define _TOOLS_LINUX_ASM_X86_KVM_HOST_H + +#include +#include + +struct kvm_vm_arch { + uint64_t c_bit; + uint64_t s_bit; +}; + +static inline bool __vm_arch_has_protected_memory(struct kvm_vm_arch *arch) +{ + return arch->c_bit || arch->s_bit; +} + +#define vm_arch_has_protected_memory(vm) \ + __vm_arch_has_protected_memory(&(vm)->arch) + +#endif // _TOOLS_LINUX_ASM_X86_KVM_HOST_H diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index e7f4f84f2e68..19511137d1ae 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1597,6 +1597,8 @@ void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa) { struct userspace_mem_region *region; + gpa = vm_untag_gpa(vm, gpa); + region = userspace_mem_region_find(vm, gpa, gpa); if (!region) { TEST_FAIL("No vm physical memory at 0x%lx", gpa); @@ -2305,3 +2307,18 @@ void __attribute((constructor)) kvm_selftest_init(void) kvm_selftest_arch_init(); } + +bool vm_is_gpa_protected(struct kvm_vm *vm, vm_paddr_t paddr) +{ + sparsebit_idx_t pg = 0; + struct userspace_mem_region *region; + + if (!vm_arch_has_protected_memory(vm)) + return false; + + region = userspace_mem_region_find(vm, paddr, paddr); + TEST_ASSERT(region, "No vm physical memory at 0x%lx", paddr); + + pg = paddr >> vm->page_shift; + return sparsebit_is_set(region->protected_phy_pages, pg); +} diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index 615d05247470..6c1d2c0ec584 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -157,6 +157,8 @@ static uint64_t *virt_create_upper_pte(struct kvm_vm *vm, { uint64_t *pte = virt_get_pte(vm, parent_pte, vaddr, current_level); + paddr = vm_untag_gpa(vm, paddr); + if (!(*pte & PTE_PRESENT_MASK)) { *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK; if (current_level == target_level) @@ -200,6 +202,8 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level) "Physical address beyond maximum supported,\n" " paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x", paddr, vm->max_gfn, vm->page_size); + TEST_ASSERT(vm_untag_gpa(vm, paddr) == paddr, + "Unexpected bits in paddr: %lx", paddr); /* * Allocate upper level page tables, if not already present. Return @@ -222,6 +226,15 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level) TEST_ASSERT(!(*pte & PTE_PRESENT_MASK), "PTE already present for 4k page at vaddr: 0x%lx", vaddr); *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK | (paddr & PHYSICAL_PAGE_MASK); + + /* + * 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)) + *pte |= vm->arch.c_bit; + else + *pte |= vm->arch.s_bit; } void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr) @@ -496,7 +509,7 @@ vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva) * No need for a hugepage mask on the PTE, x86-64 requires the "unused" * address bits to be zero. */ - return PTE_GET_PA(*pte) | (gva & ~HUGEPAGE_MASK(level)); + return vm_untag_gpa(vm, PTE_GET_PA(*pte)) | (gva & ~HUGEPAGE_MASK(level)); } static void kvm_setup_gdt(struct kvm_vm *vm, struct kvm_dtable *dt) -- 2.44.0.rc0.258.g7320e95886-goog