From nobody Wed Apr 29 00:43:01 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 3F100C433F5 for ; Thu, 26 May 2022 17:54:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348372AbiEZRyT (ORCPT ); Thu, 26 May 2022 13:54:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50114 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343642AbiEZRyO (ORCPT ); Thu, 26 May 2022 13:54:14 -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 0DA5F9EB44 for ; Thu, 26 May 2022 10:54:14 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id a23-20020a656557000000b003fa608197b9so1134310pgw.8 for ; Thu, 26 May 2022 10:54:14 -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=9wfIV9ktdtuy1sicWR+vMg0zPdgp8Sw4DeDOVy/L0Xg=; b=Cg2crwEdced9xr0sM9fAF9uCE6L9kxXQ1mBZfPsygwupWi1/Ykuua/+KmvwcAQ9FKt 3reJkQvmwAkXBdoojDTnY4U2cAydb30wE7MvWOXOLDzf7LjbgNrNTTPfM7kFSYd+S9mo 4VgABdhyN41ymfgFbFDD0q3AI3N5Jl123r0zdwUhWv4n47NR8aKznVO6OzJ0JF1stTCe 9knB2NYxrz0EmWtnm9R/ch1eWybZGgIQz5dY7h0lPRgGQ/nxOS2vO+yQb/SjcZvGR714 8MsG9s2M/n3hFPHLKju0epIGcu4FCNE3/zRMQ+ecNqEqnHAxeomcXZBlAxzvwsy3KQAi 4H5w== 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=9wfIV9ktdtuy1sicWR+vMg0zPdgp8Sw4DeDOVy/L0Xg=; b=CpaW2H916VGBSX+JdjzFfgjZu8GyUoboYgBNEAD0y5JOMRP9UfKpq++jkF96kKhziX 4Cvufoemm8UmqXRNXsCk97UktFeBHnj4uqI7MIeaAc9PznRf3wrnC3ITy5c9aX0xCCCi qSfXaOzRxvXbrMflN9wUM+XgqRhiOikmpdcJcsMeawL0btbNoHFWKK6bCrrpt+rhYUeq Hk2DfzrRstoiFkFGWuZ2e3K7fSb8VfjweD6Z7K3pbKVTl6mMGXj9GVaL1FKftZ652ZuY TOn3eKlVgjydh+gey5LUnO1c+4gPz0DWCbjs6MNk/PUXXDMU2jjKbtVJC5ZcSIu5v9/3 vLUQ== X-Gm-Message-State: AOAM530eBRivk5e1IBwV6TJdr6xaDutB8MWy8wQ9Wd9vtgx4+5GDHZ3W iEwVmlXvuRxl+RtHsMOVrZxZ/aQrmri3 X-Google-Smtp-Source: ABdhPJwPEUSDh9zmbiYVgnxInr7tNS6kaDSzP6NbCxilAhFD4Oe5zcxZDSHVsw2MoKvzG4i4StEp2OJ3c/uZ X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a17:90b:4a51:b0:1df:7617:bcfb with SMTP id lb17-20020a17090b4a5100b001df7617bcfbmr3806835pjb.207.1653587653576; Thu, 26 May 2022 10:54:13 -0700 (PDT) Date: Thu, 26 May 2022 17:53:58 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-2-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 01/11] KVM: selftests: Remove dynamic memory allocation for stats header From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" There's no need to allocate dynamic memory for the stats header since its size is known at compile time. Reviewed-by: David Matlack Reviewed-by: Peter Xu Signed-off-by: Ben Gardon --- .../selftests/kvm/kvm_binary_stats_test.c | 58 +++++++++---------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/te= sting/selftests/kvm/kvm_binary_stats_test.c index 17f65d514915..dad34d8a41fe 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -26,56 +26,53 @@ static void stats_test(int stats_fd) int i; size_t size_desc; size_t size_data =3D 0; - struct kvm_stats_header *header; + struct kvm_stats_header header; char *id; struct kvm_stats_desc *stats_desc; u64 *stats_data; struct kvm_stats_desc *pdesc; =20 /* Read kvm stats header */ - header =3D malloc(sizeof(*header)); - TEST_ASSERT(header, "Allocate memory for stats header"); - - ret =3D read(stats_fd, header, sizeof(*header)); - TEST_ASSERT(ret =3D=3D sizeof(*header), "Read stats header"); - size_desc =3D sizeof(*stats_desc) + header->name_size; + ret =3D read(stats_fd, &header, sizeof(header)); + TEST_ASSERT(ret =3D=3D sizeof(header), "Read stats header"); + size_desc =3D sizeof(*stats_desc) + header.name_size; =20 /* Read kvm stats id string */ - id =3D malloc(header->name_size); + id =3D malloc(header.name_size); TEST_ASSERT(id, "Allocate memory for id string"); - ret =3D read(stats_fd, id, header->name_size); - TEST_ASSERT(ret =3D=3D header->name_size, "Read id string"); + ret =3D read(stats_fd, id, header.name_size); + TEST_ASSERT(ret =3D=3D header.name_size, "Read id string"); =20 /* Check id string, that should start with "kvm" */ - TEST_ASSERT(!strncmp(id, "kvm", 3) && strlen(id) < header->name_size, + TEST_ASSERT(!strncmp(id, "kvm", 3) && strlen(id) < header.name_size, "Invalid KVM stats type, id: %s", id); =20 /* Sanity check for other fields in header */ - if (header->num_desc =3D=3D 0) { + if (header.num_desc =3D=3D 0) { printf("No KVM stats defined!"); return; } /* Check overlap */ - TEST_ASSERT(header->desc_offset > 0 && header->data_offset > 0 - && header->desc_offset >=3D sizeof(*header) - && header->data_offset >=3D sizeof(*header), + TEST_ASSERT(header.desc_offset > 0 && header.data_offset > 0 + && header.desc_offset >=3D sizeof(header) + && header.data_offset >=3D sizeof(header), "Invalid offset fields in header"); - TEST_ASSERT(header->desc_offset > header->data_offset || - (header->desc_offset + size_desc * header->num_desc <=3D - header->data_offset), + TEST_ASSERT(header.desc_offset > header.data_offset || + (header.desc_offset + size_desc * header.num_desc <=3D + header.data_offset), "Descriptor block is overlapped with data block"); =20 /* Allocate memory for stats descriptors */ - stats_desc =3D calloc(header->num_desc, size_desc); + stats_desc =3D calloc(header.num_desc, size_desc); TEST_ASSERT(stats_desc, "Allocate memory for stats descriptors"); /* Read kvm stats descriptors */ ret =3D pread(stats_fd, stats_desc, - size_desc * header->num_desc, header->desc_offset); - TEST_ASSERT(ret =3D=3D size_desc * header->num_desc, + size_desc * header.num_desc, header.desc_offset); + TEST_ASSERT(ret =3D=3D size_desc * header.num_desc, "Read KVM stats descriptors"); =20 /* Sanity check for fields in descriptors */ - for (i =3D 0; i < header->num_desc; ++i) { + for (i =3D 0; i < header.num_desc; ++i) { pdesc =3D (void *)stats_desc + i * size_desc; /* Check type,unit,base boundaries */ TEST_ASSERT((pdesc->flags & KVM_STATS_TYPE_MASK) @@ -104,7 +101,7 @@ static void stats_test(int stats_fd) break; } /* Check name string */ - TEST_ASSERT(strlen(pdesc->name) < header->name_size, + TEST_ASSERT(strlen(pdesc->name) < header.name_size, "KVM stats name(%s) too long", pdesc->name); /* Check size field, which should not be zero */ TEST_ASSERT(pdesc->size, "KVM descriptor(%s) with size of 0", @@ -124,14 +121,14 @@ static void stats_test(int stats_fd) size_data +=3D pdesc->size * sizeof(*stats_data); } /* Check overlap */ - TEST_ASSERT(header->data_offset >=3D header->desc_offset - || header->data_offset + size_data <=3D header->desc_offset, + TEST_ASSERT(header.data_offset >=3D header.desc_offset + || header.data_offset + size_data <=3D header.desc_offset, "Data block is overlapped with Descriptor block"); /* Check validity of all stats data size */ - TEST_ASSERT(size_data >=3D header->num_desc * sizeof(*stats_data), + TEST_ASSERT(size_data >=3D header.num_desc * sizeof(*stats_data), "Data size is not correct"); /* Check stats offset */ - for (i =3D 0; i < header->num_desc; ++i) { + for (i =3D 0; i < header.num_desc; ++i) { pdesc =3D (void *)stats_desc + i * size_desc; TEST_ASSERT(pdesc->offset < size_data, "Invalid offset (%u) for stats: %s", @@ -142,15 +139,15 @@ static void stats_test(int stats_fd) stats_data =3D malloc(size_data); TEST_ASSERT(stats_data, "Allocate memory for stats data"); /* Read kvm stats data as a bulk */ - ret =3D pread(stats_fd, stats_data, size_data, header->data_offset); + ret =3D pread(stats_fd, stats_data, size_data, header.data_offset); TEST_ASSERT(ret =3D=3D size_data, "Read KVM stats data"); /* Read kvm stats data one by one */ size_data =3D 0; - for (i =3D 0; i < header->num_desc; ++i) { + for (i =3D 0; i < header.num_desc; ++i) { pdesc =3D (void *)stats_desc + i * size_desc; ret =3D pread(stats_fd, stats_data, pdesc->size * sizeof(*stats_data), - header->data_offset + size_data); + header.data_offset + size_data); TEST_ASSERT(ret =3D=3D pdesc->size * sizeof(*stats_data), "Read data of KVM stats: %s", pdesc->name); size_data +=3D pdesc->size * sizeof(*stats_data); @@ -159,7 +156,6 @@ static void stats_test(int stats_fd) free(stats_data); free(stats_desc); free(id); - free(header); } =20 =20 --=20 2.36.1.124.g0e6072fb45-goog From nobody Wed Apr 29 00:43:01 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 0442CC433F5 for ; Thu, 26 May 2022 17:54:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348377AbiEZRy0 (ORCPT ); Thu, 26 May 2022 13:54:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50146 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346088AbiEZRyR (ORCPT ); Thu, 26 May 2022 13:54:17 -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 12053A502E for ; Thu, 26 May 2022 10:54:16 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-2d7eaa730d9so18910897b3.13 for ; Thu, 26 May 2022 10:54:16 -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=xlflu8xJTWgeN8YYc673kTXZztT28OEQGqYXKcMTcZc=; b=UKc8S/QfO2KDNs4t5BrShZINGyYVzp7r9KvjjtdzWWAdC8pfJTlwPuw6Bpqnm8998m tsahLj+YqaCb461oohfhNAXEHu3k9HQo1iVNV0ghFHY5DaY0cH1FyFBvtANXc54G0j4O fG1a1WtOcaBYDWPW0kRpUMyny91kP8jGDoFYVIiFStx8qthi83IWngLLojYh1a+VPbhq qJM93XFxr6VNs6qyF7HHFtdz5LKVXwd4OmcXE8bDJn80t7xVyqe9/y9uH0uaklqag9Zv pb/KMxY19NLDBzhEkNAyKOoDS1B04+CQ0FTjVg5AWUHqq64QDcJMxNygoJTcmR2uvtvP 9xVw== 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=xlflu8xJTWgeN8YYc673kTXZztT28OEQGqYXKcMTcZc=; b=CYKyoKUOS7Cnt7zySCGmizSV05F891zrI1KTB7MiJhCcHJdygtRs6znbvX2HF1NclX HGt8E4KawJ6UvKnOBnV2kStca+B27lMTjLDnvsrdZhGhBhCz03XntMYaYM0j7KqE6nV7 Nii/zUGqpfNed2hvrT40q5aAjjuA+tZ2WqfWNCQzmQjpPal9pOW5Ekm8JkNv5IEU5FSp 61AoLxRR2BFpYxFBBswVB7lmrHJ6uouodJBMoDGgYauectOdfPGOEcWsaVgZcYMlvgxw 6s/YxI5IRYnNLQ4rEOvfTEsJgTVsC1LRa0n4aak7xaYGKJD4bSVLUKhz3XTmKSP9Vg5R flmA== X-Gm-Message-State: AOAM530NWKRjSkYqOpv54WKCyXQOd9vBf9cxcE5gvpZoPyheuHSxj2of x1AVifz4Ck0N1t/bPtKjPBi4qCITDabL X-Google-Smtp-Source: ABdhPJytBXiMeMyCo4WITinfBE+6stYgPM7eUOkHFwe5wzCn73c979Va1eZ3fDUY8ZULh3f5jFEQNZAntyzj X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a25:f45:0:b0:64f:8489:910f with SMTP id 66-20020a250f45000000b0064f8489910fmr26370755ybp.602.1653587655158; Thu, 26 May 2022 10:54:15 -0700 (PDT) Date: Thu, 26 May 2022 17:53:59 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-3-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 02/11] KVM: selftests: Read binary stats header in lib From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the code to read the binary stats header to the KVM selftests library. It will be re-used by other tests to check KVM behavior. No functional change intended. Reviewed-by: David Matlack Reviewed-by: Peter Xu Signed-off-by: Ben Gardon --- .../selftests/kvm/include/kvm_util_base.h | 1 + .../selftests/kvm/kvm_binary_stats_test.c | 4 ++-- tools/testing/selftests/kvm/lib/kvm_util.c | 21 +++++++++++++++++++ 3 files changed, 24 insertions(+), 2 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 92cef0ffb19e..749cded9b157 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -400,6 +400,7 @@ void assert_on_unhandled_exception(struct kvm_vm *vm, u= int32_t vcpuid); =20 int vm_get_stats_fd(struct kvm_vm *vm); int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vcpuid); +void read_stats_header(int stats_fd, struct kvm_stats_header *header); =20 uint32_t guest_get_vcpuid(void); =20 diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/te= sting/selftests/kvm/kvm_binary_stats_test.c index dad34d8a41fe..fb511b42a03e 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -33,8 +33,8 @@ static void stats_test(int stats_fd) struct kvm_stats_desc *pdesc; =20 /* Read kvm stats header */ - ret =3D read(stats_fd, &header, sizeof(header)); - TEST_ASSERT(ret =3D=3D sizeof(header), "Read stats header"); + read_stats_header(stats_fd, &header); + size_desc =3D sizeof(*stats_desc) + header.name_size; =20 /* Read kvm stats id string */ diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 1665a220abcb..1d75d41f92dc 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -2556,3 +2556,24 @@ int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vc= puid) =20 return ioctl(vcpu->fd, KVM_GET_STATS_FD, NULL); } + +/* + * Read binary stats header + * + * Input Args: + * stats_fd - the file descriptor for the binary stats file from which t= o read + * + * Output Args: + * header - a binary stats metadata header to be filled with data + * + * Return: void + * + * Read a header for the binary stats interface. + */ +void read_stats_header(int stats_fd, struct kvm_stats_header *header) +{ + ssize_t ret; + + ret =3D read(stats_fd, header, sizeof(*header)); + TEST_ASSERT(ret =3D=3D sizeof(*header), "Read stats header"); +} --=20 2.36.1.124.g0e6072fb45-goog From nobody Wed Apr 29 00:43:01 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 212F2C433EF for ; Thu, 26 May 2022 17:55:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348394AbiEZRyw (ORCPT ); Thu, 26 May 2022 13:54:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50180 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236554AbiEZRyS (ORCPT ); Thu, 26 May 2022 13:54:18 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 57BFCA502E for ; Thu, 26 May 2022 10:54:17 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id 15-20020aa7920f000000b0050cf449957fso1313972pfo.9 for ; Thu, 26 May 2022 10:54: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=0FS/khluyzXyi0v7JMPmPvXNbS+JklV5tSdCLtxEUUk=; b=HrkQFgdujrqFd3BRxxt7bRuGXEf8RWb66hZtsqdudc94AMeXuZwfxe5oSwRdX+eRrR IYhW2jztILRKX2tbD1FD5BeoyJShY4usFO+IwyRiO69sgqyELWq00S6yUzjJe212LTno lZvROlt5uqQJdKmKI2UyjeFKzNvLkICfQtm17xgybvEFMeBeobAtbYtJHyEIwALgZ/tn u9wzo7lLnURyr0C2S1YpFxjtDfJ582dTQzUyXElddc4+9jX/levpaMUXZibHirpPurBB D9tW7T8+M7d0B3uM4L/KoxIMnwiyF0QtrkDNa6X8+4ImdN9vFEQd7MfcR4rgYGNe0g+9 D+NA== 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=0FS/khluyzXyi0v7JMPmPvXNbS+JklV5tSdCLtxEUUk=; b=sJQlFQCPREk7c35eLquw2KY0v1ODFtnfXDS++ymFAcm+fCX5SDSLMz0jjIMQmbZmln RQ9xAkKJhkDWAslM2QrmsMpdV1FhPbbAJuECJdUgC149O9VgDNdawRRf5nxntrP+YR6f 7vMUOvmRI/S/IjeJtKJetsEmO/x4KzTfqkZY5Db+yrJqATs46UcNFukyHR4TM3yr/M6u s7vkwst2R5bdBZG5KR/yFiQM0szakrcN+vJChFbxLaScqIwmnNyRjQYwn1O9XMUctSXs CzClRrnjmTf7Zp3TgBzBj/HrFZ4/6lCi0T/LR6kXTaFhpbYR7wh3MPdolo0s+44iFiTR isxA== X-Gm-Message-State: AOAM532Wc6hJ9F5sDXotcHLsi1InShoX/OeOB9ivW5rIAZ0kQPt5gQZW aq+aa2mWBEQDdmv/324qzZRLRc1bMk3z X-Google-Smtp-Source: ABdhPJwEI6jPYmsPvZnvvRFp8VGXZTwyDOgPjMc7nn/ZmtEPM4e59mSKFUnPTnOJKJaq7mcxqB6EbYWXFEF5 X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a17:902:8203:b0:15f:4423:6e9c with SMTP id x3-20020a170902820300b0015f44236e9cmr39395839pln.25.1653587656833; Thu, 26 May 2022 10:54:16 -0700 (PDT) Date: Thu, 26 May 2022 17:54:00 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-4-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 03/11] KVM: selftests: Read binary stats desc in lib From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the code to read the binary stats descriptors to the KVM selftests library. It will be re-used by other tests to check KVM behavior. No functional change intended. Reviewed-by: David Matlack Reviewed-by: Peter Xu Signed-off-by: Ben Gardon --- .../selftests/kvm/include/kvm_util_base.h | 24 ++++++++++++++ .../selftests/kvm/kvm_binary_stats_test.c | 16 +++------ tools/testing/selftests/kvm/lib/kvm_util.c | 33 +++++++++++++++++++ 3 files changed, 62 insertions(+), 11 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 749cded9b157..da7bf881f94f 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -401,6 +401,30 @@ void assert_on_unhandled_exception(struct kvm_vm *vm, = uint32_t vcpuid); int vm_get_stats_fd(struct kvm_vm *vm); int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vcpuid); void read_stats_header(int stats_fd, struct kvm_stats_header *header); +struct kvm_stats_desc *read_stats_descriptors(int stats_fd, + struct kvm_stats_header *header); + +static inline ssize_t get_stats_descriptor_size(struct kvm_stats_header *h= eader) +{ + /* + * The base size of the descriptor is defined by KVM's ABI, but the + * size of the name field is variable, as far as KVM's ABI is + * concerned. For a given instance of KVM, the name field is the same + * size for all stats and is provided in the overall stats header. + */ + return sizeof(struct kvm_stats_desc) + header->name_size; +} + +static inline struct kvm_stats_desc *get_stats_descriptor(struct kvm_stats= _desc *stats, + int index, + struct kvm_stats_header *header) +{ + /* + * Note, size_desc includes the size of the name field, which is + * variable. i.e. this is NOT equivalent to &stats_desc[i]. + */ + return (void *)stats + index * get_stats_descriptor_size(header); +} =20 uint32_t guest_get_vcpuid(void); =20 diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/te= sting/selftests/kvm/kvm_binary_stats_test.c index fb511b42a03e..a5198b9a19c1 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -35,7 +35,7 @@ static void stats_test(int stats_fd) /* Read kvm stats header */ read_stats_header(stats_fd, &header); =20 - size_desc =3D sizeof(*stats_desc) + header.name_size; + size_desc =3D get_stats_descriptor_size(&header); =20 /* Read kvm stats id string */ id =3D malloc(header.name_size); @@ -62,18 +62,12 @@ static void stats_test(int stats_fd) header.data_offset), "Descriptor block is overlapped with data block"); =20 - /* Allocate memory for stats descriptors */ - stats_desc =3D calloc(header.num_desc, size_desc); - TEST_ASSERT(stats_desc, "Allocate memory for stats descriptors"); /* Read kvm stats descriptors */ - ret =3D pread(stats_fd, stats_desc, - size_desc * header.num_desc, header.desc_offset); - TEST_ASSERT(ret =3D=3D size_desc * header.num_desc, - "Read KVM stats descriptors"); + stats_desc =3D read_stats_descriptors(stats_fd, &header); =20 /* Sanity check for fields in descriptors */ for (i =3D 0; i < header.num_desc; ++i) { - pdesc =3D (void *)stats_desc + i * size_desc; + pdesc =3D get_stats_descriptor(stats_desc, i, &header); /* Check type,unit,base boundaries */ TEST_ASSERT((pdesc->flags & KVM_STATS_TYPE_MASK) <=3D KVM_STATS_TYPE_MAX, "Unknown KVM stats type"); @@ -129,7 +123,7 @@ static void stats_test(int stats_fd) "Data size is not correct"); /* Check stats offset */ for (i =3D 0; i < header.num_desc; ++i) { - pdesc =3D (void *)stats_desc + i * size_desc; + pdesc =3D get_stats_descriptor(stats_desc, i, &header); TEST_ASSERT(pdesc->offset < size_data, "Invalid offset (%u) for stats: %s", pdesc->offset, pdesc->name); @@ -144,7 +138,7 @@ static void stats_test(int stats_fd) /* Read kvm stats data one by one */ size_data =3D 0; for (i =3D 0; i < header.num_desc; ++i) { - pdesc =3D (void *)stats_desc + i * size_desc; + pdesc =3D get_stats_descriptor(stats_desc, i, &header); ret =3D pread(stats_fd, stats_data, pdesc->size * sizeof(*stats_data), header.data_offset + size_data); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 1d75d41f92dc..e5abcb189f1d 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -2577,3 +2577,36 @@ void read_stats_header(int stats_fd, struct kvm_stat= s_header *header) ret =3D read(stats_fd, header, sizeof(*header)); TEST_ASSERT(ret =3D=3D sizeof(*header), "Read stats header"); } + +/* + * Read binary stats descriptors + * + * Input Args: + * stats_fd - the file descriptor for the binary stats file from which t= o read + * header - the binary stats metadata header corresponding to the given = FD + * + * Output Args: None + * + * Return: + * A pointer to a newly allocated series of stat descriptors. + * Caller is responsible for freeing the returned kvm_stats_desc. + * + * Read the stats descriptors from the binary stats interface. + */ +struct kvm_stats_desc *read_stats_descriptors(int stats_fd, + struct kvm_stats_header *header) +{ + struct kvm_stats_desc *stats_desc; + ssize_t desc_size, total_size, ret; + + desc_size =3D get_stats_descriptor_size(header); + total_size =3D header->num_desc * desc_size; + + stats_desc =3D calloc(header->num_desc, desc_size); + TEST_ASSERT(stats_desc, "Allocate memory for stats descriptors"); + + ret =3D pread(stats_fd, stats_desc, total_size, header->desc_offset); + TEST_ASSERT(ret =3D=3D total_size, "Read KVM stats descriptors"); + + return stats_desc; +} --=20 2.36.1.124.g0e6072fb45-goog From nobody Wed Apr 29 00:43:01 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 0DAE6C433FE for ; Thu, 26 May 2022 17:54:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244515AbiEZRye (ORCPT ); Thu, 26 May 2022 13:54:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50160 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347617AbiEZRyX (ORCPT ); Thu, 26 May 2022 13:54:23 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 55271A7E33 for ; Thu, 26 May 2022 10:54:19 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id m5-20020a17090a4d8500b001e0cfe135c7so1458604pjh.3 for ; Thu, 26 May 2022 10:54: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=falxtzP4l1rM8q3vaJiFDhXAWycm4MI2aAJ4+6pFDbo=; b=Iy7Dxc3igXT8IaYfpRfrevtHrWY0aG5RMOHxZFj1X3DSUrAa9qJVreThMq7/xLkq4a fZMvR3ZTjvrg7dRmTnDc6HYXsd3dFiIB2XuVHIsu3TFrv0WqNcPIdK/aNOaUdcK3qEva G/jlnDADPDyj7xMTwBNtDLfeUGtEI5Q9/OYBpirxN2g6EqjaeSaklU/jDfLKFdnmz+w1 ICfl4elBVBMQ5pa6z//x1FCkMUBEmpaOWAMGBLdBtI+ReYvwByWhsyM7dEVRfUZ+9K0g 7a38FAhAHvfbCmszrVQSNb/gt1u7XhyrkeyFmLjMHldrtgL2HndL4D78Sbk5q0jfGFVX /pQQ== 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=falxtzP4l1rM8q3vaJiFDhXAWycm4MI2aAJ4+6pFDbo=; b=5lBEvmGHLxi7oYEJ5xGoFB5IY/NsEYRtVcGdJzSrzu4UHY0mqjLjDWCqYzRwcCCVQr FseL0XzmDzVIYR8JLgKJ7Tdg2ZjIk57mULkt78waDqTiMo8+FYMXBsA0cZdKHIeTieE0 gGiudgNjBDUf+V9UYDUf//fWbSdXTfZ5PaTPtN8MJlH0RMHJW/hTOgo9/im4MZkZ2uLx 8AORQWnDz/UCH5bw5KbnUtvOLNXZZhBmhKOR/yAXFVM/eij/bUlnP39Jr1luJ758Q8/P t/A3TFkbWhuieLT31YPbpFfKIaxDEuI5VY4jsaiwuhbVPjHC+txhNJzaGDDh1xSDAZyH ctyQ== X-Gm-Message-State: AOAM533V9CpAE2ZkET+gG9y2deiZ7SGhKfSa2p8/kp9pKQNS40Mgepe4 tJXY3v6+d7Gz7Sq+EZ4CILFrWmlh/6Fj X-Google-Smtp-Source: ABdhPJwDSn6DdJNOrV9sZ9BKy5TmJDviFFwJMbDvGYeKHMI/CLjzBDvij+HHDmlczSRBHT4jPllBJbS375pX X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a05:6a00:1a44:b0:510:a043:3b09 with SMTP id h4-20020a056a001a4400b00510a0433b09mr39441711pfv.62.1653587658635; Thu, 26 May 2022 10:54:18 -0700 (PDT) Date: Thu, 26 May 2022 17:54:01 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-5-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 04/11] KVM: selftests: Clean up coding style in binary stats test From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon 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 Fix a variety of code style violations and/or inconsistencies in the binary stats test. The 80 char limit is a soft limit and can and should be ignored/violated if doing so improves the overall code readability. Specifically, provide consistent indentation and don't split expressions at arbitrary points just to honor the 80 char limit. Opportunistically expand/add comments to call out the more subtle aspects of the code. Signed-off-by: Sean Christopherson Reviewed-by: David Matlack Signed-off-by: Ben Gardon --- .../selftests/kvm/kvm_binary_stats_test.c | 79 +++++++++++-------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/te= sting/selftests/kvm/kvm_binary_stats_test.c index a5198b9a19c1..956dc40d9bc7 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -40,27 +40,31 @@ static void stats_test(int stats_fd) /* Read kvm stats id string */ id =3D malloc(header.name_size); TEST_ASSERT(id, "Allocate memory for id string"); + ret =3D read(stats_fd, id, header.name_size); TEST_ASSERT(ret =3D=3D header.name_size, "Read id string"); =20 /* Check id string, that should start with "kvm" */ TEST_ASSERT(!strncmp(id, "kvm", 3) && strlen(id) < header.name_size, - "Invalid KVM stats type, id: %s", id); + "Invalid KVM stats type, id: %s", id); =20 /* Sanity check for other fields in header */ if (header.num_desc =3D=3D 0) { printf("No KVM stats defined!"); return; } - /* Check overlap */ - TEST_ASSERT(header.desc_offset > 0 && header.data_offset > 0 - && header.desc_offset >=3D sizeof(header) - && header.data_offset >=3D sizeof(header), - "Invalid offset fields in header"); + /* + * The descriptor and data offsets must be valid, they must not overlap + * the header, and the descriptor and data blocks must not overlap each + * other. Note, the data block is rechecked after its size is known. + */ + TEST_ASSERT(header.desc_offset && header.desc_offset >=3D sizeof(header) = && + header.data_offset && header.data_offset >=3D sizeof(header), + "Invalid offset fields in header"); + TEST_ASSERT(header.desc_offset > header.data_offset || - (header.desc_offset + size_desc * header.num_desc <=3D - header.data_offset), - "Descriptor block is overlapped with data block"); + (header.desc_offset + size_desc * header.num_desc <=3D header.data_o= ffset), + "Descriptor block is overlapped with data block"); =20 /* Read kvm stats descriptors */ stats_desc =3D read_stats_descriptors(stats_fd, &header); @@ -68,14 +72,17 @@ static void stats_test(int stats_fd) /* Sanity check for fields in descriptors */ for (i =3D 0; i < header.num_desc; ++i) { pdesc =3D get_stats_descriptor(stats_desc, i, &header); + /* Check type,unit,base boundaries */ - TEST_ASSERT((pdesc->flags & KVM_STATS_TYPE_MASK) - <=3D KVM_STATS_TYPE_MAX, "Unknown KVM stats type"); - TEST_ASSERT((pdesc->flags & KVM_STATS_UNIT_MASK) - <=3D KVM_STATS_UNIT_MAX, "Unknown KVM stats unit"); - TEST_ASSERT((pdesc->flags & KVM_STATS_BASE_MASK) - <=3D KVM_STATS_BASE_MAX, "Unknown KVM stats base"); - /* Check exponent for stats unit + TEST_ASSERT((pdesc->flags & KVM_STATS_TYPE_MASK) <=3D KVM_STATS_TYPE_MAX, + "Unknown KVM stats type"); + TEST_ASSERT((pdesc->flags & KVM_STATS_UNIT_MASK) <=3D KVM_STATS_UNIT_MAX, + "Unknown KVM stats unit"); + TEST_ASSERT((pdesc->flags & KVM_STATS_BASE_MASK) <=3D KVM_STATS_BASE_MAX, + "Unknown KVM stats base"); + + /* + * Check exponent for stats unit * Exponent for counter should be greater than or equal to 0 * Exponent for unit bytes should be greater than or equal to 0 * Exponent for unit seconds should be less than or equal to 0 @@ -86,47 +93,51 @@ static void stats_test(int stats_fd) case KVM_STATS_UNIT_NONE: case KVM_STATS_UNIT_BYTES: case KVM_STATS_UNIT_CYCLES: - TEST_ASSERT(pdesc->exponent >=3D 0, - "Unsupported KVM stats unit"); + TEST_ASSERT(pdesc->exponent >=3D 0, "Unsupported KVM stats unit"); break; case KVM_STATS_UNIT_SECONDS: - TEST_ASSERT(pdesc->exponent <=3D 0, - "Unsupported KVM stats unit"); + TEST_ASSERT(pdesc->exponent <=3D 0, "Unsupported KVM stats unit"); break; } /* Check name string */ TEST_ASSERT(strlen(pdesc->name) < header.name_size, - "KVM stats name(%s) too long", pdesc->name); + "KVM stats name(%s) too long", pdesc->name); /* Check size field, which should not be zero */ - TEST_ASSERT(pdesc->size, "KVM descriptor(%s) with size of 0", - pdesc->name); + TEST_ASSERT(pdesc->size, + "KVM descriptor(%s) with size of 0", pdesc->name); /* Check bucket_size field */ switch (pdesc->flags & KVM_STATS_TYPE_MASK) { case KVM_STATS_TYPE_LINEAR_HIST: TEST_ASSERT(pdesc->bucket_size, - "Bucket size of Linear Histogram stats (%s) is zero", - pdesc->name); + "Bucket size of Linear Histogram stats (%s) is zero", + pdesc->name); break; default: TEST_ASSERT(!pdesc->bucket_size, - "Bucket size of stats (%s) is not zero", - pdesc->name); + "Bucket size of stats (%s) is not zero", + pdesc->name); } size_data +=3D pdesc->size * sizeof(*stats_data); } - /* Check overlap */ - TEST_ASSERT(header.data_offset >=3D header.desc_offset - || header.data_offset + size_data <=3D header.desc_offset, - "Data block is overlapped with Descriptor block"); + + /* + * Now that the size of the data block is known, verify the data block + * doesn't overlap the descriptor block. + */ + TEST_ASSERT(header.data_offset >=3D header.desc_offset || + header.data_offset + size_data <=3D header.desc_offset, + "Data block is overlapped with Descriptor block"); + /* Check validity of all stats data size */ TEST_ASSERT(size_data >=3D header.num_desc * sizeof(*stats_data), - "Data size is not correct"); + "Data size is not correct"); + /* Check stats offset */ for (i =3D 0; i < header.num_desc; ++i) { pdesc =3D get_stats_descriptor(stats_desc, i, &header); TEST_ASSERT(pdesc->offset < size_data, - "Invalid offset (%u) for stats: %s", - pdesc->offset, pdesc->name); + "Invalid offset (%u) for stats: %s", + pdesc->offset, pdesc->name); } =20 /* Allocate memory for stats data */ --=20 2.36.1.124.g0e6072fb45-goog From nobody Wed Apr 29 00:43:01 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 B6931C433EF for ; Thu, 26 May 2022 17:54:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348420AbiEZRym (ORCPT ); Thu, 26 May 2022 13:54:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50182 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348383AbiEZRyX (ORCPT ); Thu, 26 May 2022 13:54:23 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 963A8A8883 for ; Thu, 26 May 2022 10:54:20 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id z21-20020aa79595000000b00518157fadaeso1306425pfj.14 for ; Thu, 26 May 2022 10:54:20 -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=5vGiJJSdPSy1HuUrdRdW0JjSgOuzkODUzYg68y2Y0IE=; b=awTsQInRgNWh6d6fLmKGIfDPoNZ4JDM2kuLlhw7abGgTIdeg2euhrAX2+NgjQ01LeN CVegJaCn3C37OaApahQZZF6U+jHJYg3R9YLzcff0AHf8fcOtObXcGOx3QYXHXjn4IFQF 7zPaztoMyM5ZejafOqecsbkhUIC0MWLUfecOjsETMrxFDi5XEdAQnzYpVaYL3ilyjbz8 j66SlEXU9kKc05kj3uu2cC1s5sJBNEgGdPpMqkqnwqPknzI/WVjPhp5bYxovnMqykJqO e4Pn7IhO0gVdfAPkt6bNvmhABkvsBDImE28fOEEdn4x5+obhzs/8efxaCWq/2y5B6YWU TMwA== 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=5vGiJJSdPSy1HuUrdRdW0JjSgOuzkODUzYg68y2Y0IE=; b=x0qFGXDnZPamM7PEAoB3g0iya2oBhhHlHkPp6Tah9P0j0Heob0FAlHeiA+7PRgTMjV 8Rv6kTBQ2xM5UQudGYR0/FF2cMidlbY5QjT0GyMryJMmJD3OyaxiNlP+0kHg2LLjhKK+ ANx6Mozs+eRUvqwHsvaoANTTSc40mlRvB+LhgDib+m4msL1G+xWXxdm74SRtiEwt9qoM pNONQfcR8oaxC0K+cFhkXbSMwhQwPIesyCB210aQXoqzoZpkrqOa8+Jn7hUdCDUf+yod vsAnX5kIK4pElWSg7WgyYRX4Xrt9OFwyunPZewHiT9EEk/uU5+EOO4q6FzOGcql0MUbS b3nQ== X-Gm-Message-State: AOAM531hvCOCZXdgVUQyL/5mcHZIERrXRRNbu9YTCLsvdqym9JNtmLB+ x4ObylUGpPYz13xaMB0SJFJE1+1Lm5c9 X-Google-Smtp-Source: ABdhPJxzDERCjXuxy/IwSh6i+hQtpcXP2gfe93mhJr6DUTfm2z6EJg4aaaHDrZmVwey6gqWbRy9hbupmzePA X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a17:903:2305:b0:162:1023:b88a with SMTP id d5-20020a170903230500b001621023b88amr25435065plh.48.1653587660052; Thu, 26 May 2022 10:54:20 -0700 (PDT) Date: Thu, 26 May 2022 17:54:02 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-6-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 05/11] KVM: selftests: Read binary stat data in lib From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the code to read the binary stats data to the KVM selftests library. It will be re-used by other tests to check KVM behavior. Also opportunistically remove an unnecessary calculation with "size_data" in stats_test. Reviewed-by: David Matlack Reviewed-by: Peter Xu Signed-off-by: Ben Gardon --- .../selftests/kvm/include/kvm_util_base.h | 4 +++ .../selftests/kvm/kvm_binary_stats_test.c | 9 ++--- tools/testing/selftests/kvm/lib/kvm_util.c | 35 +++++++++++++++++++ 3 files changed, 41 insertions(+), 7 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 da7bf881f94f..967f6d6cf255 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -426,6 +426,10 @@ static inline struct kvm_stats_desc *get_stats_descrip= tor(struct kvm_stats_desc return (void *)stats + index * get_stats_descriptor_size(header); } =20 +void read_stat_data(int stats_fd, struct kvm_stats_header *header, + struct kvm_stats_desc *desc, uint64_t *data, + size_t max_elements); + uint32_t guest_get_vcpuid(void); =20 #endif /* SELFTEST_KVM_UTIL_BASE_H */ diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/te= sting/selftests/kvm/kvm_binary_stats_test.c index 956dc40d9bc7..ee2d6c18d620 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -147,15 +147,10 @@ static void stats_test(int stats_fd) ret =3D pread(stats_fd, stats_data, size_data, header.data_offset); TEST_ASSERT(ret =3D=3D size_data, "Read KVM stats data"); /* Read kvm stats data one by one */ - size_data =3D 0; for (i =3D 0; i < header.num_desc; ++i) { pdesc =3D get_stats_descriptor(stats_desc, i, &header); - ret =3D pread(stats_fd, stats_data, - pdesc->size * sizeof(*stats_data), - header.data_offset + size_data); - TEST_ASSERT(ret =3D=3D pdesc->size * sizeof(*stats_data), - "Read data of KVM stats: %s", pdesc->name); - size_data +=3D pdesc->size * sizeof(*stats_data); + read_stat_data(stats_fd, &header, pdesc, stats_data, + pdesc->size); } =20 free(stats_data); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index e5abcb189f1d..5e1ac66faf0f 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -2610,3 +2610,38 @@ struct kvm_stats_desc *read_stats_descriptors(int st= ats_fd, =20 return stats_desc; } + +/* + * Read stat data for a particular stat + * + * Input Args: + * stats_fd - the file descriptor for the binary stats file from which t= o read + * header - the binary stats metadata header corresponding to the given = FD + * desc - the binary stat metadata for the particular stat to be read + * max_elements - the maximum number of 8-byte values to read into data + * + * Output Args: + * data - the buffer into which stat data should be read + * + * Read the data values of a specified stat from the binary stats interfac= e. + */ +void read_stat_data(int stats_fd, struct kvm_stats_header *header, + struct kvm_stats_desc *desc, uint64_t *data, + size_t max_elements) +{ + size_t nr_elements =3D min_t(ssize_t, desc->size, max_elements); + size_t size =3D nr_elements * sizeof(*data); + ssize_t ret; + + TEST_ASSERT(desc->size, "No elements in stat '%s'", desc->name); + TEST_ASSERT(max_elements, "Zero elements requested for stat '%s'", desc->= name); + + ret =3D pread(stats_fd, data, size, + header->data_offset + desc->offset); + + TEST_ASSERT(ret >=3D 0, "pread() failed on stat '%s', errno: %i (%s)", + desc->name, errno, strerror(errno)); + TEST_ASSERT(ret =3D=3D size, + "pread() on stat '%s' read %ld bytes, wanted %lu bytes", + desc->name, size, ret); +} --=20 2.36.1.124.g0e6072fb45-goog From nobody Wed Apr 29 00:43:01 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 D935CC433F5 for ; Thu, 26 May 2022 17:54:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348474AbiEZRyq (ORCPT ); Thu, 26 May 2022 13:54:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50190 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348385AbiEZRyX (ORCPT ); Thu, 26 May 2022 13:54:23 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 04C1FA88AB for ; Thu, 26 May 2022 10:54:21 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id j13-20020a170902da8d00b00161d78a9e3eso1436277plx.17 for ; Thu, 26 May 2022 10:54: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=e5pL0FxDuisARPZtbD7txNNR7V88IYUqfzY8P8cZNnU=; b=cIsfysGMiDvkrsVfnH8RT9o2QeibtiTYXoojfc0c1/ujMhHm6n8U1YACWuECWl7GlY VZAfnxpaRyUed4VFNS1PA43jOYvshFu5UoAL3ZfiFEa2DhRoXSTPO8wP/HpC171kFYCA yUrjA6lge0f1EIZcLq6qiwlXyqxFLsiAQ+p5gw0aO5yf8YoplszCZua7+wMsikzlYNaG 6rg7iEEn/4Cf5bWU6x6f4qio0j16X30M+bQo49u26bS/KTkPNc9QubfgxHBxvWSzfWDN 0k5ays4QcPftX0DvWuKYHCBdZ1Tua6HNtd45J0K6jhgGz8w37pr9MsU2bSk793UejYnh uQzQ== 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=e5pL0FxDuisARPZtbD7txNNR7V88IYUqfzY8P8cZNnU=; b=6r+11k6HaXfW7PQJF4h7zeLELEWaccLp7CyLqxkbWCwjCZuUFrNHrz7BrKIY2NOCCu Dl3Zcq+Ni7Sbnx6gw11eS3dCXGpgWvkxPgUk73SwkzP/jlA9KUDxb3xkoNxyTeAvKA+i IHUht+gtqYLazQlh8vwGwN7TubQ3rygITsRqg2QyTXWseQL9ZA3aYSb6m9qbn2EaBHhT zf58q1L2kp1e9G0LD14kbsNuAIPo8d9ECH/AnHxugSrTRZlgkW5e94ZjL3YX3ppDhTgJ PbQOc/WuTjyGV5zzJy6F/3IThR4mQxAB1otmx3+Pfx3aWHzmbNah71Hul5iG8Stwsfo+ SieA== X-Gm-Message-State: AOAM531BxE6U5KI/sIO7OEjrF4UyCeZFbdUWzGm0x8QG89EYd/Dhsk7x K52s5m1sFI9hjzttShQRSGyKS3i1LWYe X-Google-Smtp-Source: ABdhPJyHn9uFry3FM9MyhXExQxsMxxxss5btuEbXT2ZUDJccIiM9T1sma7PDox22swTBV9CY4ilLG6CSLASc X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a05:6a00:1815:b0:518:9681:44ee with SMTP id y21-20020a056a00181500b00518968144eemr23406632pfa.15.1653587661385; Thu, 26 May 2022 10:54:21 -0700 (PDT) Date: Thu, 26 May 2022 17:54:03 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-7-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 06/11] KVM: selftests: Add NX huge pages test From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" There's currently no test coverage of NX hugepages in KVM selftests, so add a basic test to ensure that the feature works as intended. The test creates a VM with a data slot backed with huge pages. The memory in the data slot is filled with op-codes for the return instruction. The guest then executes a series of accesses on the memory, some reads, some instruction fetches. After each operation, the guest exits and the test performs some checks on the backing page counts to ensure that NX page splitting an reclaim work as expected. Reviewed-by: David Matlack Signed-off-by: Ben Gardon --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 10 + .../selftests/kvm/include/kvm_util_base.h | 11 + tools/testing/selftests/kvm/lib/kvm_util.c | 46 ++++ .../selftests/kvm/x86_64/nx_huge_pages_test.c | 227 ++++++++++++++++++ .../kvm/x86_64/nx_huge_pages_test.sh | 40 +++ 6 files changed, 335 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c create mode 100755 tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftes= ts/kvm/.gitignore index 90a6dea2e84c..5cf0df616365 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -28,6 +28,7 @@ /x86_64/max_vcpuid_cap_test /x86_64/mmio_warning_test /x86_64/mmu_role_test +/x86_64/nx_huge_pages_test /x86_64/platform_info_test /x86_64/pmu_event_filter_test /x86_64/set_boot_cpu_id diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests= /kvm/Makefile index a014368a2cd2..0a41c326de84 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -43,6 +43,10 @@ LIBKVM_aarch64 =3D lib/aarch64/processor.c lib/aarch64/u= call.c lib/aarch64/handler LIBKVM_s390x =3D lib/s390x/processor.c lib/s390x/ucall.c lib/s390x/diag318= _test_handler.c LIBKVM_riscv =3D lib/riscv/processor.c lib/riscv/ucall.c =20 +# Non-compiled test targets +TEST_PROGS_x86_64 +=3D x86_64/nx_huge_pages_test.sh + +# Compiled test targets TEST_GEN_PROGS_x86_64 =3D x86_64/cpuid_test TEST_GEN_PROGS_x86_64 +=3D x86_64/cr4_cpuid_sync_test TEST_GEN_PROGS_x86_64 +=3D x86_64/get_msr_index_features @@ -106,6 +110,9 @@ TEST_GEN_PROGS_x86_64 +=3D steal_time TEST_GEN_PROGS_x86_64 +=3D kvm_binary_stats_test TEST_GEN_PROGS_x86_64 +=3D system_counter_offset_test =20 +# Compiled outputs used by test targets +TEST_GEN_PROGS_EXTENDED_x86_64 +=3D x86_64/nx_huge_pages_test + TEST_GEN_PROGS_aarch64 +=3D aarch64/arch_timer TEST_GEN_PROGS_aarch64 +=3D aarch64/debug-exceptions TEST_GEN_PROGS_aarch64 +=3D aarch64/get-reg-list @@ -145,7 +152,9 @@ TEST_GEN_PROGS_riscv +=3D kvm_page_table_test TEST_GEN_PROGS_riscv +=3D set_memory_region_test TEST_GEN_PROGS_riscv +=3D kvm_binary_stats_test =20 +TEST_PROGS +=3D $(TEST_PROGS_$(UNAME_M)) TEST_GEN_PROGS +=3D $(TEST_GEN_PROGS_$(UNAME_M)) +TEST_GEN_PROGS_EXTENDED +=3D $(TEST_GEN_PROGS_EXTENDED_$(UNAME_M)) LIBKVM +=3D $(LIBKVM_$(UNAME_M)) =20 INSTALL_HDR_PATH =3D $(top_srcdir)/usr @@ -196,6 +205,7 @@ $(OUTPUT)/libkvm.a: $(LIBKVM_OBJS) x :=3D $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS)))) all: $(STATIC_LIBS) $(TEST_GEN_PROGS): $(STATIC_LIBS) +$(TEST_GEN_PROGS_EXTENDED): $(STATIC_LIBS) =20 cscope: include_paths =3D $(LINUX_TOOL_INCLUDE) $(LINUX_HDR_PATH) include = lib .. cscope: diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/te= sting/selftests/kvm/include/kvm_util_base.h index 967f6d6cf255..035168cec451 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -430,6 +430,17 @@ void read_stat_data(int stats_fd, struct kvm_stats_hea= der *header, struct kvm_stats_desc *desc, uint64_t *data, size_t max_elements); =20 +void __vm_get_stat(struct kvm_vm *vm, const char *stat_name, uint64_t *dat= a, + size_t max_elements); + +static inline uint64_t vm_get_stat(struct kvm_vm *vm, const char *stat_nam= e) +{ + uint64_t data; + + __vm_get_stat(vm, stat_name, &data, 1); + return data; +} + uint32_t guest_get_vcpuid(void); =20 #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 5e1ac66faf0f..200d3bb803e0 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -2645,3 +2645,49 @@ void read_stat_data(int stats_fd, struct kvm_stats_h= eader *header, "pread() on stat '%s' read %ld bytes, wanted %lu bytes", desc->name, size, ret); } + +/* + * Read the data of the named stat + * + * Input Args: + * vm - the VM for which the stat should be read + * stat_name - the name of the stat to read + * max_elements - the maximum number of 8-byte values to read into data + * + * Output Args: + * data - the buffer into which stat data should be read + * + * Read the data values of a specified stat from the binary stats interfac= e. + */ +void __vm_get_stat(struct kvm_vm *vm, const char *stat_name, uint64_t *dat= a, + size_t max_elements) +{ + struct kvm_stats_desc *stats_desc; + struct kvm_stats_header header; + struct kvm_stats_desc *desc; + size_t size_desc; + int stats_fd; + int i; + + stats_fd =3D vm_get_stats_fd(vm); + + read_stats_header(stats_fd, &header); + + stats_desc =3D read_stats_descriptors(stats_fd, &header); + + size_desc =3D get_stats_descriptor_size(&header); + + for (i =3D 0; i < header.num_desc; ++i) { + desc =3D (void *)stats_desc + (i * size_desc); + + if (strcmp(desc->name, stat_name)) + continue; + + read_stat_data(stats_fd, &header, desc, data, max_elements); + + break; + } + + free(stats_desc); + close(stats_fd); +} diff --git a/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c b/tool= s/testing/selftests/kvm/x86_64/nx_huge_pages_test.c new file mode 100644 index 000000000000..09e05cda3dcd --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * tools/testing/selftests/kvm/nx_huge_page_test.c + * + * Usage: to be run via nx_huge_page_test.sh, which does the necessary + * environment setup and teardown + * + * Copyright (C) 2022, Google LLC. + */ + +#define _GNU_SOURCE + +#include +#include +#include + +#include +#include "kvm_util.h" +#include "processor.h" + +#define HPAGE_SLOT 10 +#define HPAGE_GPA (4UL << 30) /* 4G prevents collision w/ slot 0 */ +#define HPAGE_GVA HPAGE_GPA /* GVA is arbitrary, so use GPA. */ +#define PAGES_PER_2MB_HUGE_PAGE 512 +#define HPAGE_SLOT_NPAGES (3 * PAGES_PER_2MB_HUGE_PAGE) + +/* + * Passed by nx_huge_pages_test.sh to provide an easy warning if this test= is + * being run without it. + */ +#define MAGIC_TOKEN 887563923 + +/* + * x86 opcode for the return instruction. Used to call into, and then + * immediately return from, memory backed with hugepages. + */ +#define RETURN_OPCODE 0xC3 + +/* Call the specified memory address. */ +static void guest_do_CALL(uint64_t target) +{ + ((void (*)(void)) target)(); +} + +/* + * Exit the VM after each memory access so that the userspace component of= the + * test can make assertions about the pages backing the VM. + * + * See the below for an explanation of how each access should affect the + * backing mappings. + */ +void guest_code(void) +{ + uint64_t hpage_1 =3D HPAGE_GVA; + uint64_t hpage_2 =3D hpage_1 + (PAGE_SIZE * 512); + uint64_t hpage_3 =3D hpage_2 + (PAGE_SIZE * 512); + + READ_ONCE(*(uint64_t *)hpage_1); + GUEST_SYNC(1); + + READ_ONCE(*(uint64_t *)hpage_2); + GUEST_SYNC(2); + + guest_do_CALL(hpage_1); + GUEST_SYNC(3); + + guest_do_CALL(hpage_3); + GUEST_SYNC(4); + + READ_ONCE(*(uint64_t *)hpage_1); + GUEST_SYNC(5); + + READ_ONCE(*(uint64_t *)hpage_3); + GUEST_SYNC(6); +} + +static void check_2m_page_count(struct kvm_vm *vm, int expected_pages_2m) +{ + int actual_pages_2m; + + actual_pages_2m =3D vm_get_stat(vm, "pages_2m"); + + TEST_ASSERT(actual_pages_2m =3D=3D expected_pages_2m, + "Unexpected 2m page count. Expected %d, got %d", + expected_pages_2m, actual_pages_2m); +} + +static void check_split_count(struct kvm_vm *vm, int expected_splits) +{ + int actual_splits; + + actual_splits =3D vm_get_stat(vm, "nx_lpage_splits"); + + TEST_ASSERT(actual_splits =3D=3D expected_splits, + "Unexpected NX huge page split count. Expected %d, got %d", + expected_splits, actual_splits); +} + +static void wait_for_reclaim(int reclaim_period_ms) +{ + long reclaim_wait_ms; + struct timespec ts; + + reclaim_wait_ms =3D reclaim_period_ms * 5; + ts.tv_sec =3D reclaim_wait_ms / 1000; + ts.tv_nsec =3D (reclaim_wait_ms - (ts.tv_sec * 1000)) * 1000000; + nanosleep(&ts, NULL); +} + +static void help(char *name) +{ + puts(""); + printf("usage: %s [-h] [-p period_ms] [-t token]\n", name); + puts(""); + printf(" -p: The NX reclaim period in miliseconds.\n"); + printf(" -t: The magic token to indicate environment setup is done.\n"); + puts(""); + exit(0); +} + +int main(int argc, char **argv) +{ + int reclaim_period_ms =3D 0, token =3D 0, opt; + struct kvm_vm *vm; + void *hva; + + while ((opt =3D getopt(argc, argv, "hp:t:")) !=3D -1) { + switch (opt) { + case 'p': + reclaim_period_ms =3D atoi(optarg); + break; + case 't': + token =3D atoi(optarg); + break; + case 'h': + default: + help(argv[0]); + break; + } + } + + if (token !=3D MAGIC_TOKEN) { + print_skip("This test must be run with the magic token %d.\n" + "This is done by nx_huge_pages_test.sh, which\n" + "also handles environment setup for the test.", + MAGIC_TOKEN); + exit(KSFT_SKIP); + } + + if (!reclaim_period_ms) { + print_skip("The NX reclaim period must be specified and non-zero"); + exit(KSFT_SKIP); + } + + vm =3D vm_create_default(0, 0, guest_code); + + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS_HUGETLB, + HPAGE_GPA, HPAGE_SLOT, + HPAGE_SLOT_NPAGES, 0); + + virt_map(vm, HPAGE_GVA, HPAGE_GPA, HPAGE_SLOT_NPAGES); + + hva =3D addr_gpa2hva(vm, HPAGE_GPA); + memset(hva, RETURN_OPCODE, HPAGE_SLOT_NPAGES * PAGE_SIZE); + + check_2m_page_count(vm, 0); + check_split_count(vm, 0); + + /* + * The guest code will first read from the first hugepage, resulting + * in a huge page mapping being created. + */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 1); + check_split_count(vm, 0); + + /* + * Then the guest code will read from the second hugepage, resulting + * in another huge page mapping being created. + */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 2); + check_split_count(vm, 0); + + /* + * Next, the guest will execute from the first huge page, causing it + * to be remapped at 4k. + */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 1); + check_split_count(vm, 1); + + /* + * Executing from the third huge page (previously unaccessed) will + * cause part to be mapped at 4k. + */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 1); + check_split_count(vm, 2); + + /* Reading from the first huge page again should have no effect. */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 1); + check_split_count(vm, 2); + + /* Give recovery thread time to run. */ + wait_for_reclaim(reclaim_period_ms); + + /* + * Now that the reclaimer has run, all the split pages should be gone. + */ + check_2m_page_count(vm, 1); + check_split_count(vm, 0); + + /* + * The 4k mapping on hpage 3 should have been removed, so check that + * reading from it causes a huge page mapping to be installed. + */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 2); + check_split_count(vm, 0); + + kvm_vm_free(vm); + + return 0; +} + diff --git a/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh b/too= ls/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh new file mode 100755 index 000000000000..4e090a84f5f3 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-only */ +# +# Wrapper script which performs setup and cleanup for nx_huge_pages_test. +# Makes use of root privileges to set up huge pages and KVM module paramet= ers. +# +# tools/testing/selftests/kvm/nx_huge_page_test.sh +# Copyright (C) 2022, Google LLC. + +set -e + +NX_HUGE_PAGES=3D$(cat /sys/module/kvm/parameters/nx_huge_pages) +NX_HUGE_PAGES_RECOVERY_RATIO=3D$(cat /sys/module/kvm/parameters/nx_huge_pa= ges_recovery_ratio) +NX_HUGE_PAGES_RECOVERY_PERIOD=3D$(cat /sys/module/kvm/parameters/nx_huge_p= ages_recovery_period_ms) +HUGE_PAGES=3D$(cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages) + +set +e + +function sudo_echo () { + echo "$1" | sudo tee -a "$2" > /dev/null +} + +( + set -e + + sudo_echo 1 /sys/module/kvm/parameters/nx_huge_pages + sudo_echo 1 /sys/module/kvm/parameters/nx_huge_pages_recovery_ratio + sudo_echo 100 /sys/module/kvm/parameters/nx_huge_pages_recovery_period_ms + sudo_echo "$(( $HUGE_PAGES + 3 ))" /sys/kernel/mm/hugepages/hugepages-204= 8kB/nr_hugepages + + "$(dirname $0)"/nx_huge_pages_test -t 887563923 -p 100 +) +RET=3D$? + +sudo_echo "$NX_HUGE_PAGES" /sys/module/kvm/parameters/nx_huge_pages +sudo_echo "$NX_HUGE_PAGES_RECOVERY_RATIO" /sys/module/kvm/parameters/nx_hu= ge_pages_recovery_ratio +sudo_echo "$NX_HUGE_PAGES_RECOVERY_PERIOD" /sys/module/kvm/parameters/nx_h= uge_pages_recovery_period_ms +sudo_echo "$HUGE_PAGES" /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugep= ages + +exit $RET --=20 2.36.1.124.g0e6072fb45-goog From nobody Wed Apr 29 00:43:01 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 90E67C433F5 for ; Thu, 26 May 2022 17:55:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348512AbiEZRy7 (ORCPT ); Thu, 26 May 2022 13:54:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50372 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348362AbiEZRyZ (ORCPT ); Thu, 26 May 2022 13:54:25 -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 BCA499EB44 for ; Thu, 26 May 2022 10:54:23 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id d125-20020a636883000000b003db5e24db27so1128414pgc.13 for ; Thu, 26 May 2022 10:54: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=Gl1ger3sfcviuQtEjEFpxedsk42UqwPOcwBSPpwDgrU=; b=fucrALtULyCr73H7V/AH9SnvOwGVx9HHpm5iyNovmetTQtgREZgxD+4w8eqnV4gfn+ xftI2cBDekG3YFoRIfxuQyENTWfQMxB498jJ8f4i2yN8pHLiobFxCVR7sHPfb+UuyZOO OYJfLUZl+G+EAGlECaHo58kwZGC43X0jlIf03PF9V9gDe2OEUOdwd9I784uTojTJbmIT BZNMIIUqlhXjrB2QvB8AocVSl+lnC7LDI/PB0Zp1z3nk6dAR+RyISpDIFdXb+psDbxkN MSkCaJjWz4EumHXma4xy7MGPbXR9xII2n7y3KxNBZ0AANV1bJ2OUQBKsjW9JF+q7eRL8 d/HA== 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=Gl1ger3sfcviuQtEjEFpxedsk42UqwPOcwBSPpwDgrU=; b=MkiVtjUshjeV7Mjz3PgN9n7wqqZMu9vqV5TT/JQ2whTBNxIVAok7MgrezjzI8UTLLv 4dPC6P1iPxmrHmnsri6Xy9yGVOAIsm4TvQw1/2hH/fNyyVxD43yvtJlaOZvMMraiOptM fEtQytmiy5TMsnjMNgHtHqXylb439gfGsTU7gRya211PWvtmfbi5A1p9XDIliRfwj8aO RqhsyXDlzk7vI1B/Ib6oh0gXOTdny0gFXiz43IS1sTUJQVKXBV9ydm2ojxN5K1yXY9Ey ByiQsUs3BznhLAjHiMGAfI1XJZXleKH3BwnTzletykyqa5Zlz7QqoA5bzpGLwrMdj1gK E/OQ== X-Gm-Message-State: AOAM53253mfRLEOtsYgbXna+Athw8u5lWWH+58JkLVn2dWmDW89WdFmp 9LxWa6UCLodTl6HNqrbHOarD5GVkKsNe X-Google-Smtp-Source: ABdhPJwfS8zuFF5ADj/NW82LmsBUkN5yDaJ+k3+6saKpjrVZOvgqnncdg9RnQRuQWYjSi4EU2ni3mLGwusvY X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a17:90b:1bcc:b0:1e0:1c94:ebcf with SMTP id oa12-20020a17090b1bcc00b001e01c94ebcfmr3830455pjb.140.1653587663082; Thu, 26 May 2022 10:54:23 -0700 (PDT) Date: Thu, 26 May 2022 17:54:04 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-8-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 07/11] KVM: x86: Fix errant brace in KVM capability handling From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The braces around the KVM_CAP_XSAVE2 block also surround the KVM_CAP_PMU_CAPABILITY block, likely the result of a merge issue. Simply move the curly brace back to where it belongs. Fixes: ba7bb663f5547 ("KVM: x86: Provide per VM capability for disabling PM= U virtualization") Reviewed-by: David Matlack Reviewed-by: Peter Xu Signed-off-by: Ben Gardon --- arch/x86/kvm/x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 7460b9a77d9a..33653a008b28 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4414,10 +4414,10 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, l= ong ext) if (r < sizeof(struct kvm_xsave)) r =3D sizeof(struct kvm_xsave); break; + } case KVM_CAP_PMU_CAPABILITY: r =3D enable_pmu ? KVM_CAP_PMU_VALID_MASK : 0; break; - } case KVM_CAP_DISABLE_QUIRKS2: r =3D KVM_X86_VALID_QUIRKS; break; --=20 2.36.1.124.g0e6072fb45-goog From nobody Wed Apr 29 00:43:01 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 E6F9AC433EF for ; Thu, 26 May 2022 17:55:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346288AbiEZRzF (ORCPT ); Thu, 26 May 2022 13:55:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50470 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348393AbiEZRy2 (ORCPT ); Thu, 26 May 2022 13:54:28 -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 23CE1A889D for ; Thu, 26 May 2022 10:54:25 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id d12-20020a17090a628c00b001dcd2efca39so1461348pjj.2 for ; Thu, 26 May 2022 10:54: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=5VdU/60xoPJww/ihUSO/wwK+tatmb/BBMm35Hsv8bhQ=; b=ieLvTgCfulEsl4d1Y1ZtIZC9JZTGc95h1VsHqHPXLC1/D89P7+bktSUG2PE5TpowCI hAS+btFZhLV+SUKX9pkETsw8xh27EDybdVmHNfKO88D1guWdzl4WuUjcjA7dG4f0zKVG 7rCUL3cZf6Q6grExefAAH0iJmUKJJGxmKTG/yUTbh+4n16D/Gnx6VmPB5XeU/HghPzFW dZrmaHybREzC1a/Uvh52HrDAcjNF6nCTqGBEK979Zd3GlDd5YoOxa7PwyLTnNaR6/8Wo pNmpSw9umDlfR/nHq6e5E/U1l5JODPqUEZFdks22qWwLko0dAHV9doO9B6DWQ5fyjGkI 1t1Q== 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=5VdU/60xoPJww/ihUSO/wwK+tatmb/BBMm35Hsv8bhQ=; b=RuQZmKW97DmMIMBMl9HQ/nSHsq7SP7lmTKR9SlusxiXXtx4x4umYMHIhzEieLhXUM/ QrMWWnbm1BL42q0ayvHWrQprySey6HDrZ1OovZiRSes2sJ2hrSleYrtQtYrIFXnTq4DW WzMfUlPKxo4KbAX0VLh5Na09DTEN+liR6M9vHQ8reMtC5I5rBUy7qot2pMpXRP95tpbg UOZH8P3e1wTLERPxBgNAgtexqABX54kv43cMea12tx3lQ3Yy/w1jDxTPfCaGyS20VpPF QnUiPt4WJM8jRkYzTu7rQ231mcWxKH8Vnr1pyxzzGDolZQ8LGWUF/U+zst0jPXihM7LT M4dQ== X-Gm-Message-State: AOAM532YnpmoLohqFomNbpdNdkFlJhwZM2CpS4AiQTHKAAnMOiLd/hgg TiimuLCeyewN1h6Xs7lUROiWAYt+PVb8 X-Google-Smtp-Source: ABdhPJwBT04GpdFco42dsLZMxv5tF/dE0SbQaACbVQem837qUmTNc1MqUzjJputeGcJ7R1P38jb/DjKdUFqF X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:aa7:8d0f:0:b0:518:d867:bae8 with SMTP id j15-20020aa78d0f000000b00518d867bae8mr12327142pfe.13.1653587664483; Thu, 26 May 2022 10:54:24 -0700 (PDT) Date: Thu, 26 May 2022 17:54:05 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-9-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 08/11] KVM: x86/MMU: Allow NX huge pages to be disabled on a per-vm basis From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In some cases, the NX hugepage mitigation for iTLB multihit is not needed for all guests on a host. Allow disabling the mitigation on a per-VM basis to avoid the performance hit of NX hugepages on trusted workloads. In order to disable NX hugepages on a VM, ensure that the userspace actor has permission to reboot the system. Since disabling NX hugepages would allow a guest to crash the system, it is similar to reboot permissions. Ideally, KVM would require userspace to prove it has access to KVM's nx_huge_pages module param, e.g. so that userspace can opt out without needing full reboot permissions. But getting access to the module param file info is difficult because it is buried in layers of sysfs and module glue. Requiring CAP_SYS_BOOT is sufficient for all known use cases. Suggested-by: Jim Mattson Reviewed-by: David Matlack Reviewed-by: Peter Xu Signed-off-by: Ben Gardon --- Documentation/virt/kvm/api.rst | 17 +++++++++++++++++ arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/mmu/mmu_internal.h | 7 ++++--- arch/x86/kvm/mmu/spte.c | 7 ++++--- arch/x86/kvm/mmu/spte.h | 3 ++- arch/x86/kvm/mmu/tdp_mmu.c | 2 +- arch/x86/kvm/x86.c | 30 ++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 1 + 8 files changed, 61 insertions(+), 8 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index a2e17baf8a5e..d1aec56a9ab7 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -7975,6 +7975,23 @@ should adjust CPUID leaf 0xA to reflect that the PMU= is disabled. When enabled, KVM will exit to userspace with KVM_EXIT_SYSTEM_EVENT of type KVM_SYSTEM_EVENT_SUSPEND to process the guest suspend request. =20 +8.37 KVM_CAP_VM_DISABLE_NX_HUGE_PAGES +--------------------------- + +:Capability KVM_CAP_VM_DISABLE_NX_HUGE_PAGES +:Architectures: x86 +:Type: vm +:Parameters: arg[0] must be 0. +:Returns 0 on success, -EPERM if the userspace process does not + have CAP_SYS_BOOT, -EINVAL if args[0] is not 0 or any vCPUs have been + created. + +This capability disables the NX huge pages mitigation for iTLB MULTIHIT. + +The capability has no effect if the nx_huge_pages module parameter is not = set. + +This capability may only be set before any vCPUs are created. + 9. Known KVM API problems =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D =20 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index ad28b0d1d5ea..de7e910741f2 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1268,6 +1268,8 @@ struct kvm_arch { * the global KVM_MAX_VCPU_IDS may lead to significant memory waste. */ u32 max_vcpu_ids; + + bool disable_nx_huge_pages; }; =20 struct kvm_vm_stat { diff --git a/arch/x86/kvm/mmu/mmu_internal.h b/arch/x86/kvm/mmu/mmu_interna= l.h index bd2a26897b97..d7e915f3a013 100644 --- a/arch/x86/kvm/mmu/mmu_internal.h +++ b/arch/x86/kvm/mmu/mmu_internal.h @@ -141,9 +141,9 @@ void kvm_flush_remote_tlbs_with_address(struct kvm *kvm, unsigned int pte_list_count(struct kvm_rmap_head *rmap_head); =20 extern int nx_huge_pages; -static inline bool is_nx_huge_page_enabled(void) +static inline bool is_nx_huge_page_enabled(struct kvm *kvm) { - return READ_ONCE(nx_huge_pages); + return READ_ONCE(nx_huge_pages) && !kvm->arch.disable_nx_huge_pages; } =20 struct kvm_page_fault { @@ -242,7 +242,8 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu= *vcpu, gpa_t cr2_or_gpa, .user =3D err & PFERR_USER_MASK, .prefetch =3D prefetch, .is_tdp =3D likely(vcpu->arch.mmu->page_fault =3D=3D kvm_tdp_page_fault), - .nx_huge_page_workaround_enabled =3D is_nx_huge_page_enabled(), + .nx_huge_page_workaround_enabled =3D + is_nx_huge_page_enabled(vcpu->kvm), =20 .max_level =3D KVM_MAX_HUGEPAGE_LEVEL, .req_level =3D PG_LEVEL_4K, diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c index cda1851ec155..f5d0977590f6 100644 --- a/arch/x86/kvm/mmu/spte.c +++ b/arch/x86/kvm/mmu/spte.c @@ -147,7 +147,7 @@ bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_pa= ge *sp, spte |=3D spte_shadow_accessed_mask(spte); =20 if (level > PG_LEVEL_4K && (pte_access & ACC_EXEC_MASK) && - is_nx_huge_page_enabled()) { + is_nx_huge_page_enabled(vcpu->kvm)) { pte_access &=3D ~ACC_EXEC_MASK; } =20 @@ -246,7 +246,8 @@ static u64 make_spte_executable(u64 spte) * This is used during huge page splitting to build the SPTEs that make up= the * new page table. */ -u64 make_huge_page_split_spte(u64 huge_spte, int huge_level, int index) +u64 make_huge_page_split_spte(struct kvm *kvm, u64 huge_spte, int huge_lev= el, + int index) { u64 child_spte; int child_level; @@ -274,7 +275,7 @@ u64 make_huge_page_split_spte(u64 huge_spte, int huge_l= evel, int index) * When splitting to a 4K page, mark the page executable as the * NX hugepage mitigation no longer applies. */ - if (is_nx_huge_page_enabled()) + if (is_nx_huge_page_enabled(kvm)) child_spte =3D make_spte_executable(child_spte); } =20 diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h index 0127bb6e3c7d..529b76ab8f46 100644 --- a/arch/x86/kvm/mmu/spte.h +++ b/arch/x86/kvm/mmu/spte.h @@ -425,7 +425,8 @@ bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_pa= ge *sp, unsigned int pte_access, gfn_t gfn, kvm_pfn_t pfn, u64 old_spte, bool prefetch, bool can_unsync, bool host_writable, u64 *new_spte); -u64 make_huge_page_split_spte(u64 huge_spte, int huge_level, int index); +u64 make_huge_page_split_spte(struct kvm *kvm, u64 huge_spte, int huge_lev= el, + int index); u64 make_nonleaf_spte(u64 *child_pt, bool ad_disabled); u64 make_mmio_spte(struct kvm_vcpu *vcpu, u64 gfn, unsigned int access); u64 mark_spte_for_access_track(u64 spte); diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index 841feaa48be5..e3aef187dc50 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -1488,7 +1488,7 @@ static int tdp_mmu_split_huge_page(struct kvm *kvm, s= truct tdp_iter *iter, * not been linked in yet and thus is not reachable from any other CPU. */ for (i =3D 0; i < PT64_ENT_PER_PAGE; i++) - sp->spt[i] =3D make_huge_page_split_spte(huge_spte, level, i); + sp->spt[i] =3D make_huge_page_split_spte(kvm, huge_spte, level, i); =20 /* * Replace the huge spte with a pointer to the populated lower level diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 33653a008b28..cfa7d87a92ee 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4318,6 +4318,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, lon= g ext) case KVM_CAP_SYS_ATTRIBUTES: case KVM_CAP_VAPIC: case KVM_CAP_ENABLE_CAP: + case KVM_CAP_VM_DISABLE_NX_HUGE_PAGES: r =3D 1; break; case KVM_CAP_EXIT_HYPERCALL: @@ -6125,6 +6126,35 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, } mutex_unlock(&kvm->lock); break; + case KVM_CAP_VM_DISABLE_NX_HUGE_PAGES: + r =3D -EINVAL; + + /* + * Since the risk of disabling NX hugepages is a guest crashing + * the system, ensure the userspace process has permission to + * reboot the system. + * + * Note that unlike the reboot() syscall, the process must have + * this capability in the root namespace because exposing + * /dev/kvm into a container does not limit the scope of the + * iTLB multihit bug to that container. In other words, + * this must use capable(), not ns_capable(). + */ + if (!capable(CAP_SYS_BOOT)) { + r =3D -EPERM; + break; + } + + if (cap->args[0]) + break; + + mutex_lock(&kvm->lock); + if (!kvm->created_vcpus) { + kvm->arch.disable_nx_huge_pages =3D true; + r =3D 0; + } + mutex_unlock(&kvm->lock); + break; default: r =3D -EINVAL; break; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 5088bd9f1922..8e55ed67b867 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1157,6 +1157,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_VM_TSC_CONTROL 214 #define KVM_CAP_SYSTEM_EVENT_DATA 215 #define KVM_CAP_ARM_SYSTEM_SUSPEND 216 +#define KVM_CAP_VM_DISABLE_NX_HUGE_PAGES 217 =20 #ifdef KVM_CAP_IRQ_ROUTING =20 --=20 2.36.1.124.g0e6072fb45-goog From nobody Wed Apr 29 00:43:01 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 A9C02C4332F for ; Thu, 26 May 2022 17:55:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348577AbiEZRzB (ORCPT ); Thu, 26 May 2022 13:55:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50372 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348417AbiEZRyf (ORCPT ); Thu, 26 May 2022 13:54:35 -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 2CF52AF1C7 for ; Thu, 26 May 2022 10:54:26 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id o18-20020a63fb12000000b003fb22d1c6a0so957609pgh.12 for ; Thu, 26 May 2022 10:54:26 -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=Gbi/sedZET/zdh3Sj6stt7i603Maf3FW/BMVimtE9Dk=; b=RNAY/9X/J49yUlxi8AKv1KkXRYKZgi2PVinBAREd+jVpM+5cwAOYppy0mI01VfqmuD XaGRYp2JTW2yv3ibXEtx3Hff3uMup4mbPnEKt7nr6eHxB78t9CC40BM1PjdTsj0Xuqpm fv3EHLNgYDiFhZ6bAY5qung9sKodPn/4VzOYBuK6JufQFVu+BDvYYtxmOtfQaGhC+u4s NHCWNQHN5ZYGWcEgPSyEt8kMmczP2vHVUMOBo1geViZYNayZ0kn8mz1J1at6LWIMyY0H ve4Ypnk5M5fknwtsx24lQb5SEgIVvrpDrxL5uwCh5+fAOWovFBnQHVZrzzSPFWkH8bMA cuyA== 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=Gbi/sedZET/zdh3Sj6stt7i603Maf3FW/BMVimtE9Dk=; b=3hC4c2GIAePSxFGTdfpKRPe2zBcMLMIqnwyY4SpjqzS4xLW3aJpIaEbWcL5hp+cmaG IwLhksGak8/3eLkRE574DosvDnaZNZksTHT439q/KGAVCOn0LvdsZ9b+ADRILqcqFVqK NeMd/JRcBCMU9hYfqRRC4A9Aip66VCFWDWj7WhV86qpg+5xmw23evX0o5NKheO9eSy06 r7VeVyqHqQWEkOfx3j9HbM3bVeCXM2Lxq6tm7l3B1ihpIVmgEUGKXXJZEHY6HqQaTuQZ E/0CafHHVYCFlJrPSD/tf27sw/ptqxMEBe9yRz5bkUn9+AwZX1ZE4RcWlpcJaz1h+3+O iNEQ== X-Gm-Message-State: AOAM531EkGmXM3uB0mT/PK56AbhoB3M+v7gbxgNLnPaSSxRu75si3vUq CsDZ5GlbfTAzTz1Kp+RwMhNXi75QZHIC X-Google-Smtp-Source: ABdhPJxIwN1/7gxgK2uJEkp1UJVizd20EAW3Jwz+1LpuZ9Fz7N2mp3FRBVeQ8fWCXijwEYhaEYArtzfJllV+ X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:aa7:8b57:0:b0:518:7003:e28e with SMTP id i23-20020aa78b57000000b005187003e28emr32272726pfd.28.1653587666160; Thu, 26 May 2022 10:54:26 -0700 (PDT) Date: Thu, 26 May 2022 17:54:06 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-10-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 09/11] KVM: selftests: Factor out calculation of pages needed for a VM From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Factor out the calculation of the number of pages needed for a VM to make it easier to separate creating the VM and adding vCPUs. Reviewed-by: David Matlack Reviewed-by: Peter Xu Signed-off-by: Ben Gardon --- .../selftests/kvm/include/kvm_util_base.h | 4 ++ tools/testing/selftests/kvm/lib/kvm_util.c | 59 ++++++++++++++----- 2 files changed, 47 insertions(+), 16 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 035168cec451..3c9898c59ea1 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -312,6 +312,10 @@ vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_= t num, vm_paddr_t paddr_min, uint32_t memslot); vm_paddr_t vm_alloc_page_table(struct kvm_vm *vm); =20 +uint64_t vm_pages_needed(enum vm_guest_mode mode, uint32_t nr_vcpus, + uint64_t slot0_mem_pages, uint64_t extra_mem_pages, + uint32_t num_percpu_pages); + /* * Create a VM with reasonable defaults * diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 200d3bb803e0..385f249c2dc5 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -377,7 +377,7 @@ struct kvm_vm *vm_create_without_vcpus(enum vm_guest_mo= de mode, uint64_t pages) } =20 /* - * VM Create with customized parameters + * Get the number of pages needed for a VM * * Input Args: * mode - VM Mode (e.g. VM_MODE_P52V48_4K) @@ -385,27 +385,17 @@ struct kvm_vm *vm_create_without_vcpus(enum vm_guest_= mode mode, uint64_t pages) * slot0_mem_pages - Slot0 physical memory size * extra_mem_pages - Non-slot0 physical memory total size * num_percpu_pages - Per-cpu physical memory pages - * guest_code - Guest entry point - * vcpuids - VCPU IDs * * Output Args: None * * Return: - * Pointer to opaque structure that describes the created VM. - * - * Creates a VM with the mode specified by mode (e.g. VM_MODE_P52V48_4K), - * with customized slot0 memory size, at least 512 pages currently. - * extra_mem_pages is only used to calculate the maximum page table size, - * no real memory allocation for non-slot0 memory in this function. + * The number of pages needed for the VM. */ -struct kvm_vm *vm_create_with_vcpus(enum vm_guest_mode mode, uint32_t nr_v= cpus, - uint64_t slot0_mem_pages, uint64_t extra_mem_pages, - uint32_t num_percpu_pages, void *guest_code, - uint32_t vcpuids[]) +uint64_t vm_pages_needed(enum vm_guest_mode mode, uint32_t nr_vcpus, + uint64_t slot0_mem_pages, uint64_t extra_mem_pages, + uint32_t num_percpu_pages) { uint64_t vcpu_pages, extra_pg_pages, pages; - struct kvm_vm *vm; - int i; =20 /* Force slot0 memory size not small than DEFAULT_GUEST_PHY_PAGES */ if (slot0_mem_pages < DEFAULT_GUEST_PHY_PAGES) @@ -421,11 +411,48 @@ struct kvm_vm *vm_create_with_vcpus(enum vm_guest_mod= e mode, uint32_t nr_vcpus, extra_pg_pages =3D (slot0_mem_pages + extra_mem_pages + vcpu_pages) / PTE= S_PER_MIN_PAGE * 2; pages =3D slot0_mem_pages + vcpu_pages + extra_pg_pages; =20 + pages =3D vm_adjust_num_guest_pages(mode, pages); + + return pages; +} + +/* + * VM Create with customized parameters + * + * Input Args: + * mode - VM Mode (e.g. VM_MODE_P52V48_4K) + * nr_vcpus - VCPU count + * slot0_mem_pages - Slot0 physical memory size + * extra_mem_pages - Non-slot0 physical memory total size + * num_percpu_pages - Per-cpu physical memory pages + * guest_code - Guest entry point + * vcpuids - VCPU IDs + * + * Output Args: None + * + * Return: + * Pointer to opaque structure that describes the created VM. + * + * Creates a VM with the mode specified by mode (e.g. VM_MODE_P52V48_4K), + * with customized slot0 memory size, at least 512 pages currently. + * extra_mem_pages is only used to calculate the maximum page table size, + * no real memory allocation for non-slot0 memory in this function. + */ +struct kvm_vm *vm_create_with_vcpus(enum vm_guest_mode mode, uint32_t nr_v= cpus, + uint64_t slot0_mem_pages, uint64_t extra_mem_pages, + uint32_t num_percpu_pages, void *guest_code, + uint32_t vcpuids[]) +{ + uint64_t pages; + struct kvm_vm *vm; + int i; + TEST_ASSERT(nr_vcpus <=3D kvm_check_cap(KVM_CAP_MAX_VCPUS), "nr_vcpus =3D %d too large for host, max-vcpus =3D %d", nr_vcpus, kvm_check_cap(KVM_CAP_MAX_VCPUS)); =20 - pages =3D vm_adjust_num_guest_pages(mode, pages); + pages =3D vm_pages_needed(mode, nr_vcpus, slot0_mem_pages, + extra_mem_pages, num_percpu_pages); =20 vm =3D vm_create_without_vcpus(mode, pages); =20 --=20 2.36.1.124.g0e6072fb45-goog From nobody Wed Apr 29 00:43:01 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 280D0C433EF for ; Thu, 26 May 2022 17:55:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230460AbiEZRzO (ORCPT ); Thu, 26 May 2022 13:55:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50486 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348437AbiEZRyg (ORCPT ); Thu, 26 May 2022 13:54:36 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D4234B36F9 for ; Thu, 26 May 2022 10:54:28 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id d5-20020a17090a564500b001e031a8ad45so1446658pji.6 for ; Thu, 26 May 2022 10:54:28 -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=SXKeF9OqpGDpuoZVxsYVRtbB7K2x8FBA+P2quq827+Y=; b=nQo/6U11xPzxsdoihbiqFl4qSug+H3g3Qb7ocCUM0EGUDx+1gRyq8RPo8YXgvdyVMy Z1XDj1eysHJdfANHU0+Cn8tAQsjUhNIuM5a+0C982JyL4frVMd5XBhHq0AWED6DouJ9N eGwPRmd6l9dnqL0R+CyGOKYIidCD/mZEub53/pLOeSryTO92bRuPZWZUoprtCBvsmIKm ALwjBsCaiC/cZvspVuy4i/SFAaej7vjrSZH55yzFfmGPh0qPSHrASwKE5aO+j6w4zvwT 42kSICns53DkkOkeb6unR/OhSg6ta3PTI160HerUDSXTHf2VWeVD8k533Q2egV+3XnHd gk6Q== 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=SXKeF9OqpGDpuoZVxsYVRtbB7K2x8FBA+P2quq827+Y=; b=yV8vTrFYs7I3WHjF05OjC06+OSkzt+TQu1e1axIUJK6XkQryAvjeBVryIxJlHk+3wV H8C5QsI6OGeTNzJAJ4C0z6E6E002ufuizBGFo4ZSjW2YL+zx2jOG4YcK469xdEcEKnqw IhoiTtr6fRjvvD2wMCi3PhIIH6xIuztsJhapdoEembC4zMTNHxcziYr8bpOugdoXlMK0 hSGz1NW/hcsh3yUXxIzvtKe1yPsgPP/0mulmdUCyyF6GEks8U4joHTVS46cTVyAnZ9MR V0f7OLoUpJzAAe2ZyLGlJbARunYwX3bLUGBD8gEyS0DhVKK/ynyHOHre/K/gIWljnO1Z c46Q== X-Gm-Message-State: AOAM531kxtj6foQ1M70mNNOjwPZr54QXDT10XHoMA3gupj1V4Qf2R9HY Yv1+8I2A5C2ZUo8kVriXLC5aYA0tqkPN X-Google-Smtp-Source: ABdhPJzQKWFwdJlvIOv1OxlOvp4R5BCgNe1G7CZ5JXEB0H+2A6fAwaYggU549C56tFWhaMBXwf4HLm4CmV4i X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a17:90a:778c:b0:1df:56a5:8474 with SMTP id v12-20020a17090a778c00b001df56a58474mr3839118pjk.63.1653587667713; Thu, 26 May 2022 10:54:27 -0700 (PDT) Date: Thu, 26 May 2022 17:54:07 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-11-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 10/11] KVM: selftests: Test disabling NX hugepages on a VM From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon 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 an argument to the NX huge pages test to test disabling the feature on a VM using the new capability. Reviewed-by: David Matlack Signed-off-by: Ben Gardon --- .../selftests/kvm/include/kvm_util_base.h | 2 + tools/testing/selftests/kvm/lib/kvm_util.c | 27 +++- .../selftests/kvm/x86_64/nx_huge_pages_test.c | 140 ++++++++++++------ .../kvm/x86_64/nx_huge_pages_test.sh | 14 +- 4 files changed, 133 insertions(+), 50 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 3c9898c59ea1..6aa06a312250 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -447,4 +447,6 @@ static inline uint64_t vm_get_stat(struct kvm_vm *vm, c= onst char *stat_name) =20 uint32_t guest_get_vcpuid(void); =20 +int __vm_disable_nx_huge_pages(struct kvm_vm *vm); + #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 385f249c2dc5..33d4d64c1391 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -112,6 +112,11 @@ int vm_check_cap(struct kvm_vm *vm, long cap) return ret; } =20 +static int __vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap) +{ + return ioctl(vm->fd, KVM_ENABLE_CAP, cap); +} + /* VM Enable Capability * * Input Args: @@ -128,7 +133,7 @@ int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_= cap *cap) { int ret; =20 - ret =3D ioctl(vm->fd, KVM_ENABLE_CAP, cap); + ret =3D __vm_enable_cap(vm, cap); TEST_ASSERT(ret =3D=3D 0, "KVM_ENABLE_CAP IOCTL failed,\n" " rc: %i errno: %i", ret, errno); =20 @@ -2718,3 +2723,23 @@ void __vm_get_stat(struct kvm_vm *vm, const char *st= at_name, uint64_t *data, free(stats_desc); close(stats_fd); } + +/* VM disable NX huge pages + * + * Input Args: + * vm - Virtual Machine + * + * Output Args: None + * + * Return: On success, 0. -ERRNO on failure. + * + * Disables NX huge pages for the VM. + */ +int __vm_disable_nx_huge_pages(struct kvm_vm *vm) +{ + struct kvm_enable_cap cap =3D { 0 }; + + cap.cap =3D KVM_CAP_VM_DISABLE_NX_HUGE_PAGES; + cap.args[0] =3D 0; + return __vm_enable_cap(vm, &cap); +} diff --git a/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c b/tool= s/testing/selftests/kvm/x86_64/nx_huge_pages_test.c index 09e05cda3dcd..9ff554a572c0 100644 --- a/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c +++ b/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c @@ -107,52 +107,37 @@ static void wait_for_reclaim(int reclaim_period_ms) nanosleep(&ts, NULL); } =20 -static void help(char *name) -{ - puts(""); - printf("usage: %s [-h] [-p period_ms] [-t token]\n", name); - puts(""); - printf(" -p: The NX reclaim period in miliseconds.\n"); - printf(" -t: The magic token to indicate environment setup is done.\n"); - puts(""); - exit(0); -} - -int main(int argc, char **argv) +void run_test(int reclaim_period_ms, bool disable_nx_huge_pages, + bool reboot_permissions) { - int reclaim_period_ms =3D 0, token =3D 0, opt; struct kvm_vm *vm; + uint64_t pages; void *hva; - - while ((opt =3D getopt(argc, argv, "hp:t:")) !=3D -1) { - switch (opt) { - case 'p': - reclaim_period_ms =3D atoi(optarg); - break; - case 't': - token =3D atoi(optarg); - break; - case 'h': - default: - help(argv[0]); - break; + int r; + + pages =3D vm_pages_needed(VM_MODE_DEFAULT, 1, DEFAULT_GUEST_PHY_PAGES, + 0, 0); + vm =3D vm_create_without_vcpus(VM_MODE_DEFAULT, pages); + + if (disable_nx_huge_pages) { + /* + * Cannot run the test without NX huge pages if the kernel + * does not support it. + */ + if (!kvm_check_cap(KVM_CAP_VM_DISABLE_NX_HUGE_PAGES)) + return; + + r =3D __vm_disable_nx_huge_pages(vm); + if (reboot_permissions) { + TEST_ASSERT(!r, "Disabling NX huge pages should succeed if process has = reboot permissions"); + } else { + TEST_ASSERT(r =3D=3D -1 && errno =3D=3D EPERM, + "This process should not have permission to disable NX huge pages"= ); + return; } } =20 - if (token !=3D MAGIC_TOKEN) { - print_skip("This test must be run with the magic token %d.\n" - "This is done by nx_huge_pages_test.sh, which\n" - "also handles environment setup for the test.", - MAGIC_TOKEN); - exit(KSFT_SKIP); - } - - if (!reclaim_period_ms) { - print_skip("The NX reclaim period must be specified and non-zero"); - exit(KSFT_SKIP); - } - - vm =3D vm_create_default(0, 0, guest_code); + vm_vcpu_add_default(vm, 0, guest_code); =20 vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS_HUGETLB, HPAGE_GPA, HPAGE_SLOT, @@ -185,31 +170,38 @@ int main(int argc, char **argv) /* * Next, the guest will execute from the first huge page, causing it * to be remapped at 4k. + * + * If NX huge pages are disabled, this should have no effect. */ vcpu_run(vm, 0); - check_2m_page_count(vm, 1); - check_split_count(vm, 1); + check_2m_page_count(vm, disable_nx_huge_pages ? 2 : 1); + check_split_count(vm, disable_nx_huge_pages ? 0 : 1); =20 /* * Executing from the third huge page (previously unaccessed) will * cause part to be mapped at 4k. + * + * If NX huge pages are disabled, it should be mapped at 2M. */ vcpu_run(vm, 0); - check_2m_page_count(vm, 1); - check_split_count(vm, 2); + check_2m_page_count(vm, disable_nx_huge_pages ? 3 : 1); + check_split_count(vm, disable_nx_huge_pages ? 0 : 2); =20 /* Reading from the first huge page again should have no effect. */ vcpu_run(vm, 0); - check_2m_page_count(vm, 1); - check_split_count(vm, 2); + check_2m_page_count(vm, disable_nx_huge_pages ? 3 : 1); + check_split_count(vm, disable_nx_huge_pages ? 0 : 2); =20 /* Give recovery thread time to run. */ wait_for_reclaim(reclaim_period_ms); =20 /* * Now that the reclaimer has run, all the split pages should be gone. + * + * If NX huge pages are disabled, the relaimer will not run, so + * nothing should change from here on. */ - check_2m_page_count(vm, 1); + check_2m_page_count(vm, disable_nx_huge_pages ? 3 : 1); check_split_count(vm, 0); =20 /* @@ -217,10 +209,62 @@ int main(int argc, char **argv) * reading from it causes a huge page mapping to be installed. */ vcpu_run(vm, 0); - check_2m_page_count(vm, 2); + check_2m_page_count(vm, disable_nx_huge_pages ? 3 : 2); check_split_count(vm, 0); =20 kvm_vm_free(vm); +} + +static void help(char *name) +{ + puts(""); + printf("usage: %s [-h] [-p period_ms] [-t token]\n", name); + puts(""); + printf(" -p: The NX reclaim period in miliseconds.\n"); + printf(" -t: The magic token to indicate environment setup is done.\n"); + printf(" -r: The test has reboot permissions and can disable NX huge page= s.\n"); + puts(""); + exit(0); +} + +int main(int argc, char **argv) +{ + int reclaim_period_ms =3D 0, token =3D 0, opt; + bool reboot_permissions =3D false; + + while ((opt =3D getopt(argc, argv, "hp:t:r")) !=3D -1) { + switch (opt) { + case 'p': + reclaim_period_ms =3D atoi(optarg); + break; + case 't': + token =3D atoi(optarg); + break; + case 'r': + reboot_permissions =3D true; + break; + case 'h': + default: + help(argv[0]); + break; + } + } + + if (token !=3D MAGIC_TOKEN) { + print_skip("This test must be run with the magic token %d.\n" + "This is done by nx_huge_pages_test.sh, which\n" + "also handles environment setup for the test.", + MAGIC_TOKEN); + exit(KSFT_SKIP); + } + + if (!reclaim_period_ms) { + print_skip("The NX reclaim period must be specified and non-zero"); + exit(KSFT_SKIP); + } + + run_test(reclaim_period_ms, false, reboot_permissions); + run_test(reclaim_period_ms, true, reboot_permissions); =20 return 0; } diff --git a/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh b/too= ls/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh index 4e090a84f5f3..6bd8e026ee61 100755 --- a/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh +++ b/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh @@ -20,6 +20,8 @@ function sudo_echo () { echo "$1" | sudo tee -a "$2" > /dev/null } =20 +NXECUTABLE=3D"$(dirname $0)/nx_huge_pages_test" + ( set -e =20 @@ -28,7 +30,17 @@ function sudo_echo () { sudo_echo 100 /sys/module/kvm/parameters/nx_huge_pages_recovery_period_ms sudo_echo "$(( $HUGE_PAGES + 3 ))" /sys/kernel/mm/hugepages/hugepages-204= 8kB/nr_hugepages =20 - "$(dirname $0)"/nx_huge_pages_test -t 887563923 -p 100 + # Test with reboot permissions + if [ $(whoami) !=3D "root" ] ; then + sudo setcap cap_sys_boot+ep $NXECUTABLE + fi + $NXECUTABLE -t 887563923 -p 100 -r + + # Test without reboot permissions + if [ $(whoami) !=3D "root" ] ; then + sudo setcap cap_sys_boot-ep $NXECUTABLE + $NXECUTABLE -t 887563923 -p 100 + fi ) RET=3D$? =20 --=20 2.36.1.124.g0e6072fb45-goog From nobody Wed Apr 29 00:43:01 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 0B46FC433F5 for ; Thu, 26 May 2022 17:55:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348404AbiEZRzT (ORCPT ); Thu, 26 May 2022 13:55:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51170 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240286AbiEZRyp (ORCPT ); Thu, 26 May 2022 13:54:45 -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 71F98C03BB for ; Thu, 26 May 2022 10:54:30 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id z186-20020a6233c3000000b00510a6bc2864so1309565pfz.10 for ; Thu, 26 May 2022 10:54:30 -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=FRI3yOd2jBqllb9cCkfyWs3M3poFKw/VaB/vECthXc0=; b=qaLYC8O0iC/49VvNbNC4/d+/0PPNhyiS1NmDCxgYJI6YRSk4bOI/2G1qfmi5uArvAr +ihmPwxft3+Xie9rw/VuqSYu1q+T7tg4iaOwyNwsEYOG7Y5ckgHyhSLDjMC7dvl4H0Sa 3UDvXdYrW1B2M3pqqDVFxus5CHojluv1mp8W6eVqHHIX/XI1Xejr4k6xpx1hKYpyjTzh q8fV6/jUKCI/EEG/JaukT2qQDAMPhS87QdMSAfoaDLGOe1zNnKoulrhr3ybYJ7d4NbGd 5th9CjEyr4mSvsn/ncspBqPm7JyDzgZfS0wmfaioWvJ4HZIUe27gUvYj2ytH3T2aa8I/ GQmw== 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=FRI3yOd2jBqllb9cCkfyWs3M3poFKw/VaB/vECthXc0=; b=PqKJnaKH2FKqFZDBXm9udohwJEXAMlIZryKeHgbpkEYjXkeNdm4U0alXbgRK8HXJFD yf2xMUtoTiCx7VFKO6EKddilZ37G2QH7DqZ/NA04l5ehWGA8Offkj2YyNDBqDfdGfWlx zRZTUwVQar99Xbh0J5VVCnsBKDqw5VCPo1cJv9V6VYnvIHRbSkfvSmGmsdHxMJY9p5zK GjCumhfnkR7DjlrLr7HprUrz4d1PiPYOhLn2ir22Ur23+UEDphiCtubNmx/Oo9Wn7HY8 jj6nm9IMrDyRGXeF17m2BUsgfOalNMD499EkL4F8/dkX3tex1GwAwoMawqcXtnEmtECy Hgog== X-Gm-Message-State: AOAM532lID3w/ZRSsIUB31ElSx3rH6wkSlHZEF8dEr7hcZMDKThImgBq Um1tS4WZo0EQQnos3qau92j32xVcDm4D X-Google-Smtp-Source: ABdhPJwiQksr/pw7CYHck0RR+tFA/cI985RJqtaX3uK/hhC4hDNVaZ2egzRl+njfFBnFaWvq9tHOXyPjVXcH X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a17:90b:1192:b0:1e0:63f3:c463 with SMTP id gk18-20020a17090b119200b001e063f3c463mr184161pjb.1.1653587669619; Thu, 26 May 2022 10:54:29 -0700 (PDT) Date: Thu, 26 May 2022 17:54:08 +0000 In-Reply-To: <20220526175408.399718-1-bgardon@google.com> Message-Id: <20220526175408.399718-12-bgardon@google.com> Mime-Version: 1.0 References: <20220526175408.399718-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v8 11/11] KVM: selftests: Cache binary stats metadata for duration of test From: Ben Gardon To: kvm@vger.kernel.org, Paolo Bonzini Cc: linux-kernel@vger.kernel.org, Peter Xu , Sean Christopherson , David Matlack , Jim Mattson , David Dunn , Jing Zhang , Junaid Shahid , Ben Gardon Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In order to improve performance across multiple reads of VM stats, cache the stats metadata in the VM struct. Signed-off-by: Ben Gardon --- tools/testing/selftests/kvm/lib/kvm_util.c | 32 ++++++++++--------- .../selftests/kvm/lib/kvm_util_internal.h | 5 +++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 33d4d64c1391..a32b7b4352b9 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -736,6 +736,12 @@ void kvm_vm_free(struct kvm_vm *vmp) if (vmp =3D=3D NULL) return; =20 + /* Free cached stats metadata and close FD */ + if (vmp->stats_fd) { + free(vmp->stats_desc); + close(vmp->stats_fd); + } + /* Free userspace_mem_regions. */ hash_for_each_safe(vmp->regions.slot_hash, ctr, node, region, slot_node) __vm_mem_region_delete(vmp, region, false); @@ -2694,34 +2700,30 @@ void read_stat_data(int stats_fd, struct kvm_stats_= header *header, void __vm_get_stat(struct kvm_vm *vm, const char *stat_name, uint64_t *dat= a, size_t max_elements) { - struct kvm_stats_desc *stats_desc; - struct kvm_stats_header header; struct kvm_stats_desc *desc; size_t size_desc; - int stats_fd; int i; =20 - stats_fd =3D vm_get_stats_fd(vm); - - read_stats_header(stats_fd, &header); - - stats_desc =3D read_stats_descriptors(stats_fd, &header); + if (!vm->stats_fd) { + vm->stats_fd =3D vm_get_stats_fd(vm); + read_stats_header(vm->stats_fd, &vm->stats_header); + vm->stats_desc =3D read_stats_descriptors(vm->stats_fd, + &vm->stats_header); + } =20 - size_desc =3D get_stats_descriptor_size(&header); + size_desc =3D get_stats_descriptor_size(&vm->stats_header); =20 - for (i =3D 0; i < header.num_desc; ++i) { - desc =3D (void *)stats_desc + (i * size_desc); + for (i =3D 0; i < vm->stats_header.num_desc; ++i) { + desc =3D (void *)vm->stats_desc + (i * size_desc); =20 if (strcmp(desc->name, stat_name)) continue; =20 - read_stat_data(stats_fd, &header, desc, data, max_elements); + read_stat_data(vm->stats_fd, &vm->stats_header, desc, + data, max_elements); =20 break; } - - free(stats_desc); - close(stats_fd); } =20 /* VM disable NX huge pages diff --git a/tools/testing/selftests/kvm/lib/kvm_util_internal.h b/tools/te= sting/selftests/kvm/lib/kvm_util_internal.h index a03febc24ba6..e753edd7b8d3 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util_internal.h +++ b/tools/testing/selftests/kvm/lib/kvm_util_internal.h @@ -67,6 +67,11 @@ struct kvm_vm { vm_vaddr_t idt; vm_vaddr_t handlers; uint32_t dirty_ring_size; + + /* Cache of information for binary stats interface */ + int stats_fd; + struct kvm_stats_header stats_header; + struct kvm_stats_desc *stats_desc; }; =20 struct vcpu *vcpu_find(struct kvm_vm *vm, uint32_t vcpuid); --=20 2.36.1.124.g0e6072fb45-goog