From nobody Mon Apr 27 11:29:25 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 C8B1CCCA47C for ; Mon, 13 Jun 2022 21:31:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352426AbiFMVba (ORCPT ); Mon, 13 Jun 2022 17:31:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60360 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353125AbiFMV3S (ORCPT ); Mon, 13 Jun 2022 17:29:18 -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 97D8C30F for ; Mon, 13 Jun 2022 14:25:28 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id p2-20020a170902e74200b00164081f682cso3635236plf.16 for ; Mon, 13 Jun 2022 14:25: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=85TvZ48xblqSeyK1ObCYU4jDiPNtGo9XwK9ZI/euUPA=; b=GlrUwH24qHzeQ9AganD4s3/3Ga/Btx+c2gJklWdAJr4qQa86y8XRjlNfiHKg3Ey5n5 RtEHIfspjhcsZzz3CEFeagPWopLPu3VvHGppUiV/T5E+AUl9RqnSqFUb7xD9aUSVm0TR uyQOknyKeIrN3StVJeJy7ZRZ8kAeNTnZS6/iESqszFSN7xQlQYRxCxDKvDBohMFsEkso b/77rfvP+me+dvvuxBgEdWsL+zWFDmYZ2ebe4x4yuYHFu8aoMo+xEpJc+2nIey5+N2Bv LSDQDD5xFhA3jatkW8ngSfgUGX5wrRy4CWwyLlhSyYFry+DNyd8MJorgfK1mJDG9dpk2 gbbA== 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=85TvZ48xblqSeyK1ObCYU4jDiPNtGo9XwK9ZI/euUPA=; b=HO+lfpF1jOsPfetMurjZtk1I60x7zCV+vBcZ+gV0Svw+0/ezOq+pY5GRScikVYUZ0a 5FuYYo09hG8YLWU2yPmrUVjCJfDVfUn9+P/kz0fQIMBZ4OiOfYyBAiIm7znrOIJUvply DupBEfFhUgzuHO1vKlFHhUnsAr8W1OE0LVu368O3BWfcNtZdnWv2/htAmdyShpuimlED qvrTfBCbBwvO3f83mMfGbiTsl/XfMxKUzNJn2iCgo4O8THdz+Lw50+QfOENp1pCX1cFL yQRyHce1AHD62jASu6XsjhUETPIiBPQsGpCU+SrhGKv2DtnNTni5+IdWZsL527KcwxKz RDAg== X-Gm-Message-State: AOAM5335CETZeI4RDhgT+VweGLsX0rbBm7rkvyQBEOrQQ9onRXJ5eZsB vxpLhGo/dUSGYn3PcD99xrfJWMqPiuMS X-Google-Smtp-Source: AGRyM1teZsQrTvOprp3xqHfR3ZP6vv0nwWhoMDiS4OVcjajPvm6qIOyxiRJQjnLWDjIo5LP2ad3IKe9CknIJ X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a62:820a:0:b0:51b:d1f9:b45f with SMTP id w10-20020a62820a000000b0051bd1f9b45fmr1253849pfd.63.1655155527858; Mon, 13 Jun 2022 14:25:27 -0700 (PDT) Date: Mon, 13 Jun 2022 21:25:14 +0000 In-Reply-To: <20220613212523.3436117-1-bgardon@google.com> Message-Id: <20220613212523.3436117-2-bgardon@google.com> Mime-Version: 1.0 References: <20220613212523.3436117-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH v9 01/10] 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 1baabf955d63..ae48d4153f85 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.476.g0c4daa206d-goog From nobody Mon Apr 27 11:29:25 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 7F52FC433EF for ; Mon, 13 Jun 2022 21:31:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352402AbiFMVbZ (ORCPT ); Mon, 13 Jun 2022 17:31:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353130AbiFMV3S (ORCPT ); Mon, 13 Jun 2022 17:29:18 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 09B9831D for ; Mon, 13 Jun 2022 14:25:30 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id n8-20020a170902d2c800b001663868e2c2so3627269plc.21 for ; Mon, 13 Jun 2022 14:25: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=q6y/cC7ApzMVwblo2wX2ATrZhvcsAJbJjDOeRfXShtw=; b=RN4Ahs2YdEGqhtKw34QQe3IO/xafb0O5TijAX1HUmRKqJ5SPvgQBNF9hDRuK4I/rLo IcP4HvdCBbNrtqzDZxXk4P7qWw1bf0z304OUkJ5gd4As+5RYdXhGQXAYpaUednwXsceK 1qr0bayaCTCYN4HzkgxTbjkceHZjHWESZt/7Iu3pOw8Lkv+Bbcuhfr6ACeDCeUas6G8O 9u6vj1t96vO0oufnlrHIFZAInvk/eCa+BqvV0btNPG22I7xBwCClYfYJzRoVbltrG2Eu iC8wXOPHRy11Ym07Ttf3LH4ulolEHI3AiwXY+QCE1QprbAj6S57opoZCh22HQ1I0sXtc nWpQ== 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=q6y/cC7ApzMVwblo2wX2ATrZhvcsAJbJjDOeRfXShtw=; b=oXtFJu4uKIHwWGfPJ5Mzpf03GbYr0HQNgg/d1EPddbPfm9CCa3dRNXEQaRhAN/2gwe 7+4CxVZQvayiFUpeYjZCkI77ALsErzTUtFOXVhyGK0B2rx7bB3KinspVFfHYtdlR24ry 0f5ru5+f7ofbUfB/iSA2O4jbUkYKVzom384qLZanNrzHNhNe/8dkDOsrok/hVpo2nwg0 sbbkYqVkIJ97ReMtY4e/CAlaze180ZvPT1mYDcQy//HchnUIoUSSyMPU81HaJyQWaj/4 vbRCAQxMRxjnQVfJ/z/rnzRURWBQQj6NYPBIOs4ghF/qBjGOENo0l20heAKIbLqlWy+5 gTfQ== X-Gm-Message-State: AJIora+stFRp8fIatsueV22/Wss6JWxgdjxykAOOjkLGeA/DCQQDx0sv Rk2/cuFhHxU611VafZFxQWDakci3WhI2 X-Google-Smtp-Source: AGRyM1vUtxSBaOadpUzI1R0wd/z2CXO0o1CfpyEq9BbjSFAphaDKd24NnJRz1w7VV3Qj/dH1ku1jH+IeLDz+ X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a17:90b:2247:b0:1e8:9f24:269a with SMTP id hk7-20020a17090b224700b001e89f24269amr774220pjb.14.1655155529508; Mon, 13 Jun 2022 14:25:29 -0700 (PDT) Date: Mon, 13 Jun 2022 21:25:15 +0000 In-Reply-To: <20220613212523.3436117-1-bgardon@google.com> Message-Id: <20220613212523.3436117-3-bgardon@google.com> Mime-Version: 1.0 References: <20220613212523.3436117-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH v9 02/10] 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 --- tools/testing/selftests/kvm/include/kvm_util_base.h | 8 ++++++++ tools/testing/selftests/kvm/kvm_binary_stats_test.c | 4 ++-- 2 files changed, 10 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 cdaea2383543..3d3dd144f427 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -303,6 +303,14 @@ static inline int vm_get_stats_fd(struct kvm_vm *vm) return fd; } =20 +static inline 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"); +} + void vm_create_irqchip(struct kvm_vm *vm); =20 void vm_set_user_memory_region(struct kvm_vm *vm, uint32_t slot, uint32_t = flags, diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/te= sting/selftests/kvm/kvm_binary_stats_test.c index ae48d4153f85..64db17faacd2 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 */ --=20 2.36.1.476.g0c4daa206d-goog From nobody Mon Apr 27 11:29:25 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 D9F50CCA47B for ; Mon, 13 Jun 2022 21:30:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352015AbiFMVaC (ORCPT ); Mon, 13 Jun 2022 17:30:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60372 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353142AbiFMV3T (ORCPT ); Mon, 13 Jun 2022 17:29:19 -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 16457382 for ; Mon, 13 Jun 2022 14:25:32 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id 18-20020a621512000000b0051b90b3a793so2844366pfv.8 for ; Mon, 13 Jun 2022 14:25:32 -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=NphrsrvGM2ysfafA1BnbkDe+v8oridLj8hF4hpwL2dk=; b=UaWigyO27u2sBfxzJ5wByM0XODuTu6u5V7qsHyfP/HPKyAOcmdvCHk1hwQvAgh4ruy Qd/rkJnn9bdgQRvedE1ZXlUV6Aa/Ke9FSLA+s0trhhwy8iJNrIfSJAjxcfn5ZziS9LYY suku1u+ummjIygddnqgUKWI4xap5mZhk0oCYNVVMSjhKoRMVNap2wtYmj+ceoDRwE3YP ZByl5fn4fjZkLqqT7+yhm7ZiztK45KGa3jnECz8cVDFzZXUQGjwQ50Tdpm6EPex/cqH2 uwTPUFFpH3Wr5Xn5vVJgN7Pvt13j/LOfdQ0HKE0APVdEbXU7jX7ZiWxqwzlGq5vriCYX wO0Q== 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=NphrsrvGM2ysfafA1BnbkDe+v8oridLj8hF4hpwL2dk=; b=w8r30+R0vd3ftHU5KyoUOjEy3GzjZ03f1tdtC6k0hpS4iHuH/CK1SE5j//Xh9megG2 +eE+zXilF09zT1mdJAcY1E9AUjyBdldztzMLqEk5XzMKDPGLVyl9gQkEwcuoy3piUIDn gO8bL5GLYyzlYdwbTcyb1YVZFzVIIPFkGZM01YecCMRWn5pU8XdDnNBlV03KVgv1stGT VRavvUdhdzPwodd8fhvVYVyOc/pCVj1Q42EytHbQzKjFfXgFHtVSWA/t/LgFnGvJQ3M1 Zgnavpyye+E9GIjVPsPQxQCh6BFU3lR6wMGPSJFE1bFjU7CO74OoWS/AfMrkY/QlJ4sg Qnpg== X-Gm-Message-State: AJIora92g6P1q+sIlrkY+G1QEgn6Q0RpsMuaPyOHtSaZ0RoSevKUTXMy sSO1BmN2+QTbGNcZnc3dagN4m4YXWA2x X-Google-Smtp-Source: AGRyM1uIxj1wGiaZ4qlThdtRyOdAttssYwQlrUBe6mjmg1rt0zRK6XHQtdF7fki40BpGMsRRihfZ2oz0TLCt X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a17:902:f688:b0:163:ee37:91c5 with SMTP id l8-20020a170902f68800b00163ee3791c5mr959491plg.86.1655155531550; Mon, 13 Jun 2022 14:25:31 -0700 (PDT) Date: Mon, 13 Jun 2022 21:25:16 +0000 In-Reply-To: <20220613212523.3436117-1-bgardon@google.com> Message-Id: <20220613212523.3436117-4-bgardon@google.com> Mime-Version: 1.0 References: <20220613212523.3436117-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH v9 03/10] 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 | 25 ++++++++++++++ .../selftests/kvm/kvm_binary_stats_test.c | 16 +++------ tools/testing/selftests/kvm/lib/kvm_util.c | 33 +++++++++++++++++++ 3 files changed, 63 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 3d3dd144f427..6c66c6ef485b 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -311,6 +311,31 @@ static inline void read_stats_header(int stats_fd, str= uct kvm_stats_header *head TEST_ASSERT(ret =3D=3D sizeof(*header), "Read stats header"); } =20 +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); +} + void vm_create_irqchip(struct kvm_vm *vm); =20 void vm_set_user_memory_region(struct kvm_vm *vm, uint32_t slot, uint32_t = flags, diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/te= sting/selftests/kvm/kvm_binary_stats_test.c index 64db17faacd2..9d3b9a0ce2ef 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 39f2f5f1338f..fc957a385a0a 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1857,3 +1857,36 @@ unsigned int vm_calc_num_guest_pages(enum vm_guest_m= ode mode, size_t size) n =3D DIV_ROUND_UP(size, vm_guest_mode_params[mode].page_size); return vm_adjust_num_guest_pages(mode, n); } + +/* + * 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.476.g0c4daa206d-goog From nobody Mon Apr 27 11:29:25 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 152EDC433EF for ; Mon, 13 Jun 2022 21:30:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351959AbiFMVak (ORCPT ); Mon, 13 Jun 2022 17:30:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57842 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353152AbiFMV3W (ORCPT ); Mon, 13 Jun 2022 17:29:22 -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 C83F0393 for ; Mon, 13 Jun 2022 14:25:33 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id b1-20020a631b41000000b003fd9e4765f4so3921012pgm.10 for ; Mon, 13 Jun 2022 14:25:33 -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=Kj1m4/hp4yXa0MCKZFilZvFRZAcbfqXBAQSF/QNTX0I=; b=Ejx7pQeJpfGG0NaTdJvphAGp4nv3Ihs+s1AJftLby+RDwLbq4kgntxJuqvoKueo8hx 54rII6yXHK1HDJLoL27lmAg6Gwxs7HF+a3ym+KNQ1iJoz7SGrB85nWOH0hONhmj0qCMp whi/Ro+Gsr2v38mem6shBBdglqIXrMBlo991Eo8vUytdJhwVRIAigHdnznxg2Nci3HEn ru93AOURfwT6gVAHQg26kGqkhaHgD3YW3+PpylZzhAOm57FKdVxrD36AWjxE/aSZmhOb 8j7bqHKQMY6bDvQvgczyM6YQ6Dtc3aSEFeg0kd8/FQUA00qoHJifBIY2Lqo5wmJ2FmM3 GfOQ== 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=Kj1m4/hp4yXa0MCKZFilZvFRZAcbfqXBAQSF/QNTX0I=; b=jQ29LZ0TG/KGY+RUpKIHUBpInHO4Kam1Qdx89W/m8Hg/jPIM1K9i9ceTgKUJeu/EBc BWy7AyhLn2BO8z2MbaDhsC591313M2FXXfb+KNod+1bnfeUuGdpDAu4yY9AZK++lqYDC QiIFHZ1vtjnCwkzIBtYl26B5UfanBAOpz+1N2SAO03/Di34ryK+ndP4U3BRTLOqXwNqm RDshTi9jzv8n+Rx2DFo3K5jq0b2+zF9pcjJBQhfDRzkA+PWliU5eSvMt43h2cFMQW+FS hwuR/quhjvbUOH+j2Ok/Xpj9uq+p9IZEJfddMrLSn1IG7C4VL0j5YuOtfxBqQwY6yePX CZSw== X-Gm-Message-State: AJIora92a+5buO8M4IeIBuKmEW3V+P5fLqmgizr9lOTA2PjsXuEnGQnu sJFYNIH0lqa9tIcEgMzTsbk0Q2nKn+Lr X-Google-Smtp-Source: AGRyM1smgvIZPd4Fy0LJ7U8fw816XS0spLgdGPVjYHUYW8dPHNfQ3e1xW40sIVmdC2nvZP1ZeTLY6Y+cAqme X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a17:903:1d2:b0:168:e3b9:e62b with SMTP id e18-20020a17090301d200b00168e3b9e62bmr981167plh.115.1655155533185; Mon, 13 Jun 2022 14:25:33 -0700 (PDT) Date: Mon, 13 Jun 2022 21:25:17 +0000 In-Reply-To: <20220613212523.3436117-1-bgardon@google.com> Message-Id: <20220613212523.3436117-5-bgardon@google.com> Mime-Version: 1.0 References: <20220613212523.3436117-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH v9 04/10] 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 9d3b9a0ce2ef..3002fab2bbf1 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.476.g0c4daa206d-goog From nobody Mon Apr 27 11:29:26 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 76461C43334 for ; Mon, 13 Jun 2022 21:30:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235022AbiFMVae (ORCPT ); Mon, 13 Jun 2022 17:30:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60458 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353164AbiFMV3W (ORCPT ); Mon, 13 Jun 2022 17:29:22 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B856B397 for ; Mon, 13 Jun 2022 14:25:35 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id k73-20020a25244c000000b0065ca88b381aso6033299ybk.2 for ; Mon, 13 Jun 2022 14:25:35 -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=ZzUThN+xouEXvquQYC3DjLFRmnBgRRe1A4CrkgI7ln4=; b=sHRyLYL421Xs0PblSrY0pePkWWuCbev2uWNsbFVqXMw40pLxEjaugtFZH9hHbSx7HR 1NRAaX3xND50k/oiJGPt2gfpQw5CCLDxrwJ1UddD3gWct9pbidECcF7B0SiF2sZj1Fi7 jhMPI8hV3cd37iDSymmTrD8JUZL8E4M1t/6n0Uy16fIpFJRGWTDuy0ToyJQaujRUPAwi /jSl4bUG8WzViV5GMDtPalVnzRSw81d+nyCjDLsK7uaQFuNNemWBTka3EPFqYXyLoCq1 oqjRs/x595w3x3i7jjjg9Q/p31wQHgWAVTtF/0CNX7Xl6kkXITVorHa5fHfB9KAaBP0K XAUA== 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=ZzUThN+xouEXvquQYC3DjLFRmnBgRRe1A4CrkgI7ln4=; b=XCfTUVcOmQUVqgDHsnvXEDwh7w3YnmAXhKi8X2jJXIXCcw1yMW4t5ROEE4mpBitA4q NaSE/qBgqz/Cy2B89qhQ6x09fpXqWm1jy5st8CUwHL/quXS7xX36lzWIr7VFUWWTFYUQ 98bA/N8ho5OHLeRO5BC1CGy5y+BzdhSyqm/29Wd3boQVVmVK6PNTSqw4QoB8QHyb4cK5 85ksYmLLoxvFpLtIiawXKPWmSs1R5KF4EkYOCOvsOQ9tNFySv3T6Exn3zWIZkex6l4dD ex3UFCqtlGnXMTjFWx4HEllx2FNm7EGEk0JdFQuaFLsrequtUoaZWObHySf7L/P2qNRk 72Hw== X-Gm-Message-State: AJIora+d5xdx6e4beMUj2Q8Smt+R5laYFjKww/ilNQrVVrxnQz7jTqUT EnN45KHUylnt6NxJmHvRSTKBHDbMqyr0 X-Google-Smtp-Source: AGRyM1sXk21WOlgWX4dQMcaAZ1rEcbnnYGTFH9DeiQwG9O2E9jG7cqqfX4nk+5lfn4xuFhinU/bIu6fC/ZmM X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a81:a95:0:b0:30c:7063:ff2e with SMTP id 143-20020a810a95000000b0030c7063ff2emr1915851ywk.65.1655155534947; Mon, 13 Jun 2022 14:25:34 -0700 (PDT) Date: Mon, 13 Jun 2022 21:25:18 +0000 In-Reply-To: <20220613212523.3436117-1-bgardon@google.com> Message-Id: <20220613212523.3436117-6-bgardon@google.com> Mime-Version: 1.0 References: <20220613212523.3436117-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH v9 05/10] 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 6c66c6ef485b..aa7f8b681944 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -336,6 +336,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); + void vm_create_irqchip(struct kvm_vm *vm); =20 void vm_set_user_memory_region(struct kvm_vm *vm, uint32_t slot, uint32_t = flags, diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/te= sting/selftests/kvm/kvm_binary_stats_test.c index 3002fab2bbf1..98b882ec8f98 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 fc957a385a0a..5b8249a0e1de 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1890,3 +1890,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.476.g0c4daa206d-goog From nobody Mon Apr 27 11:29:26 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 1C995C433EF for ; Mon, 13 Jun 2022 21:30:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237309AbiFMVaT (ORCPT ); Mon, 13 Jun 2022 17:30:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353172AbiFMV3W (ORCPT ); Mon, 13 Jun 2022 17:29:22 -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 0F1F9C43 for ; Mon, 13 Jun 2022 14:25:37 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id n8-20020a635908000000b00401a7b6235bso3934201pgb.5 for ; Mon, 13 Jun 2022 14:25:37 -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=hFr8PsWzXcCevW+O39uLVgaDSEuW1J+A2EXvpoU3Ydw=; b=n3JixA5ALbnkM7954Xw2FPC9bUJXKQeMSjcwlBzNz0tqVY4KZZkOlO+3dwN9Sf42WI QPECHfX77X2oXjnwrENIuz3a0BG18RI9I9VpeZO8u/Xe7dO4QqbaEjCnxJ2KG1JHKcMJ fPUBqxKa4/FlYFo8jhax/MrVDu/esJMwO3Bkk4gKvLVrJBnKF1iq1KPlKWB0Qnai6J5e iGm+KMD17kV8evIuhJ1AFx2F2hO1IjHmRiaMPJkTScxfqXYbtcnijF5UIN/Ng7Q3QEYI bn/H7M1AdlN0PqJjYk4ZsC67e5BJlziS+asRFZw0uR0+d8DTGxmvzI6sDi5oEJLGgN2Q mVQQ== 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=hFr8PsWzXcCevW+O39uLVgaDSEuW1J+A2EXvpoU3Ydw=; b=ePUTinRVjrDMc/VVsuuzuvt2TdMiptnTCpXTm6wClzqbMU0+zbL2X9WndA6Edi5nS+ 0drrlW1yJIuMovXwFyzmkqIwRGWGbCIwGecXmRbRPWLGiZlQP2etPe+EtEAUkpYtevFE qokL3ntSUF4DVSWaEO2c+hT7RV7v3i/zt6XpPzJC8Xms+SAE7otv3DRYxZzDWni+dHYH 8L/Zix56jYuJuU1d9vJyElCDqvqDm1qSv1kZlbGMbgApsDDuGJS9lYBOqmGxff5/iawL T/3Q4ae2mBcrU++GM5+V2Txj7+adRPtWay+5XEDm9RZjhJdh/x0FaI6dqZyO9ywjpD5a kViw== X-Gm-Message-State: AJIora9NuUb925jTUWrOifc6QudiC3zZnQGJHv4AkeOoLNre3hpuGVCE XmsDl4rPJfWCp6RxDSW/ceBcvCvplsvF X-Google-Smtp-Source: AGRyM1vam0eY4kxLgjE9vgO4zYasfCIOb1P3WCqhqqO69ysLbXyvcyI6DvJ1MpV7tsaczHqiAb7fCisFyF4V X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a05:6a00:2809:b0:51b:f239:d24d with SMTP id bl9-20020a056a00280900b0051bf239d24dmr898928pfb.73.1655155536556; Mon, 13 Jun 2022 14:25:36 -0700 (PDT) Date: Mon, 13 Jun 2022 21:25:19 +0000 In-Reply-To: <20220613212523.3436117-1-bgardon@google.com> Message-Id: <20220613212523.3436117-7-bgardon@google.com> Mime-Version: 1.0 References: <20220613212523.3436117-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH v9 06/10] 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 | 229 ++++++++++++++++++ .../kvm/x86_64/nx_huge_pages_test.sh | 40 +++ 6 files changed, 337 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 dd5c88c11059..1f2e81c0f36a 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 b52c130f7b2f..fc2299f31a85 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -70,6 +70,10 @@ LIBKVM_s390x +=3D lib/s390x/ucall.c LIBKVM_riscv +=3D lib/riscv/processor.c LIBKVM_riscv +=3D 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 @@ -134,6 +138,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 @@ -173,7 +180,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 @@ -220,6 +229,7 @@ $(LIBKVM_S_OBJ): $(OUTPUT)/%.o: %.S =20 x :=3D $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS)))) $(TEST_GEN_PROGS): $(LIBKVM_OBJS) +$(TEST_GEN_PROGS_EXTENDED): $(LIBKVM_OBJS) =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 aa7f8b681944..81ab7adfbef5 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -340,6 +340,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; +} + void vm_create_irqchip(struct kvm_vm *vm); =20 void vm_set_user_memory_region(struct kvm_vm *vm, uint32_t slot, uint32_t = flags, diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 5b8249a0e1de..0d97142a590e 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1925,3 +1925,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..5fa61d225787 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c @@ -0,0 +1,229 @@ +// 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_vcpu *vcpu; + 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(1); + vcpu =3D vm_vcpu_add(vm, 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(vcpu); + 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(vcpu); + 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(vcpu); + 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(vcpu); + check_2m_page_count(vm, 1); + check_split_count(vm, 2); + + /* Reading from the first huge page again should have no effect. */ + vcpu_run(vcpu); + 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(vcpu); + 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.476.g0c4daa206d-goog From nobody Mon Apr 27 11:29:26 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 AEEF8C433EF for ; Mon, 13 Jun 2022 21:30:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352343AbiFMVay (ORCPT ); Mon, 13 Jun 2022 17:30:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58482 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353168AbiFMV3W (ORCPT ); Mon, 13 Jun 2022 17:29:22 -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 1F111DB9 for ; Mon, 13 Jun 2022 14:25:39 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-30c99cb3d4dso8960147b3.6 for ; Mon, 13 Jun 2022 14:25:39 -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=VkR00FIY91tjDpMUCEsQU2PfErV2sywfNrBtcS7WMdA=; b=UEPb/R59lq8V0rQq30AmkNgtayiFpIGEWCSalN9r1ucDzSJGzRnBAV01JGW8njwhqC lWQO5gk9PF8tD8n20nTTH3SLPkjg/m+VbFCZWv6BgtKjkZJ7B9EXdjAbyfgF3EaD/wU4 IryCXnecgXVcCT49ytAduSe478drjCJTURMN8X7SgkMQYfWm53xldKgzGVG+OtGCya+g mRjWssFxkU7v9KRaL5jNgNwNm1cSf4wyOBeXVU8CBVWcWmWvdAeTs1LkqiWrsoyiLZdE aSXEP7njhdjc5obmr6XMESfssR40v+dbNPmwEQy0HuxewMWAiEvKtc/kEJbFV/eShkGN 9JyA== 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=VkR00FIY91tjDpMUCEsQU2PfErV2sywfNrBtcS7WMdA=; b=APmn6qhwdI301fGC51QyeoonqKAyxsI3aGks6djtFK5+YzKf4sQaLRuro2nohY359Z 9l63wWZOThuIpQ75i7yPlrDPliJhrzzPYVR15ZJJ1vW9LUGSGLU86zt4K5Utjsf4xjC4 7yVCPuMGrn8MT0i622SSh3ROeEgtZ4cBrC7Df4mg99FIJM2X+jt/Kaq2Gn3WlC518rrs 9rT9ycZuYD1/MWfpoQc2XAop8oIecLxjk2RkvqwTlINXxNTGb3iFvAMXLcauotlYvGTg XX8+2kM1mJFO1WUPRzb+n2kqYyq4wo19cWR07EYcBtAkT93+BE8YDG5QD25RLwvVcmcf EuSg== X-Gm-Message-State: AJIora/J2VfoLPHG0FctVVgRj9TY+K87450EDn6E3reNjG5amk5b2Zw+ YHzcm8nuRsG96OEu7UWtR7I2ALfc6K9G X-Google-Smtp-Source: AGRyM1sceaZ0bDImwee/oOoIdhrOh/Mf9Twz8hbEsZTH2MRSIYefJttI+4NGXFaKqrCk/yQgMsZj6WphjB0J X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a25:d4c9:0:b0:65c:a345:64a1 with SMTP id m192-20020a25d4c9000000b0065ca34564a1mr1627968ybf.535.1655155538306; Mon, 13 Jun 2022 14:25:38 -0700 (PDT) Date: Mon, 13 Jun 2022 21:25:20 +0000 In-Reply-To: <20220613212523.3436117-1-bgardon@google.com> Message-Id: <20220613212523.3436117-8-bgardon@google.com> Mime-Version: 1.0 References: <20220613212523.3436117-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH v9 07/10] 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 2318a99139fa..d6639653a113 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4398,10 +4398,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.476.g0c4daa206d-goog From nobody Mon Apr 27 11:29:26 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 A62D2C43334 for ; Mon, 13 Jun 2022 21:30:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352159AbiFMVaM (ORCPT ); Mon, 13 Jun 2022 17:30:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60456 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353173AbiFMV3X (ORCPT ); Mon, 13 Jun 2022 17:29: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 4F070E70 for ; Mon, 13 Jun 2022 14:25:40 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id z186-20020a6233c3000000b00510a6bc2864so2832782pfz.10 for ; Mon, 13 Jun 2022 14:25:40 -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=U87ZD4vxw8iq8ifrEN0gIUIBbkESGREXZK75qYLTKJQ=; b=d8YgD1f/y6Inx1ooa8+q+yL+n3zm1UN3pT1uKV5FhJiETDgkDx2xG7DEnoeojSG9MS +GhfTG9blw72GiAPbRHloyIra7mcSVFiDCCm9DyByKQmzMOBgjClpcTRSiehSbdjVYx2 teBCv9QS9rFYQViefK2Qt7ti5plxUHp+QlsybhIli8VAsh6Kr1zLZ8PgVs7oTOqNAS8n xb5Z8KAh3UZx7MbPgmH4FdLgJBDc4k117bLD6sRe2J0nvBWUMVnBg+VlbiIuRrFvYeWQ VAIctw1puJI/8LY70l3Za1PhxHZkeYrJlFKJUb4Q5qWpp9o2Ga7rHoFG4nonomnWPbjE ZRWw== 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=U87ZD4vxw8iq8ifrEN0gIUIBbkESGREXZK75qYLTKJQ=; b=tCw9nW09G/fu1Zt8HGeLAhM/xNSwgywEGue1uL55R2TI1ozFvQsEAX9RPXd0FXCSTV Lhjfn1H/ttd0Hi6yoMVlprPaxVldj4UFP7CpIcQ1rYoBpIYB1+O2qISj4vHW2vxkB1c9 ckPw+cCWrgDNSMnYujwbKjgGZbFbUpQ1KULGDRqnN015l5IlWl0XTgcKW1CHnbzk2Egv Xyo4Tdbuld5zC+nOm7g0Bh2jEQsKtpmkpXOK0mn1knfXK9YlU5hKpZT5jkOSXsFnZFoy cfYAG2QyvWbsB3qktuzkfYtDgwlncqCFEsfoHGB2EjRr7sL9dug6yMPwyHtTJOU81j/J vp+w== X-Gm-Message-State: AOAM5325kQYkDDldqigpHvfTw8Lar/6CgxGwDT+FPTP9cqGFA5+g/gEF iRvPMgShK9PYLE2xE3bCTJA4C0g9EKSQ X-Google-Smtp-Source: AGRyM1v8bIo9qjOSxESmw2hrxA5pyAmXh6PCA6Cm/CZ+kqXW+VLX48DyxZ4DGeA+pSgox2ODmXt1SswOreEM X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:a05:6a00:338e:b0:51b:c452:4210 with SMTP id cm14-20020a056a00338e00b0051bc4524210mr902094pfb.69.1655155539805; Mon, 13 Jun 2022 14:25:39 -0700 (PDT) Date: Mon, 13 Jun 2022 21:25:21 +0000 In-Reply-To: <20220613212523.3436117-1-bgardon@google.com> Message-Id: <20220613212523.3436117-9-bgardon@google.com> Mime-Version: 1.0 References: <20220613212523.3436117-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH v9 08/10] 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 | 16 ++++++++++++++++ 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, 60 insertions(+), 8 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 84c486ce6279..7f777aa488e3 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -8193,6 +8193,22 @@ PV guests. The `KVM_PV_DUMP` command is available fo= r the dump related UV data. Also the vcpu ioctl `KVM_S390_PV_CPU_COMMAND` is available and supports the `KVM_PV_DUMP_CPU` subcommand. =20 +8.38 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. =20 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 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 7e98b2876380..de278f904740 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1337,6 +1337,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 7b9265d67131..96692758e104 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 d6639653a113..0a0752587acb 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4302,6 +4302,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: @@ -6162,6 +6163,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 7569b4ec199c..a36e78710382 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1166,6 +1166,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_S390_PROTECTED_DUMP 217 #define KVM_CAP_X86_TRIPLE_FAULT_EVENT 218 #define KVM_CAP_X86_NOTIFY_VMEXIT 219 +#define KVM_CAP_VM_DISABLE_NX_HUGE_PAGES 220 =20 #ifdef KVM_CAP_IRQ_ROUTING =20 --=20 2.36.1.476.g0c4daa206d-goog From nobody Mon Apr 27 11:29:26 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 55BC2C43334 for ; Mon, 13 Jun 2022 21:31:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236312AbiFMVbB (ORCPT ); Mon, 13 Jun 2022 17:31:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60452 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353189AbiFMV3Z (ORCPT ); Mon, 13 Jun 2022 17:29:25 -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 B6202C62 for ; Mon, 13 Jun 2022 14:25:41 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id s10-20020a170902a50a00b00162359521c9so3634058plq.23 for ; Mon, 13 Jun 2022 14:25:41 -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=ff4fVSapUxUvxB9n2Zl0T+CskRaCkgl+6PL+fmMltA8=; b=ViU1g4IXRwdIhNofi8BH7fqSlsEv32y03c03Y02Vk+QIDq1vArSJfsn201yYUkUbKU W3wDGy7regdl6SSjmTlUtL/0MFrnZ2IRaUNkIhYCgtkhWjpK8MrVkbXRM4Eb8MDkWugK 0lI0IiD+26eyChVxDUVkVRAkcq2Vl4RoWM2d3NAH12Ghc5c6J2AmU1t2rl0vEEMQ5AZe 6zdP/Q8wKiY4QjpSFP+4ff37r2dHTqSe/FrRLG7AWzOfhzcMX+pTN749wHNbdLSveyk6 My1v8Hy/fMfpucWLbFm1eX5AVIOvif7SuHa5wVg0G1IWQDTWfruof1pjyqRjVfu3Ni+7 rQ8A== 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=ff4fVSapUxUvxB9n2Zl0T+CskRaCkgl+6PL+fmMltA8=; b=I3u+kq47fwIGzHL/VB0UK0u9altplnA2cSw80QFFBaw6cR0TPuex1PJV/wGakiOuPe nFo3TYHLki/9hivPwR1t5xPiAT2ILGzY3qoKqUJpbn2CJv1LLVeCGCFeclQRz9tBJDp7 VPPjbNgeEareSsdwE2RbNzSbbeZLp/2y41zm1d9c5N1jEroA5niHBDtxq3KDNMlDGLeJ mD8Lj22xy6N40vseJNpDd80hz29qIwSmDcKfkc/Ut55wFb6lQhso09Oj3o8NVeWV/kjw eWP3ipMSUvKR9Zm25aAPTnMDNgSvLH2E5Aw+jBPTDhT3/xVuJnpGa6d1guUwHPkH28wE 97/g== X-Gm-Message-State: AOAM533tbj0clHfuE/PQpv+UDwsukwv7BCgzQj+eebQMj74xfdl9NnDm 1xMRhNEM8AezprEZbsfiVUL3rKwwhItP X-Google-Smtp-Source: AGRyM1ujH/8wJgnWLOU39KDbFOQcd+ADIaJJ+FNow/hKmegWIyz+ttFnHcvrApS9oLsLGz/ShD1JOxE+KHhq X-Received: from sweer.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:e45]) (user=bgardon job=sendgmr) by 2002:aa7:92d2:0:b0:51b:4d60:6475 with SMTP id k18-20020aa792d2000000b0051b4d606475mr1251862pfa.73.1655155541209; Mon, 13 Jun 2022 14:25:41 -0700 (PDT) Date: Mon, 13 Jun 2022 21:25:22 +0000 In-Reply-To: <20220613212523.3436117-1-bgardon@google.com> Message-Id: <20220613212523.3436117-10-bgardon@google.com> Mime-Version: 1.0 References: <20220613212523.3436117-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH v9 09/10] 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 | 6 + .../selftests/kvm/x86_64/nx_huge_pages_test.c | 134 ++++++++++++------ .../kvm/x86_64/nx_huge_pages_test.sh | 14 +- 3 files changed, 106 insertions(+), 48 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 81ab7adfbef5..537b8a047d6e 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -804,4 +804,10 @@ static inline void virt_dump(FILE *stream, struct kvm_= vm *vm, uint8_t indent) virt_arch_dump(stream, vm, indent); } =20 + +static inline int __vm_disable_nx_huge_pages(struct kvm_vm *vm) +{ + return __vm_enable_cap(vm, KVM_CAP_VM_DISABLE_NX_HUGE_PAGES, 0); +} + #endif /* SELFTEST_KVM_UTIL_BASE_H */ 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 5fa61d225787..cc6421716400 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,53 +107,34 @@ 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_vcpu *vcpu; struct kvm_vm *vm; void *hva; + int r; =20 - 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); - } + vm =3D vm_create(1); =20 - if (!reclaim_period_ms) { - print_skip("The NX reclaim period must be specified and non-zero"); - exit(KSFT_SKIP); + 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 - vm =3D vm_create(1); vcpu =3D vm_vcpu_add(vm, 0, guest_code); =20 vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS_HUGETLB, @@ -187,31 +168,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(vcpu); - 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(vcpu); - 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(vcpu); - 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 /* @@ -219,10 +207,62 @@ int main(int argc, char **argv) * reading from it causes a huge page mapping to be installed. */ vcpu_run(vcpu); - 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.476.g0c4daa206d-goog From nobody Mon Apr 27 11:29:26 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 DDC5BCCA47C for ; Mon, 13 Jun 2022 21:30:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352095AbiFMVaJ (ORCPT ); Mon, 13 Jun 2022 17:30:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60460 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353195AbiFMV3Z (ORCPT ); Mon, 13 Jun 2022 17:29:25 -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 5AAB1BFC for ; Mon, 13 Jun 2022 14:25:43 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id t24-20020a170902b21800b00168e27c3c2aso1670723plr.18 for ; Mon, 13 Jun 2022 14:25:43 -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=2HZEMfRIxWFvhgNolJdHE+4fmvokBk1d/agQn4Bf6T4=; b=RdGzy/6cYG/hqt377t5RGc5j2qzeneOwISpagbEXNwhnJRGvEuJRIOJNxRgc1uaD9J z1XHzQ3qx6rtvshQtkND+/6k5zcdfEmAGAQe4MBNv37e95zUI5qlEr+ukkA7NSdUsA1z SRcW9mBtWtFzBGnm/P9jSA8P/+/B31FIzTXSkjfDUHBHwnMuu6nFLEgVutqEPjNF2Njr I6aapXMjXkcuw4mTcC+r8vW3kDTpnhz1sSNktr6TUaIlqZg7AJ94G0IPUs8ZUmEDzxES JsjLZl1f2MpBzRN6+L3kZ6u7UkB6aktI6zG3HWkWXJN/vQ/rnFhG9lnuDv6PFe1YDY69 nI0Q== 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=2HZEMfRIxWFvhgNolJdHE+4fmvokBk1d/agQn4Bf6T4=; b=e25NBaTEcm/0/OoxAskAY4ZmVRmwZ2c6DhpRvrR1JDdnBoA04DAooF5YQIdC4r3BGY eiOGVB0ZhzwkIx+Y5+QUc683lkPJhMRGhGqu0puhgp+ynqT29N61W3IQ3VefXMsYggPU EeJvb+PQXPu4pdv6OmB30I6xsYvDWMNj+ggbonF2BpndIIWsf6/IFjm7iEasc5tiKu2D wDr/6UTE8hexNBI7VfCAsW8HtrZFJgFlIllyAErODZ8dI0PN/YyGNdSJvx6hj8ylOR6Q GZtwrxa8sISU8cFemYu8gUj4nWaMWHcddVhu9mdWe/szcP/kLhCxeHxYoPzOjEwJo8M5 lAkw== X-Gm-Message-State: AJIora9Hx8tqWKShpB5/Mo7DUvkhqwy+Zjk5sxt0WB/FcdqvVek18iDM FIeZiFK82cmWEF+0NM4OC15RYIjbLOAt X-Google-Smtp-Source: AGRyM1vSLQ762BI4fr+CHdSH7bPhrBuiIxkFdEVnBv9ahJasB6kow7g6SLnoXz4WYJnTfC/qn+sEUP/QTeGX 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:1e2:da25:4095 with SMTP id gk18-20020a17090b119200b001e2da254095mr737030pjb.240.1655155542892; Mon, 13 Jun 2022 14:25:42 -0700 (PDT) Date: Mon, 13 Jun 2022 21:25:23 +0000 In-Reply-To: <20220613212523.3436117-1-bgardon@google.com> Message-Id: <20220613212523.3436117-11-bgardon@google.com> Mime-Version: 1.0 References: <20220613212523.3436117-1-bgardon@google.com> X-Mailer: git-send-email 2.36.1.476.g0c4daa206d-goog Subject: [PATCH v9 10/10] 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 --- .../selftests/kvm/include/kvm_util_base.h | 5 +++ tools/testing/selftests/kvm/lib/kvm_util.c | 32 ++++++++++--------- 2 files changed, 22 insertions(+), 15 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 537b8a047d6e..daf201174d2a 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -84,6 +84,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 =20 diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 0d97142a590e..787aeb0c61f3 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -551,6 +551,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); @@ -1942,32 +1948,28 @@ 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 2.36.1.476.g0c4daa206d-goog