From nobody Thu Apr 9 12:40:30 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A2F32ECAAD2 for ; Mon, 29 Aug 2022 17:11:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231311AbiH2RK6 (ORCPT ); Mon, 29 Aug 2022 13:10:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52172 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230350AbiH2RKz (ORCPT ); Mon, 29 Aug 2022 13:10:55 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D1FFE11142 for ; Mon, 29 Aug 2022 10:10:52 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id k3-20020a170902c40300b001743aafd6c6so6562348plk.20 for ; Mon, 29 Aug 2022 10:10:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=d7ZiMUB7LT41+2/O/fscI6FlTx2h5Za4q8M0Amcc3B4=; b=ZhI8GIrMnTkdrvVsyH9Db+OCesFOtjP3YC959CITathFqifVfvqSQbd5FM76Olwvsb QIZ63/MpVM7Ygz3srB8Iu4f/q5RR+l4/IzBQBcGb9y0jIMHyS16Q3uZv63EWIGjtP0Ut Up5yfbY/kEQsT14gbcfxP0gcGUPtqOBs51u/bSKOUqgxmJfUAggczWvk/MdVhF8sZmCJ dRpCsG5+mGiILKF/BDKHyt08ehXh3fO6IwGSkpR3dn92CFwk6QK/0iN0d17XLHKlHlE3 171TwZaVopJP2hReB2DS9Qbf+JRFzc0MzPHzGvqZx/kz0vIy6ysBYkb8p8UVm5YmAt9A npWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=d7ZiMUB7LT41+2/O/fscI6FlTx2h5Za4q8M0Amcc3B4=; b=XwnfzrSObiFz/9SHsdT2phcbYVXaSSO2Q2RPyWaTYwhCJ43lPaNZGCKKJNlE04tNdG PqtvtGjTZVJ5/db8u9Gq1Tm6z1vyg+F+fPTz54NVJTJmhtgEWvgBUBK8Ymv0/d1PleI7 sYesrjI9zBXFmB3MKuenFqqSJqtUKCKGliVoTATlCJHUHKVa9njEypl18QDaQq7wJ59i kQXAQS6DVL5udervXcHVZa6VGHnPLhwHCKBNIOyZS9SDqluomjGzdgaMr0ZJlkBo5c6j OPAPlNFI9SkDQHmjUUrWHfVYYdSbL1M86MxgtPnp4LcIZReyf5xaKNSr5zW+jSIcLSC3 ufhA== X-Gm-Message-State: ACgBeo3795YyWfyBY8q7SyHEYDtVeoIJhu4mmAhy5SjaNL+Eu1uF3buU 51KCrFbOFc46PNRJ1jEf1z+Qarwa5iw= X-Google-Smtp-Source: AA6agR61sjj8KgjJQ7+tGZSdi+MrfGFJVVy/DwyyXR3ptKKf3tFUJkU3TWwbxGMaGS/oKDXM2GYG6uI3gTo= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:cddb:77a7:c55e:a7a2]) (user=pgonda job=sendgmr) by 2002:a17:90b:4a01:b0:1fb:5583:578a with SMTP id kk1-20020a17090b4a0100b001fb5583578amr19849612pjb.216.1661793052405; Mon, 29 Aug 2022 10:10:52 -0700 (PDT) Date: Mon, 29 Aug 2022 10:10:14 -0700 In-Reply-To: <20220829171021.701198-1-pgonda@google.com> Message-Id: <20220829171021.701198-2-pgonda@google.com> Mime-Version: 1.0 References: <20220829171021.701198-1-pgonda@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [V4 1/8] KVM: selftests: move vm_phy_pages_alloc() earlier in file From: Peter Gonda To: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org, marcorr@google.com, seanjc@google.com, michael.roth@amd.com, thomas.lendacky@amd.com, joro@8bytes.org, mizhang@google.com, pbonzini@redhat.com, andrew.jones@linux.dev, Peter Gonda Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Michael Roth Subsequent patches will break some of this code out into file-local helper functions, which will be used by functions like vm_vaddr_alloc(), which currently are defined earlier in the file, so a forward declaration would be needed. Instead, move it earlier in the file, just above vm_vaddr_alloc() and and friends, which are the main users. Reviewed-by: Mingwei Zhang Reviewed-by: Andrew Jones Signed-off-by: Michael Roth Signed-off-by: Peter Gonda --- tools/testing/selftests/kvm/lib/kvm_util.c | 145 ++++++++++----------- 1 file changed, 72 insertions(+), 73 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 846f9f6c5a17..06559994711e 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1100,6 +1100,78 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, ui= nt32_t vcpu_id) return vcpu; } =20 +/* + * Physical Contiguous Page Allocator + * + * Input Args: + * vm - Virtual Machine + * num - number of pages + * paddr_min - Physical address minimum + * memslot - Memory region to allocate page from + * + * Output Args: None + * + * Return: + * Starting physical address + * + * Within the VM specified by vm, locates a range of available physical + * pages at or above paddr_min. If found, the pages are marked as in use + * and their base address is returned. A TEST_ASSERT failure occurs if + * not enough pages are available at or above paddr_min. + */ +vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, + vm_paddr_t paddr_min, uint32_t memslot) +{ + struct userspace_mem_region *region; + sparsebit_idx_t pg, base; + + TEST_ASSERT(num > 0, "Must allocate at least one page"); + + TEST_ASSERT((paddr_min % vm->page_size) =3D=3D 0, + "Min physical address not divisible by page size.\n paddr_min: 0x%lx pag= e_size: 0x%x", + paddr_min, vm->page_size); + + region =3D memslot2region(vm, memslot); + base =3D pg =3D paddr_min >> vm->page_shift; + + do { + for (; pg < base + num; ++pg) { + if (!sparsebit_is_set(region->unused_phy_pages, pg)) { + base =3D pg =3D sparsebit_next_set(region->unused_phy_pages, pg); + break; + } + } + } while (pg && pg !=3D base + num); + + if (pg =3D=3D 0) { + fprintf(stderr, + "No guest physical page available, paddr_min: 0x%lx page_size: 0x%x mem= slot: %u\n", + paddr_min, vm->page_size, memslot); + fputs("---- vm dump ----\n", stderr); + vm_dump(stderr, vm, 2); + abort(); + } + + for (pg =3D base; pg < base + num; ++pg) + sparsebit_clear(region->unused_phy_pages, pg); + + return base * vm->page_size; +} + +vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min, + uint32_t memslot) +{ + return vm_phy_pages_alloc(vm, 1, paddr_min, memslot); +} + +/* Arbitrary minimum physical address used for virtual translation tables.= */ +#define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000 + +vm_paddr_t vm_alloc_page_table(struct kvm_vm *vm) +{ + return vm_phy_page_alloc(vm, KVM_GUEST_PAGE_TABLE_MIN_PADDR, 0); +} + /* * VM Virtual Address Unused Gap * @@ -1746,79 +1818,6 @@ const char *exit_reason_str(unsigned int exit_reason) return "Unknown"; } =20 -/* - * Physical Contiguous Page Allocator - * - * Input Args: - * vm - Virtual Machine - * num - number of pages - * paddr_min - Physical address minimum - * memslot - Memory region to allocate page from - * - * Output Args: None - * - * Return: - * Starting physical address - * - * Within the VM specified by vm, locates a range of available physical - * pages at or above paddr_min. If found, the pages are marked as in use - * and their base address is returned. A TEST_ASSERT failure occurs if - * not enough pages are available at or above paddr_min. - */ -vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, - vm_paddr_t paddr_min, uint32_t memslot) -{ - struct userspace_mem_region *region; - sparsebit_idx_t pg, base; - - TEST_ASSERT(num > 0, "Must allocate at least one page"); - - TEST_ASSERT((paddr_min % vm->page_size) =3D=3D 0, "Min physical address " - "not divisible by page size.\n" - " paddr_min: 0x%lx page_size: 0x%x", - paddr_min, vm->page_size); - - region =3D memslot2region(vm, memslot); - base =3D pg =3D paddr_min >> vm->page_shift; - - do { - for (; pg < base + num; ++pg) { - if (!sparsebit_is_set(region->unused_phy_pages, pg)) { - base =3D pg =3D sparsebit_next_set(region->unused_phy_pages, pg); - break; - } - } - } while (pg && pg !=3D base + num); - - if (pg =3D=3D 0) { - fprintf(stderr, "No guest physical page available, " - "paddr_min: 0x%lx page_size: 0x%x memslot: %u\n", - paddr_min, vm->page_size, memslot); - fputs("---- vm dump ----\n", stderr); - vm_dump(stderr, vm, 2); - abort(); - } - - for (pg =3D base; pg < base + num; ++pg) - sparsebit_clear(region->unused_phy_pages, pg); - - return base * vm->page_size; -} - -vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min, - uint32_t memslot) -{ - return vm_phy_pages_alloc(vm, 1, paddr_min, memslot); -} - -/* Arbitrary minimum physical address used for virtual translation tables.= */ -#define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000 - -vm_paddr_t vm_alloc_page_table(struct kvm_vm *vm) -{ - return vm_phy_page_alloc(vm, KVM_GUEST_PAGE_TABLE_MIN_PADDR, 0); -} - /* * Address Guest Virtual to Host Virtual * --=20 2.37.2.672.g94769d06f0-goog From nobody Thu Apr 9 12:40:30 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B138ECAAD2 for ; Mon, 29 Aug 2022 17:11:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231386AbiH2RLH (ORCPT ); Mon, 29 Aug 2022 13:11:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52470 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231315AbiH2RK6 (ORCPT ); Mon, 29 Aug 2022 13:10:58 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 92A6861DB3 for ; Mon, 29 Aug 2022 10:10:55 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id z14-20020a170903018e00b00174fff57d17so680970plg.14 for ; Mon, 29 Aug 2022 10:10:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=dX0fGQyKMWqvamPUwIryEe5C9G06tiwNTIrRunhoG64=; b=hd1sCVNIo+5ajxCodOuRhJbGYJXWTf0x/fRkJgF7jA4do+8jVV4WfgOIWfx5ZE5xSW 1vRq9hfdFK0+1uYHgDWI43f94WS7BYDrsf0W/yV08znHqi+YCbitVeABurNu+7ytNTWn JFiqXzjTBT4GbE5HsB/JgOVoewL0YWE+l9S4srFj6HEZFVyKykujdUBhYK//4aqdm/v8 bfiqw2/QOTM5gYuEm3xGJ3Mzd6ykK8VxichismUdcbHINIuIyoXsR9xprnoTPFgX5f88 NVEHpxtO+hPVJKoAuoPQKYVexPx2pMFNlMOpH1lDPOBePNNoiUx/WNkaEBCKteFPZpWu LAyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=dX0fGQyKMWqvamPUwIryEe5C9G06tiwNTIrRunhoG64=; b=NvOYJgW+ow1VVJuhxnfkzYKxx+XYo6CEspvbXwhhmJvLCu5vKJBIdnfRgKjXHQ01kY 3/4QN09gOkWJ89yE7SwUCQQvCnaC5FKyP5+0MHmq0t98tTDBGMxEocf7hEieUL0F991+ QMxYaRUpgkeJB3P/zpAHKkSAKMwK3Z2D9yXaDBnqrO6Zw7kEvNXbMs/8fn8Ll/i53maS 49VN2456bmVxdPDDr9ZxNNyhAR4n6sqUZduc/QQd/cLn9JTzf9I9VtACfRCADi//AKB/ gYMj4Zo5ioIZHgYqrBW8uJWScXxyM5BhqKhk55a5Y9kArFXBtYHJt+QwZvU/3g/91NMl JWbA== X-Gm-Message-State: ACgBeo0O3agO31uobKhA5XyBPtfBVM7jkKiZ3yJQ7R4SXEYY+e3ZaguK 3IkyLatk03Bj69UWJ7MgGBWOJgHpxS8= X-Google-Smtp-Source: AA6agR6sFii+PJbaxcIB2SvAF0BiUh6nSC9bu6R6U3r4Owe3/QiE+IwxlunoIX+KpqilkUvUYT9M5Z1xuFc= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:cddb:77a7:c55e:a7a2]) (user=pgonda job=sendgmr) by 2002:a17:902:bd49:b0:170:953d:c489 with SMTP id b9-20020a170902bd4900b00170953dc489mr17422831plx.96.1661793054376; Mon, 29 Aug 2022 10:10:54 -0700 (PDT) Date: Mon, 29 Aug 2022 10:10:15 -0700 In-Reply-To: <20220829171021.701198-1-pgonda@google.com> Message-Id: <20220829171021.701198-3-pgonda@google.com> Mime-Version: 1.0 References: <20220829171021.701198-1-pgonda@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [V4 2/8] KVM: selftests: sparsebit: add const where appropriate From: Peter Gonda To: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org, marcorr@google.com, seanjc@google.com, michael.roth@amd.com, thomas.lendacky@amd.com, joro@8bytes.org, mizhang@google.com, pbonzini@redhat.com, andrew.jones@linux.dev, Peter Gonda Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Michael Roth Subsequent patches will introduce an encryption bitmap in kvm_util that would be useful to allow tests to access in read-only fashion. This will be done via a const sparsebit*. To avoid warnings or the need to add casts everywhere, add const to the various sparsebit functions that are applicable for read-only usage of sparsebit. Reviewed-by: Andrew Jones Signed-off-by: Michael Roth Signed-off-by: Peter Gonda --- .../testing/selftests/kvm/include/sparsebit.h | 36 +++++++------- tools/testing/selftests/kvm/lib/sparsebit.c | 48 +++++++++---------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/tools/testing/selftests/kvm/include/sparsebit.h b/tools/testin= g/selftests/kvm/include/sparsebit.h index 12a9a4b9cead..fb5170d57fcb 100644 --- a/tools/testing/selftests/kvm/include/sparsebit.h +++ b/tools/testing/selftests/kvm/include/sparsebit.h @@ -30,26 +30,26 @@ typedef uint64_t sparsebit_num_t; =20 struct sparsebit *sparsebit_alloc(void); void sparsebit_free(struct sparsebit **sbitp); -void sparsebit_copy(struct sparsebit *dstp, struct sparsebit *src); +void sparsebit_copy(struct sparsebit *dstp, const struct sparsebit *src); =20 -bool sparsebit_is_set(struct sparsebit *sbit, sparsebit_idx_t idx); -bool sparsebit_is_set_num(struct sparsebit *sbit, +bool sparsebit_is_set(const struct sparsebit *sbit, sparsebit_idx_t idx); +bool sparsebit_is_set_num(const struct sparsebit *sbit, sparsebit_idx_t idx, sparsebit_num_t num); -bool sparsebit_is_clear(struct sparsebit *sbit, sparsebit_idx_t idx); -bool sparsebit_is_clear_num(struct sparsebit *sbit, +bool sparsebit_is_clear(const struct sparsebit *sbit, sparsebit_idx_t idx); +bool sparsebit_is_clear_num(const struct sparsebit *sbit, sparsebit_idx_t idx, sparsebit_num_t num); -sparsebit_num_t sparsebit_num_set(struct sparsebit *sbit); -bool sparsebit_any_set(struct sparsebit *sbit); -bool sparsebit_any_clear(struct sparsebit *sbit); -bool sparsebit_all_set(struct sparsebit *sbit); -bool sparsebit_all_clear(struct sparsebit *sbit); -sparsebit_idx_t sparsebit_first_set(struct sparsebit *sbit); -sparsebit_idx_t sparsebit_first_clear(struct sparsebit *sbit); -sparsebit_idx_t sparsebit_next_set(struct sparsebit *sbit, sparsebit_idx_t= prev); -sparsebit_idx_t sparsebit_next_clear(struct sparsebit *sbit, sparsebit_idx= _t prev); -sparsebit_idx_t sparsebit_next_set_num(struct sparsebit *sbit, +sparsebit_num_t sparsebit_num_set(const struct sparsebit *sbit); +bool sparsebit_any_set(const struct sparsebit *sbit); +bool sparsebit_any_clear(const struct sparsebit *sbit); +bool sparsebit_all_set(const struct sparsebit *sbit); +bool sparsebit_all_clear(const struct sparsebit *sbit); +sparsebit_idx_t sparsebit_first_set(const struct sparsebit *sbit); +sparsebit_idx_t sparsebit_first_clear(const struct sparsebit *sbit); +sparsebit_idx_t sparsebit_next_set(const struct sparsebit *sbit, sparsebit= _idx_t prev); +sparsebit_idx_t sparsebit_next_clear(const struct sparsebit *sbit, sparseb= it_idx_t prev); +sparsebit_idx_t sparsebit_next_set_num(const struct sparsebit *sbit, sparsebit_idx_t start, sparsebit_num_t num); -sparsebit_idx_t sparsebit_next_clear_num(struct sparsebit *sbit, +sparsebit_idx_t sparsebit_next_clear_num(const struct sparsebit *sbit, sparsebit_idx_t start, sparsebit_num_t num); =20 void sparsebit_set(struct sparsebit *sbitp, sparsebit_idx_t idx); @@ -62,9 +62,9 @@ void sparsebit_clear_num(struct sparsebit *sbitp, sparsebit_idx_t start, sparsebit_num_t num); void sparsebit_clear_all(struct sparsebit *sbitp); =20 -void sparsebit_dump(FILE *stream, struct sparsebit *sbit, +void sparsebit_dump(FILE *stream, const struct sparsebit *sbit, unsigned int indent); -void sparsebit_validate_internal(struct sparsebit *sbit); +void sparsebit_validate_internal(const struct sparsebit *sbit); =20 #ifdef __cplusplus } diff --git a/tools/testing/selftests/kvm/lib/sparsebit.c b/tools/testing/se= lftests/kvm/lib/sparsebit.c index 50e0cf41a7dd..6777a5b1fbd2 100644 --- a/tools/testing/selftests/kvm/lib/sparsebit.c +++ b/tools/testing/selftests/kvm/lib/sparsebit.c @@ -202,7 +202,7 @@ static sparsebit_num_t node_num_set(struct node *nodep) /* Returns a pointer to the node that describes the * lowest bit index. */ -static struct node *node_first(struct sparsebit *s) +static struct node *node_first(const struct sparsebit *s) { struct node *nodep; =20 @@ -216,7 +216,7 @@ static struct node *node_first(struct sparsebit *s) * lowest bit index > the index of the node pointed to by np. * Returns NULL if no node with a higher index exists. */ -static struct node *node_next(struct sparsebit *s, struct node *np) +static struct node *node_next(const struct sparsebit *s, struct node *np) { struct node *nodep =3D np; =20 @@ -244,7 +244,7 @@ static struct node *node_next(struct sparsebit *s, stru= ct node *np) * highest index < the index of the node pointed to by np. * Returns NULL if no node with a lower index exists. */ -static struct node *node_prev(struct sparsebit *s, struct node *np) +static struct node *node_prev(const struct sparsebit *s, struct node *np) { struct node *nodep =3D np; =20 @@ -273,7 +273,7 @@ static struct node *node_prev(struct sparsebit *s, stru= ct node *np) * subtree and duplicates the bit settings to the newly allocated nodes. * Returns the newly allocated copy of subtree. */ -static struct node *node_copy_subtree(struct node *subtree) +static struct node *node_copy_subtree(const struct node *subtree) { struct node *root; =20 @@ -307,7 +307,7 @@ static struct node *node_copy_subtree(struct node *subt= ree) * index is within the bits described by the mask bits or the number of * contiguous bits set after the mask. Returns NULL if there is no such n= ode. */ -static struct node *node_find(struct sparsebit *s, sparsebit_idx_t idx) +static struct node *node_find(const struct sparsebit *s, sparsebit_idx_t i= dx) { struct node *nodep; =20 @@ -393,7 +393,7 @@ static struct node *node_add(struct sparsebit *s, spars= ebit_idx_t idx) } =20 /* Returns whether all the bits in the sparsebit array are set. */ -bool sparsebit_all_set(struct sparsebit *s) +bool sparsebit_all_set(const struct sparsebit *s) { /* * If any nodes there must be at least one bit set. Only case @@ -776,7 +776,7 @@ static void node_reduce(struct sparsebit *s, struct nod= e *nodep) /* Returns whether the bit at the index given by idx, within the * sparsebit array is set or not. */ -bool sparsebit_is_set(struct sparsebit *s, sparsebit_idx_t idx) +bool sparsebit_is_set(const struct sparsebit *s, sparsebit_idx_t idx) { struct node *nodep; =20 @@ -922,7 +922,7 @@ static inline sparsebit_idx_t node_first_clear(struct n= ode *nodep, int start) * used by test cases after they detect an unexpected condition, as a means * to capture diagnostic information. */ -static void sparsebit_dump_internal(FILE *stream, struct sparsebit *s, +static void sparsebit_dump_internal(FILE *stream, const struct sparsebit *= s, unsigned int indent) { /* Dump the contents of s */ @@ -970,7 +970,7 @@ void sparsebit_free(struct sparsebit **sbitp) * sparsebit_alloc(). It can though already have bits set, which * if different from src will be cleared. */ -void sparsebit_copy(struct sparsebit *d, struct sparsebit *s) +void sparsebit_copy(struct sparsebit *d, const struct sparsebit *s) { /* First clear any bits already set in the destination */ sparsebit_clear_all(d); @@ -982,7 +982,7 @@ void sparsebit_copy(struct sparsebit *d, struct sparseb= it *s) } =20 /* Returns whether num consecutive bits starting at idx are all set. */ -bool sparsebit_is_set_num(struct sparsebit *s, +bool sparsebit_is_set_num(const struct sparsebit *s, sparsebit_idx_t idx, sparsebit_num_t num) { sparsebit_idx_t next_cleared; @@ -1006,14 +1006,14 @@ bool sparsebit_is_set_num(struct sparsebit *s, } =20 /* Returns whether the bit at the index given by idx. */ -bool sparsebit_is_clear(struct sparsebit *s, +bool sparsebit_is_clear(const struct sparsebit *s, sparsebit_idx_t idx) { return !sparsebit_is_set(s, idx); } =20 /* Returns whether num consecutive bits starting at idx are all cleared. = */ -bool sparsebit_is_clear_num(struct sparsebit *s, +bool sparsebit_is_clear_num(const struct sparsebit *s, sparsebit_idx_t idx, sparsebit_num_t num) { sparsebit_idx_t next_set; @@ -1042,13 +1042,13 @@ bool sparsebit_is_clear_num(struct sparsebit *s, * value. Use sparsebit_any_set(), instead of sparsebit_num_set() > 0, * to determine if the sparsebit array has any bits set. */ -sparsebit_num_t sparsebit_num_set(struct sparsebit *s) +sparsebit_num_t sparsebit_num_set(const struct sparsebit *s) { return s->num_set; } =20 /* Returns whether any bit is set in the sparsebit array. */ -bool sparsebit_any_set(struct sparsebit *s) +bool sparsebit_any_set(const struct sparsebit *s) { /* * Nodes only describe set bits. If any nodes then there @@ -1071,20 +1071,20 @@ bool sparsebit_any_set(struct sparsebit *s) } =20 /* Returns whether all the bits in the sparsebit array are cleared. */ -bool sparsebit_all_clear(struct sparsebit *s) +bool sparsebit_all_clear(const struct sparsebit *s) { return !sparsebit_any_set(s); } =20 /* Returns whether all the bits in the sparsebit array are set. */ -bool sparsebit_any_clear(struct sparsebit *s) +bool sparsebit_any_clear(const struct sparsebit *s) { return !sparsebit_all_set(s); } =20 /* Returns the index of the first set bit. Abort if no bits are set. */ -sparsebit_idx_t sparsebit_first_set(struct sparsebit *s) +sparsebit_idx_t sparsebit_first_set(const struct sparsebit *s) { struct node *nodep; =20 @@ -1098,7 +1098,7 @@ sparsebit_idx_t sparsebit_first_set(struct sparsebit = *s) /* Returns the index of the first cleared bit. Abort if * no bits are cleared. */ -sparsebit_idx_t sparsebit_first_clear(struct sparsebit *s) +sparsebit_idx_t sparsebit_first_clear(const struct sparsebit *s) { struct node *nodep1, *nodep2; =20 @@ -1152,7 +1152,7 @@ sparsebit_idx_t sparsebit_first_clear(struct sparsebi= t *s) /* Returns index of next bit set within s after the index given by prev. * Returns 0 if there are no bits after prev that are set. */ -sparsebit_idx_t sparsebit_next_set(struct sparsebit *s, +sparsebit_idx_t sparsebit_next_set(const struct sparsebit *s, sparsebit_idx_t prev) { sparsebit_idx_t lowest_possible =3D prev + 1; @@ -1245,7 +1245,7 @@ sparsebit_idx_t sparsebit_next_set(struct sparsebit *= s, /* Returns index of next bit cleared within s after the index given by pre= v. * Returns 0 if there are no bits after prev that are cleared. */ -sparsebit_idx_t sparsebit_next_clear(struct sparsebit *s, +sparsebit_idx_t sparsebit_next_clear(const struct sparsebit *s, sparsebit_idx_t prev) { sparsebit_idx_t lowest_possible =3D prev + 1; @@ -1301,7 +1301,7 @@ sparsebit_idx_t sparsebit_next_clear(struct sparsebit= *s, * and returns the index of the first sequence of num consecutively set * bits. Returns a value of 0 of no such sequence exists. */ -sparsebit_idx_t sparsebit_next_set_num(struct sparsebit *s, +sparsebit_idx_t sparsebit_next_set_num(const struct sparsebit *s, sparsebit_idx_t start, sparsebit_num_t num) { sparsebit_idx_t idx; @@ -1336,7 +1336,7 @@ sparsebit_idx_t sparsebit_next_set_num(struct sparseb= it *s, * and returns the index of the first sequence of num consecutively cleared * bits. Returns a value of 0 of no such sequence exists. */ -sparsebit_idx_t sparsebit_next_clear_num(struct sparsebit *s, +sparsebit_idx_t sparsebit_next_clear_num(const struct sparsebit *s, sparsebit_idx_t start, sparsebit_num_t num) { sparsebit_idx_t idx; @@ -1584,7 +1584,7 @@ static size_t display_range(FILE *stream, sparsebit_i= dx_t low, * contiguous bits. This is done because '-' is used to specify command-l= ine * options, and sometimes ranges are specified as command-line arguments. */ -void sparsebit_dump(FILE *stream, struct sparsebit *s, +void sparsebit_dump(FILE *stream, const struct sparsebit *s, unsigned int indent) { size_t current_line_len =3D 0; @@ -1682,7 +1682,7 @@ void sparsebit_dump(FILE *stream, struct sparsebit *s, * s. On error, diagnostic information is printed to stderr and * abort is called. */ -void sparsebit_validate_internal(struct sparsebit *s) +void sparsebit_validate_internal(const struct sparsebit *s) { bool error_detected =3D false; struct node *nodep, *prev =3D NULL; --=20 2.37.2.672.g94769d06f0-goog From nobody Thu Apr 9 12:40:30 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 90832C6FA81 for ; Mon, 29 Aug 2022 17:11:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231310AbiH2RLM (ORCPT ); Mon, 29 Aug 2022 13:11:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231294AbiH2RK7 (ORCPT ); Mon, 29 Aug 2022 13:10:59 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B3E4C63F17 for ; Mon, 29 Aug 2022 10:10:56 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id q60-20020a17090a17c200b001fbc6ba91bbso3534720pja.4 for ; Mon, 29 Aug 2022 10:10:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=6LTZwMRrvDfqpVLhhHWZqp+4pXfvnPC22KdqKnuCz/0=; b=FocFynqOz+suSfkXv90fdFT1W9TWPO5+CnSrEiXMlB57S0wcKJv+jvfvOofZBhm9x4 yCLrY0dFO/JMl8SdBgSGb5NRShYPh7u4NGUVyZCV6z+xdj4Iu90vHNEX1zK9sox2LJ8R 7k9EgEMEG0NJeJbu1Txz/SfpvSybz5ZLIF/Xz+RRrzF2JowSk1+J6bJyFd51csJyA4lk QGEZDHZ2n9ga9yH5EbMoSzPZNyLk5Eztd/481pJk3ZowGknw09ehKoaBWkvew4jNaVtQ dZyjO6oBL5yaPgPgmIq6N7u1jeM1eq9APXSdnvDlp/ersUD2kcYMNf7g1Dn75Xgp7cWk JGPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=6LTZwMRrvDfqpVLhhHWZqp+4pXfvnPC22KdqKnuCz/0=; b=PU6+ZoEtahw7ks1vG8XO7UzNAl8Fopm6tk1scE6ujGV5HPLBnIYyAGjUASGAX77hMW BxVkNhanowbFcxODMEQiI4idZ2AKu9uaCkuHw0NMs1M7VYYUnh94Kh3nl8WgGmRgoGBN TwU0aF/AeRVM+ikPxkuXzR9kqw9EXjKEd8KTKFGvg8/h0HrYeBLAqVNWXmjcN/dJAH7v bXD0YOp3RMgvw9690VjBfFV2HwJaTii2ixXyhu08rUpkx1MYjn4XH9rFm7QA93sdgo61 g5PTPIVyXzq8RBvYDk0EiCOHTW2ZxPTTyEGIkWFsvCh2hCsLpVZGPUzdAY/S+rG95TC9 +xfw== X-Gm-Message-State: ACgBeo2xx1gYhJJ+tNpwJlI9DxCS9Bt2wv75PnfV5Tk0zEeIkVd0TdxD py/pVFa6Vk0AP+sZ42HfgyI/qc2rIpA= X-Google-Smtp-Source: AA6agR6IqZl5qv/5ZTSiHIBpwhrLC/OmUBFjrSuFkk6YDx0C/Z3kfJ6vgNlEMzo+GLzONevvYYx6/tL7SKc= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:cddb:77a7:c55e:a7a2]) (user=pgonda job=sendgmr) by 2002:a63:e507:0:b0:42c:65d3:f3b6 with SMTP id r7-20020a63e507000000b0042c65d3f3b6mr1935660pgh.395.1661793056160; Mon, 29 Aug 2022 10:10:56 -0700 (PDT) Date: Mon, 29 Aug 2022 10:10:16 -0700 In-Reply-To: <20220829171021.701198-1-pgonda@google.com> Message-Id: <20220829171021.701198-4-pgonda@google.com> Mime-Version: 1.0 References: <20220829171021.701198-1-pgonda@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [V4 3/8] KVM: selftests: add hooks for managing encrypted guest memory From: Peter Gonda To: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org, marcorr@google.com, seanjc@google.com, michael.roth@amd.com, thomas.lendacky@amd.com, joro@8bytes.org, mizhang@google.com, pbonzini@redhat.com, andrew.jones@linux.dev, Peter Gonda Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Michael Roth VM implementations that make use of encrypted memory need a way to configure things like the encryption/shared bit position for page table handling, the default encryption policy for internal allocations made by the core library, and a way to fetch the list/bitmap of encrypted pages to do the actual memory encryption. Add an interface to configure these parameters. Also introduce a sparsebit map to track allocations/mappings that should be treated as encrypted, and provide a way for VM implementations to retrieve it to handle operations related memory encryption. Reviewed-by: Mingwei Zhang Signed-off-by: Michael Roth Signed-off-by: Peter Gonda --- .../selftests/kvm/include/kvm_util_base.h | 17 ++++++ tools/testing/selftests/kvm/lib/kvm_util.c | 52 +++++++++++++++++-- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/te= sting/selftests/kvm/include/kvm_util_base.h index 59d52b58a1a6..5ecde5ad4c2f 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -33,6 +33,7 @@ typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) v= irtual address */ struct userspace_mem_region { struct kvm_userspace_memory_region region; struct sparsebit *unused_phy_pages; + struct sparsebit *encrypted_phy_pages; int fd; off_t offset; void *host_mem; @@ -65,6 +66,14 @@ struct userspace_mem_regions { DECLARE_HASHTABLE(slot_hash, 9); }; =20 +/* Memory encryption policy/configuration. */ +struct vm_memcrypt { + bool enabled; + int8_t enc_by_default; + bool has_enc_bit; + int8_t enc_bit; +}; + struct kvm_vm { int mode; unsigned long type; @@ -89,6 +98,7 @@ struct kvm_vm { vm_vaddr_t idt; vm_vaddr_t handlers; uint32_t dirty_ring_size; + struct vm_memcrypt memcrypt; =20 /* Cache of information for binary stats interface */ int stats_fd; @@ -849,4 +859,11 @@ static inline int __vm_disable_nx_huge_pages(struct kv= m_vm *vm) return __vm_enable_cap(vm, KVM_CAP_VM_DISABLE_NX_HUGE_PAGES, 0); } =20 +void vm_set_memory_encryption(struct kvm_vm *vm, bool enc_by_default, bool= has_enc_bit, + uint8_t enc_bit); + +const struct sparsebit *vm_get_encrypted_phy_pages(struct kvm_vm *vm, int = slot, + vm_paddr_t *gpa_start, + uint64_t *size); + #endif /* SELFTEST_KVM_UTIL_BASE_H */ diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 06559994711e..53b9a509c1d5 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -553,6 +553,7 @@ static void __vm_mem_region_delete(struct kvm_vm *vm, vm_ioctl(vm, KVM_SET_USER_MEMORY_REGION, ®ion->region); =20 sparsebit_free(®ion->unused_phy_pages); + sparsebit_free(®ion->encrypted_phy_pages); ret =3D munmap(region->mmap_start, region->mmap_size); TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("munmap()", ret)); =20 @@ -893,6 +894,7 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm, } =20 region->unused_phy_pages =3D sparsebit_alloc(); + region->encrypted_phy_pages =3D sparsebit_alloc(); sparsebit_set_num(region->unused_phy_pages, guest_paddr >> vm->page_shift, npages); region->region.slot =3D slot; @@ -1108,6 +1110,7 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uin= t32_t vcpu_id) * num - number of pages * paddr_min - Physical address minimum * memslot - Memory region to allocate page from + * encrypt - Whether to treat the pages as encrypted * * Output Args: None * @@ -1119,8 +1122,9 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uin= t32_t vcpu_id) * and their base address is returned. A TEST_ASSERT failure occurs if * not enough pages are available at or above paddr_min. */ -vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, - vm_paddr_t paddr_min, uint32_t memslot) +static vm_paddr_t +_vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, vm_paddr_t paddr_min, + uint32_t memslot, bool encrypt) { struct userspace_mem_region *region; sparsebit_idx_t pg, base; @@ -1152,12 +1156,22 @@ vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, si= ze_t num, abort(); } =20 - for (pg =3D base; pg < base + num; ++pg) + for (pg =3D base; pg < base + num; ++pg) { sparsebit_clear(region->unused_phy_pages, pg); + if (encrypt) + sparsebit_set(region->encrypted_phy_pages, pg); + } =20 return base * vm->page_size; } =20 +vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, + vm_paddr_t paddr_min, uint32_t memslot) +{ + return _vm_phy_pages_alloc(vm, num, paddr_min, memslot, + vm->memcrypt.enc_by_default); +} + vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min, uint32_t memslot) { @@ -1741,6 +1755,10 @@ void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_= t indent) region->host_mem); fprintf(stream, "%*sunused_phy_pages: ", indent + 2, ""); sparsebit_dump(stream, region->unused_phy_pages, 0); + if (vm->memcrypt.enabled) { + fprintf(stream, "%*sencrypted_phy_pages: ", indent + 2, ""); + sparsebit_dump(stream, region->encrypted_phy_pages, 0); + } } fprintf(stream, "%*sMapped Virtual Pages:\n", indent, ""); sparsebit_dump(stream, vm->vpages_mapped, indent + 2); @@ -1989,3 +2007,31 @@ void __vm_get_stat(struct kvm_vm *vm, const char *st= at_name, uint64_t *data, break; } } + +void vm_set_memory_encryption(struct kvm_vm *vm, bool enc_by_default, bool= has_enc_bit, + uint8_t enc_bit) +{ + vm->memcrypt.enabled =3D true; + vm->memcrypt.enc_by_default =3D enc_by_default; + vm->memcrypt.has_enc_bit =3D has_enc_bit; + vm->memcrypt.enc_bit =3D enc_bit; +} + +const struct sparsebit * +vm_get_encrypted_phy_pages(struct kvm_vm *vm, int slot, vm_paddr_t *gpa_st= art, + uint64_t *size) +{ + struct userspace_mem_region *region; + + if (!vm->memcrypt.enabled) + return NULL; + + region =3D memslot2region(vm, slot); + if (!region) + return NULL; + + *size =3D region->region.memory_size; + *gpa_start =3D region->region.guest_phys_addr; + + return region->encrypted_phy_pages; +} --=20 2.37.2.672.g94769d06f0-goog From nobody Thu Apr 9 12:40:30 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E3126ECAAD2 for ; Mon, 29 Aug 2022 17:11:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231434AbiH2RLP (ORCPT ); Mon, 29 Aug 2022 13:11:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52654 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231340AbiH2RLB (ORCPT ); Mon, 29 Aug 2022 13:11:01 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5CB5265561 for ; Mon, 29 Aug 2022 10:10:59 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-32a115757b6so139341217b3.13 for ; Mon, 29 Aug 2022 10:10:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=BWDSIQFh5SU/Yj/rdeVVfM86JlFg7CLWWjt3RvlTVT8=; b=rPBdqSr3qzyN9GHMLkW1dGpcU20ZGIp9yOgxBxxd8cBGRmLCfZnbqe4DSJ7oY2X2bd qW4QITYBAmBXXFANzMZWokFig9TMa6Jc9r1UjxOZBX+JEX2LlkYY1W5stRYLZGjSFbDw OoOOnSa6zorbTcaJ8xWoGDtkO3ABEhj2JjidS1J/yfkKWck3bLv7Enfko42XSCMXlJbY akDfphYzbvDGHyG7eHqozDh/M1LlbSe5xe9rsZe5XOXzRtWBVGL30zE/27rEgOtgcsug B5DvBGYu+dEbOTmrllEVg+V4TyhQFHahfO4T9BOBGDdz2rb2EhaG3au38yO1FVB3U5XF xbaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=BWDSIQFh5SU/Yj/rdeVVfM86JlFg7CLWWjt3RvlTVT8=; b=h24SmDppOHj6fpMbfzgECXBdYMZvmU/p2uWcCfrFw9XAUfwaZadXdUNy9Vn+6spDIg uQJjj1I8dhMvsoQRm4QTaza5SsgpgsceC2pDEksvgIdSQl5YzoZ5z3wHpIV36sP2HazO l/U/wKz1CEc6Uf8+4QqszTpeY9NzyqmJwPdVMBrEUY06dXy995ok6D5mPONYNxhkOo4M d6yupOCGKNgIwwJCiqQ+95SiLVe68omlGFlzGFWdknfCVTTgyvZIkiSRy/tR0JJIO02T 8Gg7B36PH9HAXWabGgNQDFUi6R+86n13cXVO9bFXiHAo5vG0TknTZ8VSCfAjZQ9YLE99 7Oxw== X-Gm-Message-State: ACgBeo2Q2N5mbPpYCxlYZFrpmOw9iRewm5+eKY2eMEPLF7vv0mykWDrV gW1V8l1amzbrfiTl3UOg5I0VUYxC0Eo= X-Google-Smtp-Source: AA6agR67NBL7H7Y4dIIhiq7N/9qsKQbiKZwmYiZZSoWxuyk6Bkle2OXlTT7glTdGNJi02DHYb8dMtiobkL0= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:cddb:77a7:c55e:a7a2]) (user=pgonda job=sendgmr) by 2002:a81:7346:0:b0:329:ca9b:a53 with SMTP id o67-20020a817346000000b00329ca9b0a53mr11121530ywc.377.1661793057997; Mon, 29 Aug 2022 10:10:57 -0700 (PDT) Date: Mon, 29 Aug 2022 10:10:17 -0700 In-Reply-To: <20220829171021.701198-1-pgonda@google.com> Message-Id: <20220829171021.701198-5-pgonda@google.com> Mime-Version: 1.0 References: <20220829171021.701198-1-pgonda@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [V4 4/8] KVM: selftests: handle encryption bits in page tables From: Peter Gonda To: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org, marcorr@google.com, seanjc@google.com, michael.roth@amd.com, thomas.lendacky@amd.com, joro@8bytes.org, mizhang@google.com, pbonzini@redhat.com, andrew.jones@linux.dev, Peter Gonda Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Michael Roth SEV guests rely on an encyption bit which resides within the range that current code treats as address bits. Guest code will expect these bits to be set appropriately in their page tables, whereas the rest of the kvm_util functions will generally expect these bits to not be present. Introduce addr_gpa2raw()/addr_raw2gpa() to add/remove these bits, then use them where appropriate. Signed-off-by: Michael Roth Signed-off-by: Peter Gonda --- .../selftests/kvm/include/kvm_util_base.h | 2 + tools/testing/selftests/kvm/lib/kvm_util.c | 55 ++++++++++++++++++- .../selftests/kvm/lib/x86_64/processor.c | 15 +++-- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/te= sting/selftests/kvm/include/kvm_util_base.h index 5ecde5ad4c2f..dda8467d1434 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -401,6 +401,8 @@ 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); void *addr_gpa2alias(struct kvm_vm *vm, vm_paddr_t gpa); +vm_paddr_t addr_raw2gpa(struct kvm_vm *vm, vm_vaddr_t gpa_raw); +vm_paddr_t addr_gpa2raw(struct kvm_vm *vm, vm_vaddr_t gpa); =20 void vcpu_run(struct kvm_vcpu *vcpu); int _vcpu_run(struct kvm_vcpu *vcpu); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 53b9a509c1d5..de13be62d52d 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1388,6 +1388,58 @@ void virt_map(struct kvm_vm *vm, uint64_t vaddr, uin= t64_t paddr, } } =20 +/* + * Mask off any special bits from raw GPA + * + * Input Args: + * vm - Virtual Machine + * gpa_raw - Raw VM physical address + * + * Output Args: None + * + * Return: + * GPA with special bits (e.g. shared/encrypted) masked off. + */ +vm_paddr_t addr_raw2gpa(struct kvm_vm *vm, vm_paddr_t gpa_raw) +{ + if (!vm->memcrypt.has_enc_bit) + return gpa_raw; + + return gpa_raw & ~(1ULL << vm->memcrypt.enc_bit); +} + +/* + * Add special/encryption bits to a GPA based on encryption bitmap. + * + * Input Args: + * vm - Virtual Machine + * gpa - VM physical address + * + * Output Args: None + * + * Return: + * GPA with special bits (e.g. shared/encrypted) added in. + */ +vm_paddr_t addr_gpa2raw(struct kvm_vm *vm, vm_paddr_t gpa) +{ + struct userspace_mem_region *region; + sparsebit_idx_t pg; + vm_paddr_t gpa_raw =3D gpa; + + TEST_ASSERT(addr_raw2gpa(vm, gpa) =3D=3D gpa, "Unexpected bits in GPA: %l= x", + gpa); + + if (!vm->memcrypt.has_enc_bit) + return gpa; + + region =3D userspace_mem_region_find(vm, gpa, gpa); + pg =3D gpa >> vm->page_shift; + if (sparsebit_is_set(region->encrypted_phy_pages, pg)) + gpa_raw |=3D (1ULL << vm->memcrypt.enc_bit); + + return gpa_raw; +} + /* * Address VM Physical to Host Virtual * @@ -1405,9 +1457,10 @@ void virt_map(struct kvm_vm *vm, uint64_t vaddr, uin= t64_t paddr, * address providing the memory to the vm physical address is returned. * A TEST_ASSERT failure occurs if no region containing gpa exists. */ -void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa) +void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa_raw) { struct userspace_mem_region *region; + vm_paddr_t gpa =3D addr_raw2gpa(vm, gpa_raw); =20 region =3D userspace_mem_region_find(vm, gpa, gpa); if (!region) { diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/tes= ting/selftests/kvm/lib/x86_64/processor.c index 2e6e61bbe81b..b2df259ce706 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -118,7 +118,7 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm) =20 /* If needed, create page map l4 table. */ if (!vm->pgd_created) { - vm->pgd =3D vm_alloc_page_table(vm); + vm->pgd =3D addr_gpa2raw(vm, vm_alloc_page_table(vm)); vm->pgd_created =3D true; } } @@ -140,13 +140,15 @@ static uint64_t *virt_create_upper_pte(struct kvm_vm = *vm, int target_level) { uint64_t *pte =3D virt_get_pte(vm, pt_pfn, vaddr, current_level); + uint64_t paddr_raw =3D addr_gpa2raw(vm, paddr); =20 if (!(*pte & PTE_PRESENT_MASK)) { *pte =3D PTE_PRESENT_MASK | PTE_WRITABLE_MASK; if (current_level =3D=3D target_level) - *pte |=3D PTE_LARGE_MASK | (paddr & PHYSICAL_PAGE_MASK); + *pte |=3D PTE_LARGE_MASK | (paddr_raw & PHYSICAL_PAGE_MASK); else - *pte |=3D vm_alloc_page_table(vm) & PHYSICAL_PAGE_MASK; + *pte |=3D addr_gpa2raw(vm, vm_alloc_page_table(vm)) & PHYSICAL_PAGE_MAS= K; + } else { /* * Entry already present. Assert that the caller doesn't want @@ -184,6 +186,8 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, u= int64_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(addr_raw2gpa(vm, paddr) =3D=3D paddr, + "Unexpected bits in paddr: %lx", paddr); =20 /* * Allocate upper level page tables, if not already present. Return @@ -206,7 +210,8 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, u= int64_t paddr, int level) pte =3D virt_get_pte(vm, PTE_GET_PFN(*pde), vaddr, PG_LEVEL_4K); TEST_ASSERT(!(*pte & PTE_PRESENT_MASK), "PTE already present for 4k page at vaddr: 0x%lx\n", vaddr); - *pte =3D PTE_PRESENT_MASK | PTE_WRITABLE_MASK | (paddr & PHYSICAL_PAGE_MA= SK); + *pte =3D PTE_PRESENT_MASK | PTE_WRITABLE_MASK | + (addr_gpa2raw(vm, paddr) & PHYSICAL_PAGE_MASK); } =20 void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr) @@ -515,7 +520,7 @@ vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vadd= r_t gva) if (!(pte[index[0]] & PTE_PRESENT_MASK)) goto unmapped_gva; =20 - return (PTE_GET_PFN(pte[index[0]]) * vm->page_size) + (gva & ~PAGE_MASK); + return addr_raw2gpa(vm, PTE_GET_PFN(pte[index[0]]) * vm->page_size) + (gv= a & ~PAGE_MASK); =20 unmapped_gva: TEST_FAIL("No mapping for vm virtual address, gva: 0x%lx", gva); --=20 2.37.2.672.g94769d06f0-goog From nobody Thu Apr 9 12:40:30 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6105BECAAD2 for ; Mon, 29 Aug 2022 17:11:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231439AbiH2RLV (ORCPT ); Mon, 29 Aug 2022 13:11:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52812 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231346AbiH2RLE (ORCPT ); Mon, 29 Aug 2022 13:11:04 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6EDEB67459 for ; Mon, 29 Aug 2022 10:11:00 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id l16-20020a170902f69000b00175138bcd25so65921plg.2 for ; Mon, 29 Aug 2022 10:11:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=DjSpUEd4vF4lOtP0B99mET3glfEYpz5arg2nPAewBOU=; b=dbslTdjbaCy+F+LzP2tdEdjdbHXFFIR9slvTIDv3G6gdLS8Qx074F0vFDwHlu3al4c A434GfDVx+TxN4m0G5IjSxevmn0DuZUadZ9rw3Y5icqBrmUSAVSufMrMYkQXMKC0b5n5 ZYxZlrAXGNXMnM/LsEwEPxa5hrbYCgKgeJHhc+8PXU+zzj4crGvHR0tQo4V2sGnLQhHq udJom4hoMCj13IDh89VngNXEDoagGF85oXzRbQ4ijVTNZRO4QnpYS783ZiYe0w5svsDT ysB2X/wirzxvzXpYf1izcVDqMZm5medbG2Y80uoHLoi4s11tyHOdAn4Tnd93KtgVdd63 Bohw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=DjSpUEd4vF4lOtP0B99mET3glfEYpz5arg2nPAewBOU=; b=ZuEJr6QhDLyfEusGnsQ5qqNI5JtDyl5UMZGFMfy4Yu8bQKV4hRe9ndxAOIzTD24pRv JcmcBLiJ+Tk/F1BZ4Ei7GwZy9I1h1nBRBfeKyIYpsNIqpfmtDRVoDe+T8pKPBD2KNGph VQrcbkI9cKFV60x9+7eds6TrPsAhdI2rn0iwrMwSEWKSIQ781rSOTXHgKpwx2ubt5vQz i6mNKtTZ3BrGJTArqGUjSrxJ0oNWHLMlW+aZE/EL6H2p3jkcv8rIJ6isaBulOqUD3kZX uDDosc7hvy4f8I7vWcUVkyGZGzxSbd1dtzQS/275VdLplyM7QZFwyLtMSSgXg0M6AU8C znTg== X-Gm-Message-State: ACgBeo1OEQla1Wd/Qw7HjXG5ZfZBSzj6+TfEjR+kaP8HnDXHKbQiBvCe kicFFJ4TWPjRDRviYmzbL2qfQkn+CYk= X-Google-Smtp-Source: AA6agR4t3eAZwrotYfOGWZoVzAPy8mVfbIrrH8RjKkVrjJizM8PQCYVxyMvRapKjxvgGRdCoqyB8Ze3Acc8= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:cddb:77a7:c55e:a7a2]) (user=pgonda job=sendgmr) by 2002:a17:90b:1e08:b0:1f5:1f0d:3736 with SMTP id pg8-20020a17090b1e0800b001f51f0d3736mr19635518pjb.58.1661793059938; Mon, 29 Aug 2022 10:10:59 -0700 (PDT) Date: Mon, 29 Aug 2022 10:10:18 -0700 In-Reply-To: <20220829171021.701198-1-pgonda@google.com> Message-Id: <20220829171021.701198-6-pgonda@google.com> Mime-Version: 1.0 References: <20220829171021.701198-1-pgonda@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [V4 5/8] KVM: selftests: add support for encrypted vm_vaddr_* allocations From: Peter Gonda To: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org, marcorr@google.com, seanjc@google.com, michael.roth@amd.com, thomas.lendacky@amd.com, joro@8bytes.org, mizhang@google.com, pbonzini@redhat.com, andrew.jones@linux.dev, Peter Gonda Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Michael Roth The default policy for whether to handle allocations as encrypted or shared pages is currently determined by vm_phy_pages_alloc(), which in turn uses the policy defined by vm->memcrypt.enc_by_default. Test programs may wish to allocate shared vaddrs for things like sharing memory with the guest. Since enc_by_default will be true in the case of SEV guests (since it's required in order to have the initial ELF binary and page table become part of the initial guest payload), an interface is needed to explicitly request shared pages. Implement this by splitting the common code out from vm_vaddr_alloc() and introducing a new vm_vaddr_alloc_shared(). Signed-off-by: Michael Roth Signed-off-by: Peter Gonda --- .../selftests/kvm/include/kvm_util_base.h | 1 + tools/testing/selftests/kvm/lib/kvm_util.c | 21 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/te= sting/selftests/kvm/include/kvm_util_base.h index dda8467d1434..489e8c833e5f 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -392,6 +392,7 @@ void vm_mem_region_move(struct kvm_vm *vm, uint32_t slo= t, uint64_t new_gpa); void vm_mem_region_delete(struct kvm_vm *vm, uint32_t slot); struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id); vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_m= in); +vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz, vm_vaddr_t = vaddr_min); 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); =20 diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index de13be62d52d..ffdf39a5b12d 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1273,12 +1273,13 @@ static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm= *vm, size_t sz, } =20 /* - * VM Virtual Address Allocate + * VM Virtual Address Allocate Shared/Encrypted * * Input Args: * vm - Virtual Machine * sz - Size in bytes * vaddr_min - Minimum starting virtual address + * encrypt - Whether the region should be handled as encrypted * * Output Args: None * @@ -1291,13 +1292,15 @@ static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm= *vm, size_t sz, * a unique set of pages, with the minimum real allocation being at least * a page. */ -vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_m= in) +static vm_vaddr_t +_vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, bool e= ncrypt) { uint64_t pages =3D (sz >> vm->page_shift) + ((sz % vm->page_size) !=3D 0); =20 virt_pgd_alloc(vm); - vm_paddr_t paddr =3D vm_phy_pages_alloc(vm, pages, - KVM_UTIL_MIN_PFN * vm->page_size, 0); + vm_paddr_t paddr =3D _vm_phy_pages_alloc(vm, pages, + KVM_UTIL_MIN_PFN * vm->page_size, + 0, encrypt); =20 /* * Find an unused range of virtual page addresses of at least @@ -1318,6 +1321,16 @@ vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t = sz, vm_vaddr_t vaddr_min) return vaddr_start; } =20 +vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_m= in) +{ + return _vm_vaddr_alloc(vm, sz, vaddr_min, vm->memcrypt.enc_by_default); +} + +vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz, vm_vaddr_t = vaddr_min) +{ + return _vm_vaddr_alloc(vm, sz, vaddr_min, false); +} + /* * VM Virtual Address Allocate Pages * --=20 2.37.2.672.g94769d06f0-goog From nobody Thu Apr 9 12:40:30 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 004F0ECAAD2 for ; Mon, 29 Aug 2022 17:11:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231376AbiH2RLs (ORCPT ); Mon, 29 Aug 2022 13:11:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53868 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231444AbiH2RL2 (ORCPT ); Mon, 29 Aug 2022 13:11:28 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 754456DF85 for ; Mon, 29 Aug 2022 10:11:02 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id c135-20020a624e8d000000b0053617082770so3319024pfb.8 for ; Mon, 29 Aug 2022 10:11:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=qYBu9gvtSH25gzhu9AMMMrhFUrc6l+KYBGnqODMY8CI=; b=VQ/GS+WrbwpQxbs7uP6/1uuMKIc8Qp7pagAU63kllL+2+jGmpPYU0tO5ogwGOPfrHm vDgXW3vMtbWgrzSzPlj3qKA2pJba7bFL+cCmPx7jwKT8kh468FHjO8lo9NnHkwRAehy5 Gn09ia2P7x4qjIRMNX86MyqBE7JEzHKuo73sfk9LzpPjzTlgNz0Qprp6tAcS8MRNdw1A J2NVgCKx1aWrPIPWBD/g/46y3eRPCz5J/zvgcyDRj0suGWiedUZLv09rzsxFXJS4/TOj MDt9sLgR85Jc3PfuleG58xhMIgEPurZbAsqMjhFYc0iI8ntbW08plqjDPbCwIL2F8qZJ EJSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=qYBu9gvtSH25gzhu9AMMMrhFUrc6l+KYBGnqODMY8CI=; b=xevvpEjA4dfRP5amDvgDe+kWEx5LSXco99G7qMUy2h9qUn40yucuwZb4AQgOBDuMGD MdvgRHO4l7XynZI7NBOn+vIjYCCWd+sLmVNJ1rsl3VIu7dasrG0XBflmlM7P5Po/FE4T FvyLgiwzZnu0Ly0n4Ji1QTgKLyOvm93Yrg0orIekz3d3WcFRruW6knTOiNkPJ7JNF/6v sGxFXM8QFiWVEQX2OZwpuRCeae14aIR9r1h9+s5tnHQWwIPUKUDVpJBLagR5Jh0miSqQ mKgCZLYXOjzPaOJVO0Cal1xRZF5KVW1CbNyb7v/0TbV+bK1OZCl4TphRACR6nyXf+Rw9 v1UQ== X-Gm-Message-State: ACgBeo14faRmlRaPSRQWYukMqY7MHysk5Qcm8qk4J4bgAVDhqm+MZLf6 sBkZc3QsGIwmtPQOmtH+E3D29Ow01pU= X-Google-Smtp-Source: AA6agR7GBGZ5S1BuVQpRcvhwV3Zq/amjMJEM/KN6XPoeQKwtvyCOh5BKqVStNRP9yUi0i3hZOjPsANV5J3k= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:cddb:77a7:c55e:a7a2]) (user=pgonda job=sendgmr) by 2002:a17:902:be02:b0:172:d409:e057 with SMTP id r2-20020a170902be0200b00172d409e057mr17472215pls.90.1661793061692; Mon, 29 Aug 2022 10:11:01 -0700 (PDT) Date: Mon, 29 Aug 2022 10:10:19 -0700 In-Reply-To: <20220829171021.701198-1-pgonda@google.com> Message-Id: <20220829171021.701198-7-pgonda@google.com> Mime-Version: 1.0 References: <20220829171021.701198-1-pgonda@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [V4 6/8] KVM: selftests: add library for creating/interacting with SEV guests From: Peter Gonda To: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org, marcorr@google.com, seanjc@google.com, michael.roth@amd.com, thomas.lendacky@amd.com, joro@8bytes.org, mizhang@google.com, pbonzini@redhat.com, andrew.jones@linux.dev, Peter Gonda Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add interfaces to allow tests to create/manage SEV guests. The additional state associated with these guests is encapsulated in a new struct sev_vm, which is a light wrapper around struct kvm_vm. These VMs will use vm_set_memory_encryption() and vm_get_encrypted_phy_pages() under the covers to configure and sync up with the core kvm_util library on what should/shouldn't be treated as encrypted memory. Originally-by: Michael Roth Signed-off-by: Peter Gonda --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/kvm_util_base.h | 3 + .../selftests/kvm/include/x86_64/sev.h | 47 ++++ tools/testing/selftests/kvm/lib/x86_64/sev.c | 232 ++++++++++++++++++ 4 files changed, 283 insertions(+) create mode 100644 tools/testing/selftests/kvm/include/x86_64/sev.h create mode 100644 tools/testing/selftests/kvm/lib/x86_64/sev.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests= /kvm/Makefile index 23649c5d42fc..0a70e50f0498 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -56,6 +56,7 @@ LIBKVM_x86_64 +=3D lib/x86_64/processor.c LIBKVM_x86_64 +=3D lib/x86_64/svm.c LIBKVM_x86_64 +=3D lib/x86_64/ucall.c LIBKVM_x86_64 +=3D lib/x86_64/vmx.c +LIBKVM_x86_64 +=3D lib/x86_64/sev.c =20 LIBKVM_aarch64 +=3D lib/aarch64/gic.c LIBKVM_aarch64 +=3D lib/aarch64/gic_v3.c diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/te= sting/selftests/kvm/include/kvm_util_base.h index 489e8c833e5f..0927e262623d 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -69,6 +69,7 @@ struct userspace_mem_regions { /* Memory encryption policy/configuration. */ struct vm_memcrypt { bool enabled; + bool encrypted; int8_t enc_by_default; bool has_enc_bit; int8_t enc_bit; @@ -831,6 +832,8 @@ vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vadd= r_t gva); =20 static inline vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva) { + TEST_ASSERT(!vm->memcrypt.encrypted, + "Encrypted guests have their page tables encrypted so gva2gpa conver= sions are not possible."); return addr_arch_gva2gpa(vm, gva); } =20 diff --git a/tools/testing/selftests/kvm/include/x86_64/sev.h b/tools/testi= ng/selftests/kvm/include/x86_64/sev.h new file mode 100644 index 000000000000..810d36377e8c --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/sev.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Helpers used for SEV guests + * + * Copyright (C) 2021 Advanced Micro Devices + */ +#ifndef SELFTEST_KVM_SEV_H +#define SELFTEST_KVM_SEV_H + +#include +#include +#include "kvm_util.h" + +/* Makefile might set this separately for user-overrides */ +#ifndef SEV_DEV_PATH +#define SEV_DEV_PATH "/dev/sev" +#endif + +#define SEV_FW_REQ_VER_MAJOR 0 +#define SEV_FW_REQ_VER_MINOR 17 + +#define SEV_POLICY_NO_DBG (1UL << 0) +#define SEV_POLICY_ES (1UL << 2) + +enum sev_guest_state { + SEV_GSTATE_UNINIT =3D 0, + SEV_GSTATE_LUPDATE, + SEV_GSTATE_LSECRET, + SEV_GSTATE_RUNNING, +}; + +struct sev_vm { + struct kvm_vm *vm; + int fd; + int enc_bit; + uint32_t sev_policy; +}; + +void kvm_sev_ioctl(struct sev_vm *sev, int cmd, void *data); + +struct sev_vm *sev_vm_create(uint32_t policy, uint64_t npages); +void sev_vm_free(struct sev_vm *sev); +void sev_vm_launch(struct sev_vm *sev); +void sev_vm_launch_measure(struct sev_vm *sev, uint8_t *measurement); +void sev_vm_launch_finish(struct sev_vm *sev); + +#endif /* SELFTEST_KVM_SEV_H */ diff --git a/tools/testing/selftests/kvm/lib/x86_64/sev.c b/tools/testing/s= elftests/kvm/lib/x86_64/sev.c new file mode 100644 index 000000000000..dd8d708fd01a --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86_64/sev.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Helpers used for SEV guests + * + * Copyright (C) 2021 Advanced Micro Devices + */ + +#include +#include +#include "kvm_util.h" +#include "linux/psp-sev.h" +#include "processor.h" +#include "sev.h" + +#define CPUID_MEM_ENC_LEAF 0x8000001f +#define CPUID_EBX_CBIT_MASK 0x3f + +/* Common SEV helpers/accessors. */ + +void sev_ioctl(int sev_fd, int cmd, void *data) +{ + int ret; + struct sev_issue_cmd arg; + + arg.cmd =3D cmd; + arg.data =3D (unsigned long)data; + ret =3D ioctl(sev_fd, SEV_ISSUE_CMD, &arg); + TEST_ASSERT(ret =3D=3D 0, + "SEV ioctl %d failed, error: %d, fw_error: %d", + cmd, ret, arg.error); +} + +void kvm_sev_ioctl(struct sev_vm *sev, int cmd, void *data) +{ + struct kvm_sev_cmd arg =3D {0}; + int ret; + + arg.id =3D cmd; + arg.sev_fd =3D sev->fd; + arg.data =3D (__u64)data; + + ret =3D ioctl(sev->vm->fd, KVM_MEMORY_ENCRYPT_OP, &arg); + TEST_ASSERT(ret =3D=3D 0, + "SEV KVM ioctl %d failed, rc: %i errno: %i (%s), fw_error: %d", + cmd, ret, errno, strerror(errno), arg.error); +} + +/* Local helpers. */ + +static void sev_register_user_region(struct sev_vm *sev, void *hva, uint64= _t size) +{ + struct kvm_enc_region range =3D {0}; + int ret; + + pr_debug("%s: hva: %p, size: %lu\n", __func__, hva, size); + + range.addr =3D (__u64)hva; + range.size =3D size; + + ret =3D ioctl(sev->vm->fd, KVM_MEMORY_ENCRYPT_REG_REGION, &range); + TEST_ASSERT(ret =3D=3D 0, "failed to register user range, errno: %i\n", e= rrno); +} + +static void sev_encrypt_phy_range(struct sev_vm *sev, vm_paddr_t gpa, uint= 64_t size) +{ + struct kvm_sev_launch_update_data ksev_update_data =3D {0}; + + pr_debug("%s: addr: 0x%lx, size: %lu\n", __func__, gpa, size); + + ksev_update_data.uaddr =3D (__u64)addr_gpa2hva(sev->vm, gpa); + ksev_update_data.len =3D size; + + kvm_sev_ioctl(sev, KVM_SEV_LAUNCH_UPDATE_DATA, &ksev_update_data); +} + +static void sev_encrypt(struct sev_vm *sev) +{ + const struct sparsebit *enc_phy_pages; + struct kvm_vm *vm =3D sev->vm; + sparsebit_idx_t pg =3D 0; + vm_paddr_t gpa_start; + uint64_t memory_size; + int ctr; + struct userspace_mem_region *region; + + hash_for_each(vm->regions.slot_hash, ctr, region, slot_node) { + enc_phy_pages =3D vm_get_encrypted_phy_pages( + sev->vm, region->region.slot, &gpa_start, &memory_size); + TEST_ASSERT(enc_phy_pages, + "Unable to retrieve encrypted pages bitmap"); + while (pg < (memory_size / vm->page_size)) { + sparsebit_idx_t pg_cnt; + + if (sparsebit_is_clear(enc_phy_pages, pg)) { + pg =3D sparsebit_next_set(enc_phy_pages, pg); + if (!pg) + break; + } + + pg_cnt =3D sparsebit_next_clear(enc_phy_pages, pg) - pg; + if (pg_cnt <=3D 0) + pg_cnt =3D 1; + + sev_encrypt_phy_range(sev, + gpa_start + pg * vm->page_size, + pg_cnt * vm->page_size); + pg +=3D pg_cnt; + } + } + + sev->vm->memcrypt.encrypted =3D true; +} + +/* SEV VM implementation. */ + +static struct sev_vm *sev_vm_alloc(struct kvm_vm *vm) +{ + struct sev_user_data_status sev_status; + uint32_t eax, ebx, ecx, edx; + struct sev_vm *sev; + int sev_fd; + + sev_fd =3D open(SEV_DEV_PATH, O_RDWR); + if (sev_fd < 0) { + pr_info("Failed to open SEV device, path: %s, error: %d, skipping test.\= n", + SEV_DEV_PATH, sev_fd); + return NULL; + } + + sev_ioctl(sev_fd, SEV_PLATFORM_STATUS, &sev_status); + + if (!(sev_status.api_major > SEV_FW_REQ_VER_MAJOR || + (sev_status.api_major =3D=3D SEV_FW_REQ_VER_MAJOR && + sev_status.api_minor >=3D SEV_FW_REQ_VER_MINOR))) { + pr_info("SEV FW version too old. Have API %d.%d (build: %d), need %d.%d,= skipping test.\n", + sev_status.api_major, sev_status.api_minor, sev_status.build, + SEV_FW_REQ_VER_MAJOR, SEV_FW_REQ_VER_MINOR); + return NULL; + } + + sev =3D calloc(1, sizeof(*sev)); + sev->fd =3D sev_fd; + sev->vm =3D vm; + + /* Get encryption bit via CPUID. */ + cpuid(CPUID_MEM_ENC_LEAF, &eax, &ebx, &ecx, &edx); + sev->enc_bit =3D ebx & CPUID_EBX_CBIT_MASK; + + return sev; +} + +void sev_vm_free(struct sev_vm *sev) +{ + kvm_vm_free(sev->vm); + close(sev->fd); + free(sev); +} + +struct sev_vm *sev_vm_create(uint32_t policy, uint64_t npages) +{ + struct sev_vm *sev; + struct kvm_vm *vm; + + /* Need to handle memslots after init, and after setting memcrypt. */ + vm =3D vm_create_barebones(); + sev =3D sev_vm_alloc(vm); + if (!sev) + return NULL; + sev->sev_policy =3D policy; + + kvm_sev_ioctl(sev, KVM_SEV_INIT, NULL); + + vm->vpages_mapped =3D sparsebit_alloc(); + vm_set_memory_encryption(vm, true, true, sev->enc_bit); + pr_info("SEV cbit: %d\n", sev->enc_bit); + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 0, 0, npages, 0); + sev_register_user_region(sev, addr_gpa2hva(vm, 0), + npages * vm->page_size); + + pr_info("SEV guest created, policy: 0x%x, size: %lu KB\n", + sev->sev_policy, npages * vm->page_size / 1024); + + return sev; +} + +void sev_vm_launch(struct sev_vm *sev) +{ + struct kvm_sev_launch_start ksev_launch_start =3D {0}; + struct kvm_sev_guest_status ksev_status; + + ksev_launch_start.policy =3D sev->sev_policy; + kvm_sev_ioctl(sev, KVM_SEV_LAUNCH_START, &ksev_launch_start); + kvm_sev_ioctl(sev, KVM_SEV_GUEST_STATUS, &ksev_status); + TEST_ASSERT(ksev_status.policy =3D=3D sev->sev_policy, "Incorrect guest p= olicy."); + TEST_ASSERT(ksev_status.state =3D=3D SEV_GSTATE_LUPDATE, + "Unexpected guest state: %d", ksev_status.state); + + ucall_init(sev->vm, 0); + + sev_encrypt(sev); +} + +void sev_vm_launch_measure(struct sev_vm *sev, uint8_t *measurement) +{ + struct kvm_sev_launch_measure ksev_launch_measure; + struct kvm_sev_guest_status ksev_guest_status; + + ksev_launch_measure.len =3D 256; + ksev_launch_measure.uaddr =3D (__u64)measurement; + kvm_sev_ioctl(sev, KVM_SEV_LAUNCH_MEASURE, &ksev_launch_measure); + + /* Measurement causes a state transition, check that. */ + kvm_sev_ioctl(sev, KVM_SEV_GUEST_STATUS, &ksev_guest_status); + TEST_ASSERT(ksev_guest_status.state =3D=3D SEV_GSTATE_LSECRET, + "Unexpected guest state: %d", ksev_guest_status.state); +} + +void sev_vm_launch_finish(struct sev_vm *sev) +{ + struct kvm_sev_guest_status ksev_status; + + kvm_sev_ioctl(sev, KVM_SEV_GUEST_STATUS, &ksev_status); + TEST_ASSERT(ksev_status.state =3D=3D SEV_GSTATE_LUPDATE || + ksev_status.state =3D=3D SEV_GSTATE_LSECRET, + "Unexpected guest state: %d", ksev_status.state); + + kvm_sev_ioctl(sev, KVM_SEV_LAUNCH_FINISH, NULL); + + kvm_sev_ioctl(sev, KVM_SEV_GUEST_STATUS, &ksev_status); + TEST_ASSERT(ksev_status.state =3D=3D SEV_GSTATE_RUNNING, + "Unexpected guest state: %d", ksev_status.state); +} --=20 2.37.2.672.g94769d06f0-goog From nobody Thu Apr 9 12:40:30 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55A32C6FA82 for ; Mon, 29 Aug 2022 17:11:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231372AbiH2RLg (ORCPT ); Mon, 29 Aug 2022 13:11:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53786 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231360AbiH2RL0 (ORCPT ); Mon, 29 Aug 2022 13:11:26 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81A99719B0 for ; Mon, 29 Aug 2022 10:11:04 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id y21-20020a056a001c9500b0053817f57e8dso1534865pfw.6 for ; Mon, 29 Aug 2022 10:11:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=faHDPR33m1K+EQWiVoL8b03bkn/+sib5ALODSi8oxlM=; b=bbC9oDe56U6cVXMzD0t1tIcAdVbDbwF0t0J9c/QscUe1+D90/CWAKgmVJlY4xDAu31 rypdHiqiu8s00EQ2rOWyf4j+A1awKy+g6gu6no4h8EjWqEvGZKNgQVJjR8jmi93eD0Cb lSCIqchtAncZO7jSOBYVrd+AGLqNl5RT1R9ewuTqcG8KqZ6ckFe0qlfsVrQAsyPBLxWj RS09JyIkaXukyA7Q9RBUiT6Ratwn9XBulmX/q7fS2Bp2LKFyS9mCeiLJSxZoxJ37EaDE Yxb26iwGmopetj03VVjFJLtcouz4o5VOz2x8nDoDsjiCRuJLNYaeJ04uC/oycVHF9Qbp 7Xkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=faHDPR33m1K+EQWiVoL8b03bkn/+sib5ALODSi8oxlM=; b=G93jzdMyBmv9mcqZ9T6W64qt9qL8aayUbsME/JITkMEXKz9DLTQ/NqNRU9wAY5qGJk v6g68JQuHSHzLxmrwyqt4LVYxBXAkTPd2rOU/I0/D9xpQ4fBoFWU4UuSC4l3kEH1DoVL aj46wWi2WAgIOEEb1f9drdk2O5IhGeHTX5kWgOJMVrzAIk4/oUZSwlXCWUDZYl9tYok9 ditmK/8Tr7g7JvqPKTcDEN1bl8kNGdme/eYKASox8/EnIp4suM5rMS6Eyf17H4d0jZ2y 3sVKkIFdGjv8mBc/8OgsS862LntIc9er86Zz4VtyVm2V4Eqfq6QC1E1YTFSzvxBFNoez tgIg== X-Gm-Message-State: ACgBeo1gC4DFJnRKgwRCr/f7xxwsAhgxZ2xYjL0GilHZ4n/p+SFum6qn 2vf1L3TWZXvj6LydJlPSbn6esWcLBaA= X-Google-Smtp-Source: AA6agR5+zI82TokFysYMOruQ5Cg3tQXZMltp+qDYB8UGqRTHvOXBtBSX7aMB9/yGsgQli3WPYP7aQq0kTw0= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:cddb:77a7:c55e:a7a2]) (user=pgonda job=sendgmr) by 2002:a17:90b:1e53:b0:1fb:3aba:372e with SMTP id pi19-20020a17090b1e5300b001fb3aba372emr19808530pjb.34.1661793063298; Mon, 29 Aug 2022 10:11:03 -0700 (PDT) Date: Mon, 29 Aug 2022 10:10:20 -0700 In-Reply-To: <20220829171021.701198-1-pgonda@google.com> Message-Id: <20220829171021.701198-8-pgonda@google.com> Mime-Version: 1.0 References: <20220829171021.701198-1-pgonda@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [V4 7/8] KVM: selftests: Update ucall pool to allocate from shared memory From: Peter Gonda To: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org, marcorr@google.com, seanjc@google.com, michael.roth@amd.com, thomas.lendacky@amd.com, joro@8bytes.org, mizhang@google.com, pbonzini@redhat.com, andrew.jones@linux.dev, Peter Gonda Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Update the per VM ucall_header allocation from vm_vaddr_alloc() to vm_vaddr_alloc_shared(). This allows encrypted guests to use ucall pools by placing their shared ucall structures in unencrypted (shared) memory. No behavior change for non encrypted guests. Signed-off-by: Peter Gonda --- tools/testing/selftests/kvm/lib/ucall_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing= /selftests/kvm/lib/ucall_common.c index cc79d497b6b4..8e164c47e2fb 100644 --- a/tools/testing/selftests/kvm/lib/ucall_common.c +++ b/tools/testing/selftests/kvm/lib/ucall_common.c @@ -22,7 +22,7 @@ void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa) vm_vaddr_t vaddr; int i; =20 - vaddr =3D vm_vaddr_alloc(vm, sizeof(*hdr), KVM_UTIL_MIN_VADDR); + vaddr =3D vm_vaddr_alloc_shared(vm, sizeof(*hdr), KVM_UTIL_MIN_VADDR); hdr =3D (struct ucall_header *)addr_gva2hva(vm, vaddr); memset(hdr, 0, sizeof(*hdr)); =20 --=20 2.37.2.672.g94769d06f0-goog From nobody Thu Apr 9 12:40:30 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EF4E3ECAAD2 for ; Mon, 29 Aug 2022 17:11:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231359AbiH2RL4 (ORCPT ); Mon, 29 Aug 2022 13:11:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54032 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231395AbiH2RLb (ORCPT ); Mon, 29 Aug 2022 13:11:31 -0400 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7F9565561 for ; Mon, 29 Aug 2022 10:11:05 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id r74-20020a632b4d000000b0041bc393913eso4327597pgr.10 for ; Mon, 29 Aug 2022 10:11:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc; bh=KGXjgJgUkcc6oFwdaRe0n8FvD9Ghrnwp0D/dG+3dTWU=; b=cWB2hlteQpR8H0ijk/rvn+pRYWZkD+xTiwJm//ksuQiCz1oGclbd7uMrQ5LO2KDuaN uEMy5IFApjxfdcjug8ebf8GUdVBxnl8Z4lFBvkuXhTzmJdrlXev/rcDN5SgjY7fOWnDX /T89ONu4AXccoo4f8i/QW/kLKWyNYFU2Dt6JnDid0jd1N5DBwf7yOS92OMPCWmBAYc7f vmxTYI4xnW3Gij51yVrTvPrPQpdapMkkyfJhy8G6fOcFSwIOWHAfinrk34c7dFY8Xgdl ozQoOIALNqRy9IgXaLfOH/ZS1JHLZnAc+UYD+YjLYMyd5BcKw8kmPswwD2j9kG1/noWs zxuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc; bh=KGXjgJgUkcc6oFwdaRe0n8FvD9Ghrnwp0D/dG+3dTWU=; b=iRypmqY2GJDuIYPl0Gi48HMwS4mdf2QPCpEv9MvGDBG1s8sixYK2redXjI8xyPE0DS XwlvTQMYRKqgk3rlxMbdM4FnqDfp5ORK0nRb5SAgDjPgnRJzS6voUJtPpTQ8HnXVcdI9 fVMvbuixyDpphboPjkBPPeaFTTkJhsXGxFjA2JBCmWCbYPN9K3oamOT+1PrtCiTu5yo0 6DG1sojOePop6Ej8i+RWvHuxjHqnWuN22AgpUC1ncuOAvy48drcMaFyEG5bWp/zDqcum 6bsnEsHO8R7hWDUrbWPVnY0OAXsqizkJgu4o6nkzPmnVslOFwjaPqWGS9FzBzCOGnvA2 9GOA== X-Gm-Message-State: ACgBeo2hrdLMYjLNr+nBQlQT6na8iZazyyVwF12w/bIjFUYxMEBgTM0+ B+H6C6y/jSIZilvNwrBwVVNzlW0EZ1M= X-Google-Smtp-Source: AA6agR42GjaUT73++4/5+NtkGa3o94Fet2S/yBtZK0siFe9UPVScWYZSNnJ1nu+hClUYJizP6CZ86NdfTF8= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:cddb:77a7:c55e:a7a2]) (user=pgonda job=sendgmr) by 2002:a17:90b:4c04:b0:1fb:2d28:bfb5 with SMTP id na4-20020a17090b4c0400b001fb2d28bfb5mr19086814pjb.42.1661793065115; Mon, 29 Aug 2022 10:11:05 -0700 (PDT) Date: Mon, 29 Aug 2022 10:10:21 -0700 In-Reply-To: <20220829171021.701198-1-pgonda@google.com> Message-Id: <20220829171021.701198-9-pgonda@google.com> Mime-Version: 1.0 References: <20220829171021.701198-1-pgonda@google.com> X-Mailer: git-send-email 2.37.2.672.g94769d06f0-goog Subject: [V4 8/8] KVM: selftests: Add simple sev vm testing From: Peter Gonda To: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org, marcorr@google.com, seanjc@google.com, michael.roth@amd.com, thomas.lendacky@amd.com, joro@8bytes.org, mizhang@google.com, pbonzini@redhat.com, andrew.jones@linux.dev, Peter Gonda Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A very simple of booting SEV guests that checks related CPUID bits. This is a stripped down version of "[PATCH v2 08/13] KVM: selftests: add SEV boot tests" from Michael but much simpler. Suggested-by: Michael Roth Signed-off-by: Peter Gonda --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/x86_64/sev_all_boot_test.c | 127 ++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/sev_all_boot_test.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftes= ts/kvm/.gitignore index d625a3f83780..ca57969a0923 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -33,6 +33,7 @@ /x86_64/pmu_event_filter_test /x86_64/set_boot_cpu_id /x86_64/set_sregs_test +/x86_64/sev_all_boot_test /x86_64/sev_migrate_tests /x86_64/smm_test /x86_64/state_test diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests= /kvm/Makefile index 0a70e50f0498..10a7ea09ea98 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -123,6 +123,7 @@ TEST_GEN_PROGS_x86_64 +=3D x86_64/tsc_msrs_test TEST_GEN_PROGS_x86_64 +=3D x86_64/vmx_pmu_caps_test TEST_GEN_PROGS_x86_64 +=3D x86_64/xen_shinfo_test TEST_GEN_PROGS_x86_64 +=3D x86_64/xen_vmcall_test +TEST_GEN_PROGS_x86_64 +=3D x86_64/sev_all_boot_test TEST_GEN_PROGS_x86_64 +=3D x86_64/sev_migrate_tests TEST_GEN_PROGS_x86_64 +=3D x86_64/amx_test TEST_GEN_PROGS_x86_64 +=3D x86_64/max_vcpuid_cap_test diff --git a/tools/testing/selftests/kvm/x86_64/sev_all_boot_test.c b/tools= /testing/selftests/kvm/x86_64/sev_all_boot_test.c new file mode 100644 index 000000000000..be8ed3720767 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/sev_all_boot_test.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Basic SEV boot tests. + * + * Copyright (C) 2021 Advanced Micro Devices + */ +#define _GNU_SOURCE /* for program_invocation_short_name */ +#include +#include +#include +#include +#include + +#include "test_util.h" + +#include "kvm_util.h" +#include "processor.h" +#include "svm_util.h" +#include "linux/psp-sev.h" +#include "sev.h" + +#define PAGE_STRIDE 32 + +#define SHARED_PAGES 8192 +#define SHARED_VADDR_MIN 0x1000000 + +#define PRIVATE_PAGES 2048 +#define PRIVATE_VADDR_MIN (SHARED_VADDR_MIN + SHARED_PAGES * PAGE_SIZE) + +#define TOTAL_PAGES (512 + SHARED_PAGES + PRIVATE_PAGES) + +#define NR_SYNCS 1 + +static void guest_run_loop(struct kvm_vcpu *vcpu) +{ + struct ucall uc; + int i; + + for (i =3D 0; i <=3D NR_SYNCS; ++i) { + vcpu_run(vcpu); + switch (get_ucall(vcpu, &uc)) { + case UCALL_SYNC: + continue; + case UCALL_DONE: + return; + case UCALL_ABORT: + TEST_ASSERT(false, "%s at %s:%ld\n\tvalues: %#lx, %#lx", + (const char *)uc.args[0], __FILE__, + uc.args[1], uc.args[2], uc.args[3]); + default: + TEST_ASSERT( + false, "Unexpected exit: %s", + exit_reason_str(vcpu->run->exit_reason)); + } + } +} + +static void guest_sev_code(void) +{ + uint32_t eax, ebx, ecx, edx; + uint64_t sev_status; + + GUEST_SYNC(1); + + GUEST_ASSERT(this_cpu_has(X86_FEATURE_SEV)); + + sev_status =3D rdmsr(MSR_AMD64_SEV); + GUEST_ASSERT((sev_status & 0x1) =3D=3D 1); + + GUEST_DONE(); +} + +static struct sev_vm *setup_test_common(void *guest_code, uint64_t policy, + struct kvm_vcpu **vcpu) +{ + uint8_t measurement[512]; + struct sev_vm *sev; + struct kvm_vm *vm; + int i; + + sev =3D sev_vm_create(policy, TOTAL_PAGES); + TEST_ASSERT(sev, "sev_vm_create() failed to create VM\n"); + + vm =3D sev->vm; + + /* Set up VCPU and initial guest kernel. */ + *vcpu =3D vm_vcpu_add(vm, 0, guest_code); + kvm_vm_elf_load(vm, program_invocation_name); + + /* Allocations/setup done. Encrypt initial guest payload. */ + sev_vm_launch(sev); + + /* Dump the initial measurement. A test to actually verify it would be ni= ce. */ + sev_vm_launch_measure(sev, measurement); + pr_info("guest measurement: "); + for (i =3D 0; i < 32; ++i) + pr_info("%02x", measurement[i]); + pr_info("\n"); + + sev_vm_launch_finish(sev); + + return sev; +} + +static void test_sev(void *guest_code, uint64_t policy) +{ + struct sev_vm *sev; + struct kvm_vcpu *vcpu; + + sev =3D setup_test_common(guest_code, policy, &vcpu); + + /* Guest is ready to run. Do the tests. */ + guest_run_loop(vcpu); + + pr_info("guest ran successfully\n"); + + sev_vm_free(sev); +} + +int main(int argc, char *argv[]) +{ + /* SEV tests */ + test_sev(guest_sev_code, SEV_POLICY_NO_DBG); + test_sev(guest_sev_code, 0); + + return 0; +} --=20 2.37.2.672.g94769d06f0-goog