From nobody Sat Apr 18 07:34:39 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 5CA35C433EF for ; Fri, 15 Jul 2022 19:30:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231319AbiGOTaT (ORCPT ); Fri, 15 Jul 2022 15:30:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60568 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231273AbiGOTaK (ORCPT ); Fri, 15 Jul 2022 15:30:10 -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 3F36353D23 for ; Fri, 15 Jul 2022 12:30:09 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id d185-20020a6236c2000000b0052af7994d56so2779339pfa.16 for ; Fri, 15 Jul 2022 12:30:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=HghgVNaQ+u17Qr/hDdOGN5qXJrzqdmtpwnb0Yhy4dh8=; b=PpyN7ggMVcUjhI625UHNrva+9WRZaWAxl9DyScRxNKBPPrhj+NYsQN2HxDZIuhOHqE 4A9W4gxv9zUTUkW93n3v0cgITvTpqR5/HKn2glvLOFhg276xe9/RTQ5BU6r1v/ufYfLq o174JKAUWt0qbiMIERCHHyEYjOLKr+0rt5gvsNqvAXGXyuTIaH5nQPSYraFfgcIZi3VI ArEWciB/i3NzlYvmQ8iAhxOvqqYzkQm+aKpufw7y3deWuWfKZ44FGnl8Kmi0iYSWebQD KgXVJfTAaBNQc8Vtseah2SRJbk1aFRcEePS8rnbTahOAg0vNlE5fNbkCSKPpF2TLV62u EZAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=HghgVNaQ+u17Qr/hDdOGN5qXJrzqdmtpwnb0Yhy4dh8=; b=jRguqJCjI2lT8o3RUuVX7ewguV2gnzcTs9DY5L7s+jP70xuwiQ8v8sKHe4U6YvRK/P Ze46s40tdHxOrkIvFNxtzUAAB1Usd/okGtX9F/6dDGNHcwH4xAjAR/ZfdjOX1Y0r0IT4 jfFr0tZcIyJNZg/QGSArqQZLkTsz+AYJ9OAzEb4UKo1TLc6zhnCkZQfY8cCmCIRWtutX 8w/2SiEaiBTssiCakeCSM66g1e+C79lE8hxXc3icuIqgvUOkKilJ3p+pOHsVWjrQbzMM CwuOIfqXN3Ay/U7yeVLRPYxrr6f0Q2K5pJgCXF9vMO1Kq/Ty0CHSPVSjJraXa8Rlmznz rr2g== X-Gm-Message-State: AJIora+opB9S++CS/bmnpSKN0cVM4efEj7E3DNRhdq3ve/u3yLwRXXWR m1Vtphvy0hsBlkUuxmZNajpkZEMgxWQ= X-Google-Smtp-Source: AGRyM1sDJDXiSK+Y+AQeqRGIYrc4BvuGkH/RHKyhUGaRoBx7ZuAoH+j1D0KzhTZuKEmoR0stx4vbH9VFRIg= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a17:902:7406:b0:16b:dab1:12b0 with SMTP id g6-20020a170902740600b0016bdab112b0mr15062276pll.96.1657913408828; Fri, 15 Jul 2022 12:30:08 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:47 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-3-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [RFC V1 01/10] 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, 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 Signed-off-by: Michael Roth Signed-off-by: Peter Gonda --- tools/testing/selftests/kvm/lib/kvm_util.c | 146 ++++++++++----------- 1 file changed, 73 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 768f3bce0161..b07c372b9b37 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1076,6 +1076,79 @@ 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 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); +} + /* * VM Virtual Address Unused Gap * @@ -1722,79 +1795,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.0.170.g444d1eabd0-goog From nobody Sat Apr 18 07:34:39 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 175ECCCA480 for ; Fri, 15 Jul 2022 19:30:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231401AbiGOTa0 (ORCPT ); Fri, 15 Jul 2022 15:30:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60700 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231243AbiGOTaN (ORCPT ); Fri, 15 Jul 2022 15:30:13 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AB63114D36 for ; Fri, 15 Jul 2022 12:30:11 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id m11-20020a5b040b000000b0066fcc60d1a0so4302065ybp.19 for ; Fri, 15 Jul 2022 12:30:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=jUeU4PTq7vqBLBDkh8U1e5K0y5SfhqoOqw9UeYlaJ1U=; b=fGXWkY34tiIMD1ZrP+meYoJmuClyM6iH+2BNkm9txZ3HLfkCvtWIVK+Ygj5p8jt68C Wbl4P4qK/X3SWOvO0H/zFF9+q/D1pwaxtgcj3A+f2eiAizuiins94a2k/57lu03v5M0s XrbYayux+x+BvZiGD68RMkv2PTczvF6c9hIoGcrzBLlhN4oq/jHDrt0obxOtj19RSPS5 9fjYioiITmXrNteCOyuc0KMlsjKnMzxeonhi0Ipt0Ip20Hd2Cwz7mmy8c2xdRVOcus9Q zYvaSv1149Yde3fqbtahm0+D+xOclQQtDBoOUs/OSiy2B6yNF9gezSFsHUA4rg3fCQ5b dA5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=jUeU4PTq7vqBLBDkh8U1e5K0y5SfhqoOqw9UeYlaJ1U=; b=n6jvwgxREJu7HktQuVVPH1JdROwuoM5QxyF+myhwZzbcKwk9zmiOLFUPk+0qKwxVgI xoPdYO7y+VXQbCqz4d9UxK9mnSFAZiOc4tg41sUz3kMQllJk4Z2gYrxsJp1XWrb/Chcc +FMKcQWWUJT7hjg/qPC31wsF6omsY1KAFHR/AYgJHBqDlzUIvCzaSCydbUu5dpQvDyPR /Y0teDk9Xmv2mPycBb0fdsxjqkNHASs8ddj2Spfa1s8JDvVcobdU8Lj/vSda6ZzIIL9p o4shSY0VOAYEAQqRxESf4azfNjPfCJhcmAQgE/UaZJGBPnin7HWwGhETTZQ+0/YSWQOI 5+RQ== X-Gm-Message-State: AJIora+nhu9AHdMoZiVD5eD7lofSXyCh4p7yc1vMB9Y/FZBVi+MFgrHW h/Cbuu7aV0El9EfQG1WvY81E/vUyK8Y= X-Google-Smtp-Source: AGRyM1vTAi7lAwq5ft25rFNTk1WJ2ToFdRVKPu+B1IzxbixZMpOSCn40y83IUXvSpWTdXcyaPQJ+bx4TjUI= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a5b:74e:0:b0:66f:4c3a:2141 with SMTP id s14-20020a5b074e000000b0066f4c3a2141mr16121303ybq.203.1657913410895; Fri, 15 Jul 2022 12:30:10 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:48 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-4-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [RFC V1 02/10] 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, 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. 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.0.170.g444d1eabd0-goog From nobody Sat Apr 18 07:34:39 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 AA058CCA482 for ; Fri, 15 Jul 2022 19:30:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229949AbiGOTaW (ORCPT ); Fri, 15 Jul 2022 15:30:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60580 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231296AbiGOTaR (ORCPT ); Fri, 15 Jul 2022 15:30:17 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8521C5F994 for ; Fri, 15 Jul 2022 12:30:13 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id j2-20020a2597c2000000b0064b3e54191aso4598966ybo.20 for ; Fri, 15 Jul 2022 12:30:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=bIijZklVh4BErKC7Xk3qAcNI5ZtgnzrMkDdijeXT1dg=; b=J55ZDewgDhhwMXux806HT61m2y/vP24Ri69c4jBiaDP9crsHAMRLCUwVtjggDePyHU WLMkhmSEVK9mW5IBCTRTQnX+/gkL9kpy77RvWNvgerSEMKKvpKIcMPPzOnvR7l7MCJu8 t2r1RR4899RMhyVQuKvt9GL9QQCHItPFu5cF1nDn+o0OxEc3oqWjXesM7Z0Se7PJAWbE HHiqkC5c1Qzp3MyyIXgBWXJdix8oKG3VBFNdbVm5Sb8WJ5+ZqflDJpFwD8Fr6J4J8Pdo +NCd/0YZrjAWLsQIiG7UHkPboM9cGzOcvHPdBcPKuwHVRT4MHrhsJybcvMb8JT8XyvVK y8cQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=bIijZklVh4BErKC7Xk3qAcNI5ZtgnzrMkDdijeXT1dg=; b=bw/3lHvQMbPCwU0ExdN4MgmiiDsC3BO3FkLhBqKxkoWowSFYBBcLzEbgy3W+RpgXVX m+FCe+kvxHZzL4EVYiPxFBqiNIq9jk2qKdFPP8UxcTlILrDJeGojj5X9rs86ib2RtO1P 9/dhq8WbUaaXwrtQZoSkvxvggkjtTwdbgGuTQdHJ8aFdFf3sofYqAITMHD798AXzAL4i PVN1q2Y2H4Nl0obK/pIe/e8Sogq34ivd185QHX3xboLjqNtoZ2j4ST3Byzz3QbMiDRjI v+0BCjB28W7lvnIrBkj5SBB1O44TcS68UMI8WIFgbfftVwzvT272zBwnPg03Xbnnd4qO AnBw== X-Gm-Message-State: AJIora/IWzjrDnmdduaQdpd7+g4J53L0igzSWKYW+T9q7T2FfcJYrYiM 8tKwvPI4OcqOYIvv7pXQXwhjqxnqqnY= X-Google-Smtp-Source: AGRyM1tV7Yq0WJ/pj2dbKQVAvb1sxi48Uimb+yF3RJXIeDq53I6R1rXun5mmgDrNVbT6RfjH4dGx1U7tU+Q= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a81:f82:0:b0:31c:f1ae:1ed6 with SMTP id 124-20020a810f82000000b0031cf1ae1ed6mr17477996ywp.249.1657913412751; Fri, 15 Jul 2022 12:30:12 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:49 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-5-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [RFC V1 03/10] 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, 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 b78e3c7a2566..3acb1552942b 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -32,6 +32,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; @@ -61,6 +62,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; @@ -84,6 +93,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; @@ -820,4 +830,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 b07c372b9b37..6f96d1c51f75 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -529,6 +529,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 @@ -869,6 +870,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; @@ -1084,6 +1086,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 * @@ -1095,8 +1098,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; @@ -1129,12 +1133,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) { @@ -1718,6 +1732,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); @@ -1966,3 +1984,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.0.170.g444d1eabd0-goog From nobody Sat Apr 18 07:34:39 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 9FDFDC43334 for ; Fri, 15 Jul 2022 19:30:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231419AbiGOTac (ORCPT ); Fri, 15 Jul 2022 15:30:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60862 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231326AbiGOTaT (ORCPT ); Fri, 15 Jul 2022 15:30:19 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5458071BEE for ; Fri, 15 Jul 2022 12:30:15 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 81-20020a630054000000b0041978b2aa9eso3148765pga.9 for ; Fri, 15 Jul 2022 12:30:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=yOrbZ7RaV7Jx4ZXQ1D7tU72Pr1kFVsoHo/rJhv/+f3g=; b=oArOwSWG8Bb9+5BGHMFgAnUdMJxS2ROAx0bvTpoTeYW2xU5V2YPuMnDS8qUXvn+fvW Ql+JiTST9SKDeO+ivkOfAJj7zazO4OTmqwrxFZRYnEznjhQOw9BBiTNMom7bjYgr8kV0 oyw35ZqK1AxRHnIXQHJW3fVxvYj4+YlXxasXIWCRvlo2HqVFD+MfYOivXiuP1Qblk5wO ja68CsCXWGbxy9+mZRXaWBtLOxdX7R8RJfKQ/mdHfuVjXjFGBsrfBoodbYThusFjUJJY cbpDCsyiGE5LURNEhxzmqUdGt5fPbqsAnOPD9GQDKE+0feDY+z0DDkHeh1vEmxmy5IDX 1Eew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=yOrbZ7RaV7Jx4ZXQ1D7tU72Pr1kFVsoHo/rJhv/+f3g=; b=TWWXHbdnLZAkc6dsNOjb0/00c5+zyD2MgoCcdRc9J09dOt7Q3tTfE91Z02DlxeVKIX saStOMLIW/zaydD6AwxMsVk9U63c4S+fKc/nnqKUOqXAbOziGok/9At36MOARQKKwl6X qzwUgQsD49fWJ/HVCmwLzPb1uvF1z8hGcFAO2AFWTnagij0SbbxIFIS+nDk/P5ShqYrH kcfh9TAypHOk8bUcgksjOUi6Hex3DYl6l2nwnggxtMMs4jTVaK0Sp30erZAGqKNfQ7AV 7d7y8NoE8XfRbK+zkcZv/KbfrXJHhMLq4IXCMdzai1q833MAR1T5roHocV22vzJ55V8K 6pmw== X-Gm-Message-State: AJIora+fVbaHoOCKDgcPAA0DFXBIsMlACzTfFnEirmgdn7eDhbAk3nko HCogy3x1F9tyUdEO1rj2lQCzHqNScvI= X-Google-Smtp-Source: AGRyM1sFsC+wz7TDFZzydmeHoaICojlZlmCb3NmxuIgDy3cyoQAxunjB+rE54Ba/PvXoFrpJkvBTv48sd9E= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a17:90a:249:b0:1e0:a8a3:3c6c with SMTP id t9-20020a17090a024900b001e0a8a33c6cmr911058pje.0.1657913414519; Fri, 15 Jul 2022 12:30:14 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:50 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-6-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [RFC V1 04/10] 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, 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 3acb1552942b..17eb5fb70867 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -396,6 +396,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 6f96d1c51f75..5b473a8c90ae 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1365,6 +1365,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 * @@ -1382,9 +1434,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 1a32b1c75e9a..53b115876417 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -116,7 +116,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; } } @@ -138,13 +138,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 @@ -182,6 +184,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 @@ -204,7 +208,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) @@ -517,7 +522,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.0.170.g444d1eabd0-goog From nobody Sat Apr 18 07:34:39 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 BDFECC433EF for ; Fri, 15 Jul 2022 19:30:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231447AbiGOTao (ORCPT ); Fri, 15 Jul 2022 15:30:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60896 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231277AbiGOTaV (ORCPT ); Fri, 15 Jul 2022 15:30:21 -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 5472D5C9C0 for ; Fri, 15 Jul 2022 12:30:17 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id 134-20020a63018c000000b0040cf04213a1so3148235pgb.6 for ; Fri, 15 Jul 2022 12:30:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=gs77UXlDczSHQF1pVGrbWwFBLbmSJeDP2KCTQVzhQ4w=; b=Yho4pa020PJOurbSFO1drfQJF8CGNLTiZXlRmYL31dZYBSt+tcx8ZXb+XDmvhx+yuk xUrMgnZvQ1eoy71kjdUfS7R9okqDtcQG1tDz/8NT+o/Pf7PRvwwnc58MstW9HBu5oFMR GO+Ee4Jklm816guSzjcyAJPAhWGAlppS2F4kCrrJPdmmGnqi2cjtbI3RSZy1ysTPXyWa FPrmrnLYXzMnv8hTN4ylaHNP4o5oOuyeOFrgSdbTWWkbsiWbvPHnQmjh1jGpF67Pitdb TQGz9J0SXIHYAGX+RNnZ+vX+cGAG2zO80d4uH+bftxTHinhgpC3v0ufO/BhIOC9gjWyh ZyHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=gs77UXlDczSHQF1pVGrbWwFBLbmSJeDP2KCTQVzhQ4w=; b=VE+3VXi668TgpATJKBlgWhomZDBvDRW+dPOd/8/3dR7AX1hJDdb4mJ9eFkpQdBMhuA 7bXEMZ6Y/w91366DFyDRuYptzRTVXeKjQkOmuExVqLCRx+CZxyjHaGrPNoiaQu4Ga57s DI4iQuMMIzigQGTmcZLJz3aPaGPBwMMmarZWZGlKZkEuJo/vJ7Rdf2IYedSDKer/YUHa WNQplcAkCFUJ3irsNWWDcKx4B8MkGJBvas4Idc5jyBXQESWKI+b9/yEqzatiKWpAk8dr EQNbz3raVJbZeWLjCJ4Q1UxnHGltNMb/X6rXf4wAHlqrSAx9vg6m3ta21aImx8Aye17h 6Bjw== X-Gm-Message-State: AJIora8UA7m8V1BTwv9NJHgaGI40lfYQ1++mcF1LlronYIArko52m3Gm NftLinBvcqdLuIa8aepyzWY78L2Y99Y= X-Google-Smtp-Source: AGRyM1vwMHvTQkuA7wCpNxdf75a2AjYo/3WibRk6QtD/vo0CRxXVclkLhhGPrsj0ARzMPa5/MUI93HQ7DjQ= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a17:902:e5cf:b0:16c:413c:fbfa with SMTP id u15-20020a170902e5cf00b0016c413cfbfamr15226411plf.80.1657913416653; Fri, 15 Jul 2022 12:30:16 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:51 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-7-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [RFC V1 05/10] 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, 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 17eb5fb70867..60b604ac9fa9 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -387,6 +387,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 5b473a8c90ae..17d9a2606cc8 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1250,12 +1250,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 * @@ -1268,13 +1269,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 @@ -1295,6 +1298,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.0.170.g444d1eabd0-goog From nobody Sat Apr 18 07:34:39 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 2163AC43334 for ; Fri, 15 Jul 2022 19:30:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230190AbiGOTaz (ORCPT ); Fri, 15 Jul 2022 15:30:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60968 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231374AbiGOTaW (ORCPT ); Fri, 15 Jul 2022 15:30:22 -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 4F8977A535 for ; Fri, 15 Jul 2022 12:30:19 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id v19-20020a17090abb9300b001ef7bbd5a28so5716874pjr.0 for ; Fri, 15 Jul 2022 12:30:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=l24GOrhB5xiwS9IYXc6IUpo/wNM5CtXC5pw4kqBO/F8=; b=NS8cvYntg+A8Lq5E/eFY/ZLlr/sy4y7KNe14ARQH/Sy81wod+1GFs9+ogPf1vBH7IK fN65cCoKsGv1I1APr8VCS0AX5ZDj4iWMD5z2QOZUbN/EgWP1KqEA5jZuzlWMhuKlU0P6 g5J8U/ankGFcnIDMvWjyWS+R8d8vplO1rInihVmj2AV2WJNI5a/YL8S+VLym19LbjzYT sE8j8neuQGC3JaLhXevjdcg9yYNVHXR68MOmYTwk3jPTyB5hpHpWUpfUYX4Tg4sPzKuh aDWPLJy6cWQibtHRf2xmGFBPpwZdS0YG601gZAelDLg1pnCpYciHbZUBhmCNzUKwfLBY 2tHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=l24GOrhB5xiwS9IYXc6IUpo/wNM5CtXC5pw4kqBO/F8=; b=y0z85ZxhaKDMBb8eh39qVAanUdmYeVOglckFl8QtNTxg/pB09zZZZKm+8BTXKlM2S7 iSR5JjkXOuUUotsKyQaZuTQm5sjYM+EXtS2paqRrBtZiA9oBjFovpEad+TRcEWzVkNZO bglHCmwpnUYMsMriISME5b+K3Rq7qHBiI8bP+x158j/JI1fvXzpRpx8Ks4wZ96kU2wzp NS7cgHLi9R/XViHKmKMNMzdiC/qEgng/MfcltHJ5g7eYQ12F8Mf9llCalcuob2BiSbMC 2OMmblY13T7VtUwhh8J57wTCPUZj/hS8co8xyJpDJI0qvMGu71eWBGbbdKONo05C2Gof nyXg== X-Gm-Message-State: AJIora+BcSnnyJC1RqG/QzvHf14hMK6KgiKeJ0u1LSl/O/bymVIUPmAT C6tpJPEN1ytcZa4Bf3Er/YHk+BFi9c8= X-Google-Smtp-Source: AGRyM1sfR7RDRlDwpq6mM94EZ6MFAeaZr1g/2HfOKbrYbvfFpYcW8rihI3+WY57o+JVN7EeXPZmM7HpeUC0= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a05:6a00:1ad0:b0:52b:4175:953d with SMTP id f16-20020a056a001ad000b0052b4175953dmr3572157pfv.50.1657913418792; Fri, 15 Jul 2022 12:30:18 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:52 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-8-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [RFC V1 06/10] KVM: selftests: Consolidate boilerplate code in get_ucall() 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, 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: Sean Christopherson Consolidate the actual copying of a ucall struct from guest=3D>host into the common get_ucall(). Return a host virtual address instead of a guest virtual address even though the addr_gva2hva() part could be moved to get_ucall() too. Conceptually, get_ucall() is invoked from the host and should return a host virtual address (and returning NULL for "nothing to see here" is far superior to returning 0). Use pointer shenanigans instead of an unnecessary bounce buffer when the caller of get_ucall() provides a valid pointer. Signed-off-by: Sean Christopherson Signed-off-by: Peter Gonda Reviewed-by: Andrew Jones --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/ucall_common.h | 17 +++++++- .../testing/selftests/kvm/lib/aarch64/ucall.c | 36 ++++------------- .../selftests/kvm/lib/perf_test_util.c | 2 +- tools/testing/selftests/kvm/lib/riscv/ucall.c | 40 ++++--------------- tools/testing/selftests/kvm/lib/s390x/ucall.c | 37 ++++------------- .../testing/selftests/kvm/lib/ucall_common.c | 39 ++++++++++++++++++ .../testing/selftests/kvm/lib/x86_64/ucall.c | 37 ++++------------- 8 files changed, 84 insertions(+), 125 deletions(-) create mode 100644 tools/testing/selftests/kvm/lib/ucall_common.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests= /kvm/Makefile index 4d6753aadfa0..61e85892dd9b 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -46,6 +46,7 @@ LIBKVM +=3D lib/perf_test_util.c LIBKVM +=3D lib/rbtree.c LIBKVM +=3D lib/sparsebit.c LIBKVM +=3D lib/test_util.c +LIBKVM +=3D lib/ucall_common.c =20 LIBKVM_x86_64 +=3D lib/x86_64/apic.c LIBKVM_x86_64 +=3D lib/x86_64/handlers.S diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/tes= ting/selftests/kvm/include/ucall_common.h index 98562f685151..cb9b37282701 100644 --- a/tools/testing/selftests/kvm/include/ucall_common.h +++ b/tools/testing/selftests/kvm/include/ucall_common.h @@ -23,11 +23,24 @@ struct ucall { uint64_t args[UCALL_MAX_ARGS]; }; =20 -void ucall_init(struct kvm_vm *vm, void *arg); -void ucall_uninit(struct kvm_vm *vm); +void ucall_arch_init(struct kvm_vm *vm, void *arg); +void ucall_arch_uninit(struct kvm_vm *vm); +void ucall_arch_do_ucall(vm_vaddr_t uc); +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu); + void ucall(uint64_t cmd, int nargs, ...); uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); =20 +static inline void ucall_init(struct kvm_vm *vm, void *arg) +{ + ucall_arch_init(vm, arg); +} + +static inline void ucall_uninit(struct kvm_vm *vm) +{ + ucall_arch_uninit(vm); +} + #define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4) \ ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4) #define GUEST_SYNC(stage) ucall(UCALL_SYNC, 2, "hello", stage) diff --git a/tools/testing/selftests/kvm/lib/aarch64/ucall.c b/tools/testin= g/selftests/kvm/lib/aarch64/ucall.c index 0b949ee06b5e..9c124adbb560 100644 --- a/tools/testing/selftests/kvm/lib/aarch64/ucall.c +++ b/tools/testing/selftests/kvm/lib/aarch64/ucall.c @@ -21,7 +21,7 @@ static bool ucall_mmio_init(struct kvm_vm *vm, vm_paddr_t= gpa) return true; } =20 -void ucall_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, void *arg) { vm_paddr_t gpa, start, end, step, offset; unsigned int bits; @@ -64,37 +64,20 @@ void ucall_init(struct kvm_vm *vm, void *arg) TEST_FAIL("Can't find a ucall mmio address"); } =20 -void ucall_uninit(struct kvm_vm *vm) +void ucall_arch_uninit(struct kvm_vm *vm) { ucall_exit_mmio_addr =3D 0; sync_global_to_guest(vm, ucall_exit_mmio_addr); } =20 -void ucall(uint64_t cmd, int nargs, ...) +void ucall_arch_do_ucall(vm_vaddr_t uc) { - struct ucall uc =3D { - .cmd =3D cmd, - }; - va_list va; - int i; - - nargs =3D min(nargs, UCALL_MAX_ARGS); - - va_start(va, nargs); - for (i =3D 0; i < nargs; ++i) - uc.args[i] =3D va_arg(va, uint64_t); - va_end(va); - - *ucall_exit_mmio_addr =3D (vm_vaddr_t)&uc; + *ucall_exit_mmio_addr =3D uc; } =20 -uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) { struct kvm_run *run =3D vcpu->run; - struct ucall ucall =3D {}; - - if (uc) - memset(uc, 0, sizeof(*uc)); =20 if (run->exit_reason =3D=3D KVM_EXIT_MMIO && run->mmio.phys_addr =3D=3D (uint64_t)ucall_exit_mmio_addr) { @@ -103,12 +86,7 @@ uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall = *uc) TEST_ASSERT(run->mmio.is_write && run->mmio.len =3D=3D 8, "Unexpected ucall exit mmio address access"); memcpy(&gva, run->mmio.data, sizeof(gva)); - memcpy(&ucall, addr_gva2hva(vcpu->vm, gva), sizeof(ucall)); - - vcpu_run_complete_io(vcpu); - if (uc) - memcpy(uc, &ucall, sizeof(ucall)); + return addr_gva2hva(vcpu->vm, gva); } - - return ucall.cmd; + return NULL; } diff --git a/tools/testing/selftests/kvm/lib/perf_test_util.c b/tools/testi= ng/selftests/kvm/lib/perf_test_util.c index 9618b37c66f7..14f88f3ffa80 100644 --- a/tools/testing/selftests/kvm/lib/perf_test_util.c +++ b/tools/testing/selftests/kvm/lib/perf_test_util.c @@ -209,7 +209,7 @@ struct kvm_vm *perf_test_create_vm(enum vm_guest_mode m= ode, int nr_vcpus, perf_test_setup_nested(vm, nr_vcpus, vcpus); } =20 - ucall_init(vm, NULL); + ucall_arch_init(vm, NULL); =20 /* Export the shared variables to the guest. */ sync_global_to_guest(vm, perf_test_args); diff --git a/tools/testing/selftests/kvm/lib/riscv/ucall.c b/tools/testing/= selftests/kvm/lib/riscv/ucall.c index 087b9740bc8f..37e091d4366e 100644 --- a/tools/testing/selftests/kvm/lib/riscv/ucall.c +++ b/tools/testing/selftests/kvm/lib/riscv/ucall.c @@ -10,11 +10,11 @@ #include "kvm_util.h" #include "processor.h" =20 -void ucall_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, void *arg) { } =20 -void ucall_uninit(struct kvm_vm *vm) +void ucall_arch_uninit(struct kvm_vm *vm) { } =20 @@ -44,47 +44,22 @@ struct sbiret sbi_ecall(int ext, int fid, unsigned long= arg0, return ret; } =20 -void ucall(uint64_t cmd, int nargs, ...) +void ucall_arch_do_ucall(vm_vaddr_t uc) { - struct ucall uc =3D { - .cmd =3D cmd, - }; - va_list va; - int i; - - nargs =3D min(nargs, UCALL_MAX_ARGS); - - va_start(va, nargs); - for (i =3D 0; i < nargs; ++i) - uc.args[i] =3D va_arg(va, uint64_t); - va_end(va); - sbi_ecall(KVM_RISCV_SELFTESTS_SBI_EXT, KVM_RISCV_SELFTESTS_SBI_UCALL, - (vm_vaddr_t)&uc, 0, 0, 0, 0, 0); + uc, 0, 0, 0, 0, 0); } =20 -uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) { struct kvm_run *run =3D vcpu->run; - struct ucall ucall =3D {}; - - if (uc) - memset(uc, 0, sizeof(*uc)); =20 if (run->exit_reason =3D=3D KVM_EXIT_RISCV_SBI && run->riscv_sbi.extension_id =3D=3D KVM_RISCV_SELFTESTS_SBI_EXT) { switch (run->riscv_sbi.function_id) { case KVM_RISCV_SELFTESTS_SBI_UCALL: - memcpy(&ucall, - addr_gva2hva(vcpu->vm, run->riscv_sbi.args[0]), - sizeof(ucall)); - - vcpu_run_complete_io(vcpu); - if (uc) - memcpy(uc, &ucall, sizeof(ucall)); - - break; + return addr_gva2hva(vcpu->vm, run->riscv_sbi.args[0]); case KVM_RISCV_SELFTESTS_SBI_UNEXP: vcpu_dump(stderr, vcpu, 2); TEST_ASSERT(0, "Unexpected trap taken by guest"); @@ -93,6 +68,5 @@ uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *u= c) break; } } - - return ucall.cmd; + return NULL; } diff --git a/tools/testing/selftests/kvm/lib/s390x/ucall.c b/tools/testing/= selftests/kvm/lib/s390x/ucall.c index 73dc4e21190f..0f695a031d35 100644 --- a/tools/testing/selftests/kvm/lib/s390x/ucall.c +++ b/tools/testing/selftests/kvm/lib/s390x/ucall.c @@ -6,40 +6,23 @@ */ #include "kvm_util.h" =20 -void ucall_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, void *arg) { } =20 -void ucall_uninit(struct kvm_vm *vm) +void ucall_arch_uninit(struct kvm_vm *vm) { } =20 -void ucall(uint64_t cmd, int nargs, ...) +void ucall_arch_do_ucall(vm_vaddr_t uc) { - struct ucall uc =3D { - .cmd =3D cmd, - }; - va_list va; - int i; - - nargs =3D min(nargs, UCALL_MAX_ARGS); - - va_start(va, nargs); - for (i =3D 0; i < nargs; ++i) - uc.args[i] =3D va_arg(va, uint64_t); - va_end(va); - /* Exit via DIAGNOSE 0x501 (normally used for breakpoints) */ - asm volatile ("diag 0,%0,0x501" : : "a"(&uc) : "memory"); + asm volatile ("diag 0,%0,0x501" : : "a"(uc) : "memory"); } =20 -uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) { struct kvm_run *run =3D vcpu->run; - struct ucall ucall =3D {}; - - if (uc) - memset(uc, 0, sizeof(*uc)); =20 if (run->exit_reason =3D=3D KVM_EXIT_S390_SIEIC && run->s390_sieic.icptcode =3D=3D 4 && @@ -47,13 +30,7 @@ uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *= uc) (run->s390_sieic.ipb >> 16) =3D=3D 0x501) { int reg =3D run->s390_sieic.ipa & 0xf; =20 - memcpy(&ucall, addr_gva2hva(vcpu->vm, run->s.regs.gprs[reg]), - sizeof(ucall)); - - vcpu_run_complete_io(vcpu); - if (uc) - memcpy(uc, &ucall, sizeof(ucall)); + return addr_gva2hva(vcpu->vm, run->s.regs.gprs[reg]); } - - return ucall.cmd; + return NULL; } diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing= /selftests/kvm/lib/ucall_common.c new file mode 100644 index 000000000000..c488ed23d0dd --- /dev/null +++ b/tools/testing/selftests/kvm/lib/ucall_common.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include "kvm_util.h" + +void ucall(uint64_t cmd, int nargs, ...) +{ + struct ucall uc =3D { + .cmd =3D cmd, + }; + va_list va; + int i; + + nargs =3D min(nargs, UCALL_MAX_ARGS); + + va_start(va, nargs); + for (i =3D 0; i < nargs; ++i) + uc.args[i] =3D va_arg(va, uint64_t); + va_end(va); + + ucall_arch_do_ucall((vm_vaddr_t)&uc); +} + +uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +{ + struct ucall ucall; + void *addr; + + if (!uc) + uc =3D &ucall; + + addr =3D ucall_arch_get_ucall(vcpu); + if (addr) { + memcpy(uc, addr, sizeof(*uc)); + vcpu_run_complete_io(vcpu); + } else { + memset(uc, 0, sizeof(*uc)); + } + + return uc->cmd; +} diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing= /selftests/kvm/lib/x86_64/ucall.c index e5f0f9e0d3ee..ec53a406f689 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/ucall.c +++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c @@ -8,52 +8,29 @@ =20 #define UCALL_PIO_PORT ((uint16_t)0x1000) =20 -void ucall_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, void *arg) { } =20 -void ucall_uninit(struct kvm_vm *vm) +void ucall_arch_uninit(struct kvm_vm *vm) { } =20 -void ucall(uint64_t cmd, int nargs, ...) +void ucall_arch_do_ucall(vm_vaddr_t uc) { - struct ucall uc =3D { - .cmd =3D cmd, - }; - va_list va; - int i; - - nargs =3D min(nargs, UCALL_MAX_ARGS); - - va_start(va, nargs); - for (i =3D 0; i < nargs; ++i) - uc.args[i] =3D va_arg(va, uint64_t); - va_end(va); - asm volatile("in %[port], %%al" - : : [port] "d" (UCALL_PIO_PORT), "D" (&uc) : "rax", "memory"); + : : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax", "memory"); } =20 -uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) { struct kvm_run *run =3D vcpu->run; - struct ucall ucall =3D {}; - - if (uc) - memset(uc, 0, sizeof(*uc)); =20 if (run->exit_reason =3D=3D KVM_EXIT_IO && run->io.port =3D=3D UCALL_PIO_= PORT) { struct kvm_regs regs; =20 vcpu_regs_get(vcpu, ®s); - memcpy(&ucall, addr_gva2hva(vcpu->vm, (vm_vaddr_t)regs.rdi), - sizeof(ucall)); - - vcpu_run_complete_io(vcpu); - if (uc) - memcpy(uc, &ucall, sizeof(ucall)); + return addr_gva2hva(vcpu->vm, (vm_vaddr_t)regs.rdi); } - - return ucall.cmd; + return NULL; } --=20 2.37.0.170.g444d1eabd0-goog From nobody Sat Apr 18 07:34:39 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 E9EF0C433EF for ; Fri, 15 Jul 2022 19:31:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231393AbiGOTbI (ORCPT ); Fri, 15 Jul 2022 15:31:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32982 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231397AbiGOTaZ (ORCPT ); Fri, 15 Jul 2022 15:30:25 -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 C53C9655BA for ; Fri, 15 Jul 2022 12:30:21 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-31c972f5f84so46616947b3.1 for ; Fri, 15 Jul 2022 12:30:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=TAzWPzxWt/xQfClUKSK8iVRAelG3qw/M2QmSChpgMSI=; b=YNM9JNlWqYCDiOo3N8HlI4kB6O7IiOnhbpDLU5h7U/5DOLcS/NETWbGtl2M5UsAjeU 5FQs1H/BQZETak+scuHq+3xxRENuOnxo3ZmnHKeUYLxlRlA94cNAd8IT2pFoqRcmPIKK 0o+27bCLWXWn2JJ0w10g5lPDoerBxd2qYVjX8W0aAkiNCeA7OC53VkZo84reYKvo98vM +KGohTOxpTC1z0XG4DcXsZCENDMLVxCcONr7EYF+BTbtMzbe1cGhG0onOvPAgH4QM+Yv 3hRGC/jitECNYZz7Ls9gWgR4kWwNkm+YYB2DCJSIhRyYrHMrRKHDe0Hw3hqv6da++U02 Ytaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=TAzWPzxWt/xQfClUKSK8iVRAelG3qw/M2QmSChpgMSI=; b=zynYa+f4ecMhl+WafiyDmRP/KPMtyG2VuFPaUtsBh+Y6VkRO+1Qy3ghyP6vWnhRrLZ PU1jlPTLejai8gIQuv0gS4w1PkR0oJQksPctTA0wWFehCTuqv70EJ5RjpXR8ptLEy56C YPVjRVJ+jzHlIpXpR9SsPblExp9MVDDDnupwWljcjejgdelTrtcsh9hbYIT4HT/PpoHd pojey7vbbiQ5Rn2eN4QPptGYdZ1GSn5xvG2czbpY8q1BRtom8S9cxwWLxnKFZFkUlUMw C6KHN+BTrju26it2DdfnAuLJ/DqqyKvmd8SIp+0agXyQdblc3w2/QZ1WVFmBcyrEOTnA R/Sg== X-Gm-Message-State: AJIora8F0jLzRZEKFVfdhAqMJRkxzredochkaUgyfYPJnU/RWoM2YIBB KlfCQnzHd8I03F69x2kciX1UjsfddT0= X-Google-Smtp-Source: AGRyM1tRj6psVB1GLADfUquHWkwvBdbCnSPQ69Mq1ZfxyCnynBeVXK2A+5crNaMaFlFr3oKyKuVU8aftytc= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a81:6cf:0:b0:31c:913c:144c with SMTP id 198-20020a8106cf000000b0031c913c144cmr17753756ywg.437.1657913420660; Fri, 15 Jul 2022 12:30:20 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:53 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-9-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [RFC V1 07/10] tools: Add atomic_test_and_set_bit() 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, 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" atomic_test_and_set_bit() allows for atomic bitmap usage from KVM selftests. Signed-off-by: Peter Gonda Suggested-by: Sean Christopherson --- tools/arch/x86/include/asm/atomic.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/arch/x86/include/asm/atomic.h b/tools/arch/x86/include/a= sm/atomic.h index 1f5e26aae9fc..45ea15c98957 100644 --- a/tools/arch/x86/include/asm/atomic.h +++ b/tools/arch/x86/include/asm/atomic.h @@ -8,6 +8,7 @@ =20 #define LOCK_PREFIX "\n\tlock; " =20 +#include #include =20 /* @@ -70,4 +71,10 @@ static __always_inline int atomic_cmpxchg(atomic_t *v, i= nt old, int new) return cmpxchg(&v->counter, old, new); } =20 +static inline int atomic_test_and_set_bit(long nr, volatile unsigned long = *addr) +{ + GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(bts), *addr, "Ir", nr, "%0", "c"); + +} + #endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */ --=20 2.37.0.170.g444d1eabd0-goog From nobody Sat Apr 18 07:34:39 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 EEA63C433EF for ; Fri, 15 Jul 2022 19:31:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231277AbiGOTbL (ORCPT ); Fri, 15 Jul 2022 15:31:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231422AbiGOTaj (ORCPT ); Fri, 15 Jul 2022 15:30:39 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6EA19564EE for ; Fri, 15 Jul 2022 12:30:23 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-31cbe6ad44fso47171617b3.10 for ; Fri, 15 Jul 2022 12:30:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=COdHMadNTPd2b3B+OvLKM9tybkT/K06T/ka5jk6HYjE=; b=tko02Rt0sYWe4bCjb5TsQAnEbLcyG/sBmfh1BygatkSMv8t6eZvOoL1s1Q6ICHtPRx Z13OzScGR/rr8aOX94mRafW+BxlTM15aXntiYp8La4TvcjuiKJqKMK4TrztZQmTELly8 xwB70SjBr7gCjHDCKc41cDsCBxi/WVy2NtclvRPGSWQ0ny1iQKkAf//HQJfMvB0ioNmF vH25vWD/RUzTl97uWO7M6d9zuls2XL5v741H+Wvw94xri0usW8Yguf3VzrwckSBbG16C 7sPdT5tw5pORU6FfWmHG/Ls5viXpNYSOoe4nM/AwEIACiQ0DWAL3mEfk7zXmcOLDs2zk keuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=COdHMadNTPd2b3B+OvLKM9tybkT/K06T/ka5jk6HYjE=; b=MD3v7mFANsoO8Zjd6Gr9Zj7yJe3MndGSMjOUfthWUmdZwQAnweVcBPMReEuzfCUfI6 hbHr26NkXAVcuspVDGJS3yIuR/hIl13F8noYUFz648AO9PY8mdkJaqf7ifLqpcNikmtG /qYrdyBW1FRlh9PKU9N84wr8G4EkuDWOAY9gvtd60xtw/hQjPeIiCL7Yuhx1DhPM9ZM6 EsRUPQqwh1nMnevphVEsfNz9AV3AN3BZ+A0F62FGNqkZOcbd1qV5VwbyyO3yIT6xnzqN CEZEq2BHS9fBSHSTfHXvK+zgfI37fRxmzb6yyyPWdOOg/EJy3WL5/Bur1w/gc2jOITrN 2hdw== X-Gm-Message-State: AJIora8bzp/ET5GijWsj6Sf9EUkCZFdHzfQgj9+Wp0EfrHpr1ai6Elr5 Kcm9v+4Y3Tl3YDMELd4LjXhHv7E2pbY= X-Google-Smtp-Source: AGRyM1uhd3d4RndtFJv7njRJsv3SC5wyIxRYzSXAgsbLE1MBtigrcjbpjpHCiU9hNjAq2OzrCZ6hCYUlFWw= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a81:289:0:b0:31c:8b10:fa84 with SMTP id 131-20020a810289000000b0031c8b10fa84mr17244335ywc.8.1657913422541; Fri, 15 Jul 2022 12:30:22 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:54 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-10-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [RFC V1 08/10] KVM: selftests: Make ucall work with encrypted 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, 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 support for encrypted, SEV, guests in the ucall framework. If encryption is enabled set up a pool of ucall structs in the guests' shared memory region. This was suggested in the thread on "[RFC PATCH 00/10] KVM: selftests: Add support for test-selectable ucall implementations". Using a listed as suggested there doesn't work well because the list is setup using HVAs not GVAs so use a bitmap + array solution instead to get the same pool result. Suggested-by:Sean Christopherson Signed-off-by: Peter Gonda --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/kvm_util_base.h | 30 +++-- .../selftests/kvm/include/ucall_common.h | 14 +-- .../testing/selftests/kvm/lib/ucall_common.c | 115 ++++++++++++++++-- .../testing/selftests/kvm/lib/x86_64/ucall.c | 2 +- 5 files changed, 134 insertions(+), 28 deletions(-) diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests= /kvm/Makefile index 61e85892dd9b..3d9f2a017389 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -47,6 +47,7 @@ LIBKVM +=3D lib/rbtree.c LIBKVM +=3D lib/sparsebit.c LIBKVM +=3D lib/test_util.c LIBKVM +=3D lib/ucall_common.c +LIBKVM +=3D $(top_srcdir)/tools/lib/find_bit.c =20 LIBKVM_x86_64 +=3D lib/x86_64/apic.c LIBKVM_x86_64 +=3D lib/x86_64/handlers.S diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/te= sting/selftests/kvm/include/kvm_util_base.h index 60b604ac9fa9..77aff2356d64 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -65,6 +65,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; @@ -99,6 +100,8 @@ struct kvm_vm { int stats_fd; struct kvm_stats_header stats_header; struct kvm_stats_desc *stats_desc; + + struct list_head ucall_list; }; =20 =20 @@ -141,21 +144,21 @@ enum vm_guest_mode { =20 extern enum vm_guest_mode vm_mode_default; =20 -#define VM_MODE_DEFAULT vm_mode_default -#define MIN_PAGE_SHIFT 12U -#define ptes_per_page(page_size) ((page_size) / 8) +#define VM_MODE_DEFAULT vm_mode_default +#define MIN_PAGE_SHIFT 12U +#define ptes_per_page(page_size) ((page_size) / 8) =20 #elif defined(__x86_64__) =20 -#define VM_MODE_DEFAULT VM_MODE_PXXV48_4K -#define MIN_PAGE_SHIFT 12U -#define ptes_per_page(page_size) ((page_size) / 8) +#define VM_MODE_DEFAULT VM_MODE_PXXV48_4K +#define MIN_PAGE_SHIFT 12U +#define ptes_per_page(page_size) ((page_size) / 8) =20 #elif defined(__s390x__) =20 -#define VM_MODE_DEFAULT VM_MODE_P44V64_4K -#define MIN_PAGE_SHIFT 12U -#define ptes_per_page(page_size) ((page_size) / 16) +#define VM_MODE_DEFAULT VM_MODE_P44V64_4K +#define MIN_PAGE_SHIFT 12U +#define ptes_per_page(page_size) ((page_size) / 16) =20 #elif defined(__riscv) =20 @@ -163,9 +166,9 @@ extern enum vm_guest_mode vm_mode_default; #error "RISC-V 32-bit kvm selftests not supported" #endif =20 -#define VM_MODE_DEFAULT VM_MODE_P40V48_4K -#define MIN_PAGE_SHIFT 12U -#define ptes_per_page(page_size) ((page_size) / 8) +#define VM_MODE_DEFAULT VM_MODE_P40V48_4K +#define MIN_PAGE_SHIFT 12U +#define ptes_per_page(page_size) ((page_size) / 8) =20 #endif =20 @@ -802,6 +805,9 @@ 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 gva2* conversions = are not possible."); return addr_arch_gva2gpa(vm, gva); } =20 diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/tes= ting/selftests/kvm/include/ucall_common.h index cb9b37282701..d8ac16a68c0a 100644 --- a/tools/testing/selftests/kvm/include/ucall_common.h +++ b/tools/testing/selftests/kvm/include/ucall_common.h @@ -21,6 +21,10 @@ enum { struct ucall { uint64_t cmd; uint64_t args[UCALL_MAX_ARGS]; + + /* For encrypted guests. */ + uint64_t idx; + struct ucall *hva; }; =20 void ucall_arch_init(struct kvm_vm *vm, void *arg); @@ -31,15 +35,9 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu); void ucall(uint64_t cmd, int nargs, ...); uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); =20 -static inline void ucall_init(struct kvm_vm *vm, void *arg) -{ - ucall_arch_init(vm, arg); -} +void ucall_init(struct kvm_vm *vm, void *arg); =20 -static inline void ucall_uninit(struct kvm_vm *vm) -{ - ucall_arch_uninit(vm); -} +void ucall_uninit(struct kvm_vm *vm); =20 #define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4) \ ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4) diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing= /selftests/kvm/lib/ucall_common.c index c488ed23d0dd..8e660b10f9b2 100644 --- a/tools/testing/selftests/kvm/lib/ucall_common.c +++ b/tools/testing/selftests/kvm/lib/ucall_common.c @@ -1,22 +1,123 @@ // SPDX-License-Identifier: GPL-2.0-only #include "kvm_util.h" +#include "linux/types.h" +#include "linux/bitmap.h" +#include "linux/bitops.h" +#include "linux/atomic.h" + +struct ucall_header { + DECLARE_BITMAP(in_use, KVM_MAX_VCPUS); + struct ucall ucalls[KVM_MAX_VCPUS]; +}; + +static bool encrypted_guest; +static struct ucall_header *ucall_hdr; + +void ucall_init(struct kvm_vm *vm, void *arg) +{ + struct ucall *uc; + struct ucall_header *hdr; + vm_vaddr_t vaddr; + int i; + + encrypted_guest =3D vm->memcrypt.enabled; + sync_global_to_guest(vm, encrypted_guest); + if (!encrypted_guest) + goto out; + + TEST_ASSERT(!ucall_hdr, + "Only a single encrypted guest at a time for ucalls."); + vaddr =3D vm_vaddr_alloc_shared(vm, sizeof(*hdr), vm->page_size); + hdr =3D (struct ucall_header *)addr_gva2hva(vm, vaddr); + memset(hdr, 0, sizeof(*hdr)); + + for (i =3D 0; i < KVM_MAX_VCPUS; ++i) { + uc =3D &hdr->ucalls[i]; + uc->hva =3D uc; + uc->idx =3D i; + } + + ucall_hdr =3D (struct ucall_header *)vaddr; + sync_global_to_guest(vm, ucall_hdr); + +out: + ucall_arch_init(vm, arg); +} + +void ucall_uninit(struct kvm_vm *vm) +{ + encrypted_guest =3D false; + ucall_hdr =3D NULL; + + ucall_arch_uninit(vm); +} + +static struct ucall *ucall_alloc(void) +{ + struct ucall *uc =3D NULL; + int i; + + if (!encrypted_guest) + goto out; + + for (i =3D 0; i < KVM_MAX_VCPUS; ++i) { + if (atomic_test_and_set_bit(i, ucall_hdr->in_use)) + continue; + + uc =3D &ucall_hdr->ucalls[i]; + } + +out: + return uc; +} + +static void ucall_free(struct ucall *uc) +{ + if (!encrypted_guest) + return; + + clear_bit(uc->idx, ucall_hdr->in_use); +} + +static vm_vaddr_t get_ucall_addr(struct ucall *uc) +{ + if (encrypted_guest) + return (vm_vaddr_t)uc->hva; + + return (vm_vaddr_t)uc; +} =20 void ucall(uint64_t cmd, int nargs, ...) { - struct ucall uc =3D { - .cmd =3D cmd, - }; + struct ucall *uc; + struct ucall tmp; va_list va; int i; =20 + uc =3D ucall_alloc(); + if (!uc) + uc =3D &tmp; + + uc->cmd =3D cmd; + nargs =3D min(nargs, UCALL_MAX_ARGS); =20 va_start(va, nargs); for (i =3D 0; i < nargs; ++i) - uc.args[i] =3D va_arg(va, uint64_t); + uc->args[i] =3D va_arg(va, uint64_t); va_end(va); =20 - ucall_arch_do_ucall((vm_vaddr_t)&uc); + ucall_arch_do_ucall(get_ucall_addr(uc)); + + ucall_free(uc); +} + +void *get_ucall_hva(struct kvm_vm *vm, void *uc) +{ + if (encrypted_guest) + return uc; + + return addr_gva2hva(vm, (vm_vaddr_t)uc); } =20 uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) @@ -27,9 +128,9 @@ uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *= uc) if (!uc) uc =3D &ucall; =20 - addr =3D ucall_arch_get_ucall(vcpu); + addr =3D get_ucall_hva(vcpu->vm, ucall_arch_get_ucall(vcpu)); if (addr) { - memcpy(uc, addr, sizeof(*uc)); + memcpy(uc, addr, sizeof(struct ucall)); vcpu_run_complete_io(vcpu); } else { memset(uc, 0, sizeof(*uc)); diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing= /selftests/kvm/lib/x86_64/ucall.c index ec53a406f689..ea6b2e3a8e39 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/ucall.c +++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c @@ -30,7 +30,7 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) struct kvm_regs regs; =20 vcpu_regs_get(vcpu, ®s); - return addr_gva2hva(vcpu->vm, (vm_vaddr_t)regs.rdi); + return (void *)regs.rdi; } return NULL; } --=20 2.37.0.170.g444d1eabd0-goog From nobody Sat Apr 18 07:34:39 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 7C0E6C433EF for ; Fri, 15 Jul 2022 19:31:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230385AbiGOTbR (ORCPT ); Fri, 15 Jul 2022 15:31:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33656 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231321AbiGOTao (ORCPT ); Fri, 15 Jul 2022 15:30:44 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 823107AC3F for ; Fri, 15 Jul 2022 12:30:25 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id e5-20020a636905000000b004119d180b54so3141040pgc.14 for ; Fri, 15 Jul 2022 12:30:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=c0WLAWJ/JHTc12KE1JC2Mapz7KoyyjIul983cVCdPl0=; b=Q/y7Y9sl79/wNJdtafMAakPqWiQbeht6fmos3JpLzyPoem57cZyWM3h6lhGkLxMVwA dZp+tmrnoKDFX93ruuPdxySkifQLg8s6m+BjWoTvLlhpiO7RS3J7IigM1krG/g2+iqay LypzJmnGstp9NVGIzMRHkPPAxm0rtfgzbnncmzEI6lbp7I+L6+67qdSv7U69P4f2xMvQ LlriLGlDJECq+1Sm7Np+x9eUTHfNBxKw6iZnYN/2Fg+jBlNmmq4jpX/r8hK8HAKvAHOl lqrrsamtjNPQoqQAdAPnc2bZK1f4AZ4mf8AhCQqvCduhDclpT1aTbbcZI18wp5TO37/0 Y7CA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=c0WLAWJ/JHTc12KE1JC2Mapz7KoyyjIul983cVCdPl0=; b=POdjUukp11S4QUjOB4ENAYizeEmt6QPRd4Y1A/++3FZPRyeeiyliI2lc8k+W3dywjN RHSIohrildI4lOcXqe2wJpcdWBn/Zj+V0DyvQvV6LDs7k8Yfgzpin5wn1GYc6/tfqbo4 3+qP2rTinhcAQtkTFi0WLFJgbPkXP8RtZHg8Vpwu3DG0/J11AFMSF1MLc8KQIjSKvY/l 85V784WFvIN1E55ozfmmQfNKSOPWPw2t4/7GwzSlFLP4MusuFvTJbaAFr1gQ4qS25Cij B1ciCjXWR0KTqnRxrgFu5spmSUINMkNKVJ5vGgDY1iO2AbzURSHZHahq+jF7UQJSIJXB kqrQ== X-Gm-Message-State: AJIora++lQZFM/uDWr0ZpR3DK6qMy9cG7pTGV7MMulf7J37l/QyXu+/M rmWeMF2Qfaf7Vc2wU4NY6RtU2NTlYvQ= X-Google-Smtp-Source: AGRyM1taUcCSrW6S8Nf8/IdGa+CU5/drA9ttvNwnqQCinv3tc17QFocUXJ70wm0w9eTlWpnmqorCOgK5d4E= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a17:902:f693:b0:16c:d5da:1be4 with SMTP id l19-20020a170902f69300b0016cd5da1be4mr669614plg.114.1657913424504; Fri, 15 Jul 2022 12:30:24 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:55 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-11-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [RFC V1 09/10] 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, 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 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. Signed-off-by: Michael Roth Signed-off-by: Peter Gonda --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/x86_64/sev.h | 44 +++ tools/testing/selftests/kvm/lib/x86_64/sev.c | 251 ++++++++++++++++++ 3 files changed, 296 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 3d9f2a017389..f3f29a64e4b2 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/x86_64/sev.h b/tools/testi= ng/selftests/kvm/include/x86_64/sev.h new file mode 100644 index 000000000000..2f7f7c741b12 --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/sev.h @@ -0,0 +1,44 @@ +/* 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_GSTATE_UNINIT =3D 0, + SEV_GSTATE_LUPDATE, + SEV_GSTATE_LSECRET, + SEV_GSTATE_RUNNING, +}; + +struct sev_vm; + +void kvm_sev_ioctl(struct sev_vm *sev, int cmd, void *data); +struct kvm_vm *sev_get_vm(struct sev_vm *sev); +uint8_t sev_get_enc_bit(struct sev_vm *sev); + +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..309467cd7501 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86_64/sev.c @@ -0,0 +1,251 @@ +// 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 PAGE_SHIFT 12 + +struct sev_vm { + struct kvm_vm *vm; + int fd; + int enc_bit; + uint32_t sev_policy; +}; + +/* Common SEV helpers/accessors. */ + +struct kvm_vm *sev_get_vm(struct sev_vm *sev) +{ + return sev->vm; +} + +uint8_t sev_get_enc_bit(struct sev_vm *sev) +{ + return sev->enc_bit; +} + +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, uint64_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; + + /* Only memslot 0 supported for now. */ + enc_phy_pages =3D vm_get_encrypted_phy_pages(sev->vm, 0, &gpa_start, &mem= ory_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 =3D {0}; + 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. */ + eax =3D 0x8000001f; + ecx =3D 0; + cpuid(&eax, &ebx, &ecx, &edx); + sev->enc_bit =3D ebx & 0x3F; + + return sev; +} + +void sev_vm_free(struct sev_vm *sev) +{ + ucall_uninit(sev->vm); + 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 =3D {0}; + + /* Need to use ucall_shared for synchronization. */ + //ucall_init_ops(sev_get_vm(sev), NULL, &ucall_ops_halt); + + 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, NULL); + + sev_encrypt(sev); +} + +void sev_vm_launch_measure(struct sev_vm *sev, uint8_t *measurement) +{ + struct kvm_sev_launch_measure ksev_launch_measure =3D {0}; + struct kvm_sev_guest_status ksev_guest_status =3D {0}; + + 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 =3D {0}; + + 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.0.170.g444d1eabd0-goog From nobody Sat Apr 18 07:34:39 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 D4002C433EF for ; Fri, 15 Jul 2022 19:31:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231226AbiGOTb3 (ORCPT ); Fri, 15 Jul 2022 15:31:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60662 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231400AbiGOTbI (ORCPT ); Fri, 15 Jul 2022 15:31:08 -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 D52FB7C1BA for ; Fri, 15 Jul 2022 12:30:29 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id 9-20020a631449000000b00412b1418c79so3146878pgu.2 for ; Fri, 15 Jul 2022 12:30:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=kD3cN2eYPx1hQzZPSpXzB0RRo1/KfV2Nfxd7Euk7Vec=; b=dcUOCy6GITc6WOkFigRp6EzkCpSL5Wka5Yk25WkygHmlQOwYw29mlycrtTgPYTOD2d jXBxvJYMEDPy3k+gqHPjsjWQPNNY7Gx2/lHU09ouIHG9zRgUCZlV5jpBBAhd4y4ztnaL JrESV7bxVR1b/EB46JE7ZelrY+oSnYm7x65R/pKtxO1EQEnefGZuuf5UJWXtzA4DFc4M xsbNlr0Sy9joYwwtN/nZz7hE+Ns9/I1rWYW+us5vbb6n98wpAEXwlnqNgsge5Pb86I6y jxDZKnbRDAuOY4y+wA77N+2gtW616XCakNhW9c6L9K4NcqRpjN7+XQKW3r5eQwjhzfqT q+vQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=kD3cN2eYPx1hQzZPSpXzB0RRo1/KfV2Nfxd7Euk7Vec=; b=bLaGAW2eXTX/zSnQJ1SCPLo1u9YHs5REMfbZ8f2IQ85knAno9DQJldp2f9X/jmO5yi nhbZuC8MHSqQrpffU4dl/gVET6+CX8XoQGXvektG92R3+KQXJYMjwCQxU31MUoUrOIxr LVZ9T1AtLsmhwlbEXsI9m/gMgZALXhG6FU2PWHrI2FMSAyqJJEJY6lzmT3qTeLNXlPFf HnigicpDiTJahsSM7D1omncCrIhvqwaLIwd+Wi5QbDdYeJdw2TcdpAvKE47prKtwzNpp LUARxp8C9GB8+4zoTogk9dkqr/pQF9przjb7lCy2n6mNAo0bxcrmrapGM2FAJaucQ3LB rp6g== X-Gm-Message-State: AJIora/UkebYQwz1fepntnLuhUMyFonAQmz7s1rwRfK797RJPZJS9zKw 7uibt5MhQg0BXLjVY71Jlap3cSJfzpc= X-Google-Smtp-Source: AGRyM1vbIEF6fwL/9XXNLUlwNtvb3MAHzJ7BMwrcLgCSeZqcjyjEQVgjkdh3ev4KI5kSuJwJzVswyWbEC7k= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a05:6a00:3498:b0:52a:f8f4:ca7c with SMTP id cp24-20020a056a00349800b0052af8f4ca7cmr15610136pfb.5.1657913426164; Fri, 15 Jul 2022 12:30:26 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:56 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-12-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [RFC V1 10/10] 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, 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 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. Signed-off-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 | 134 ++++++++++++++++++ 3 files changed, 136 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 f44ebf401310..ec084a61a819 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -34,6 +34,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 f3f29a64e4b2..2b89e6bcb5b0 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..222ce41d6f68 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/sev_all_boot_test.c @@ -0,0 +1,134 @@ +// 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 VCPU_ID 2 +#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 __attribute__((__flatten__)) +guest_sev_code(void) +{ + uint32_t eax, ebx, ecx, edx; + uint64_t sev_status; + + GUEST_SYNC(1); + + eax =3D 0x8000001f; + ecx =3D 0; + cpuid(&eax, &ebx, &ecx, &edx); + GUEST_ASSERT(eax & (1 << 1)); + + 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 **vcp= u) +{ + uint8_t measurement[512]; + struct sev_vm *sev; + struct kvm_vm *vm; + int i; + + sev =3D sev_vm_create(policy, TOTAL_PAGES); + if (!sev) + return NULL; + vm =3D sev_get_vm(sev); + + /* Set up VCPU and initial guest kernel. */ + *vcpu =3D vm_vcpu_add(vm, VCPU_ID, 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); + if (!sev) + return; + + /* 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.0.170.g444d1eabd0-goog From nobody Sat Apr 18 07:34:39 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 DF529CCA480 for ; Fri, 15 Jul 2022 19:30:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231244AbiGOTaL (ORCPT ); Fri, 15 Jul 2022 15:30:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60494 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231243AbiGOTaI (ORCPT ); Fri, 15 Jul 2022 15:30:08 -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 3FB2A14D36 for ; Fri, 15 Jul 2022 12:30:07 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id x16-20020a17090ab01000b001f06332d7cfso5688838pjq.3 for ; Fri, 15 Jul 2022 12:30:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=i/SNdAfUk64D/RxNbdNG84VHTcos/SfQ4XEjfo9d3YU=; b=GIO9BhruH3LIpY/Zea8l81ccU4IDmV9rzZnA7dvgO7W6nafy51RiZxJo7KhYDyOUEv +YXqh0O9wFFwqFGLGKN+QFxsJH7LxZ0FpeocjWu+sGFjFAkNkX3vovDXYenLLG/ZCeKU YV4zhHYXWM2+gtuv5qVe7OlWqXMqyJj9OafRJjCKvARTSOtdbqZ5LWrkDxsA3yRtZ2ut uGVa23PFSvVaziCq11ZRnF0R4TvzMEx9PMys5F9YJo0N4ZRlF+3h918hXbScxGNEOAbS hcmUYpXecl1NgBkwty2vcjAxsvVfyQJFNy9iBv79uYCNS0/vNSVjQvsOB92wVM2yLD8l Mceg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=i/SNdAfUk64D/RxNbdNG84VHTcos/SfQ4XEjfo9d3YU=; b=oyFwFP/rua8c2jv2GbVobGzPXxHJzb4Q1hHOwNNPbva0svGo1VF4yClMlHDagSNZds yXxlFq8p5Njn7ENWjDEramlL2toJO5rTMEHxKohbgC509CRCfGhi1Brb4hZ08ZZg0VJp Kw8l903dp92CSZ2ADsokRdGuo2TI7w/hRYtnxD7DxaW7lj4C+5c01to0bm/MwUaHVxDq 5d8Z+YSGCiUvsZyzDRF28cI5o8wXySTE89XK7FjLI+Vd7bGdKoWJlrybIl/iA6Nar4Ms ABSglak/TMiIAhoTYeX0rqyxtpAfUPR65v7vGbjEg808qlwrNmrcHNun+xA9PePkT0W9 KT4w== X-Gm-Message-State: AJIora/ONh36Zgu70GsMX21iVFiCBPC3mxj6I33VVRvJ0H1uVwTFLa5b BDOpWI4/Q4n3crkQlWLlZA3Hd3HhszA= X-Google-Smtp-Source: AGRyM1ucQOxDPQQqnhPTOZKAyy7maDKwTgvQAXn9qfcGo6mrLBrJing2NLMwfJYvq8fiEQWs7K9Rd+4kHE4= X-Received: from pgonda1.kir.corp.google.com ([2620:15c:29:203:bd4e:b81d:4780:497d]) (user=pgonda job=sendgmr) by 2002:a63:455a:0:b0:412:9855:64eb with SMTP id u26-20020a63455a000000b00412985564ebmr13789376pgk.131.1657913406759; Fri, 15 Jul 2022 12:30:06 -0700 (PDT) Date: Fri, 15 Jul 2022 12:29:46 -0700 In-Reply-To: <20220715192956.1873315-1-pgonda@google.com> Message-Id: <20220715192956.1873315-2-pgonda@google.com> Mime-Version: 1.0 References: <20220715192956.1873315-1-pgonda@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [PATCH V2] 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 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 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. Signed-off-by: Michael Roth --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/x86_64/sev_all_boot_test.c | 134 ++++++++++++++++++ 3 files changed, 136 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 f44ebf401310..ec084a61a819 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -34,6 +34,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 f3f29a64e4b2..2b89e6bcb5b0 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..222ce41d6f68 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/sev_all_boot_test.c @@ -0,0 +1,134 @@ +// 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 VCPU_ID 2 +#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 __attribute__((__flatten__)) +guest_sev_code(void) +{ + uint32_t eax, ebx, ecx, edx; + uint64_t sev_status; + + GUEST_SYNC(1); + + eax =3D 0x8000001f; + ecx =3D 0; + cpuid(&eax, &ebx, &ecx, &edx); + GUEST_ASSERT(eax & (1 << 1)); + + 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 **vcp= u) +{ + uint8_t measurement[512]; + struct sev_vm *sev; + struct kvm_vm *vm; + int i; + + sev =3D sev_vm_create(policy, TOTAL_PAGES); + if (!sev) + return NULL; + vm =3D sev_get_vm(sev); + + /* Set up VCPU and initial guest kernel. */ + *vcpu =3D vm_vcpu_add(vm, VCPU_ID, 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); + if (!sev) + return; + + /* 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.0.170.g444d1eabd0-goog