From patchwork Mon Jun 13 21:25:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12880232 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 9DE49CCA47B for ; Mon, 13 Jun 2022 21:31:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352422AbiFMVba (ORCPT ); Mon, 13 Jun 2022 17:31:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60470 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353116AbiFMV3S (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 91B3520E for ; Mon, 13 Jun 2022 14:25:28 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id c10-20020a170903234a00b00168b5f7661bso3649387plh.6 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=iaHlMZjuu/2f7QmYfmUeEpFBLi0vJ/HCCYgs7iP9LCBpy3BG24X0Sq/wVTZ8vn5Id6 HSYhPhD+cmznrnnBepGwxCSgNUSE9tedRb6gsGe/ScSXd6Q21D59ZDMrp8tb3WXFXnca kfYMZSyuU0Vq7CoOIMIN3UbmvvkWQySP3tHJRG0ktewFBsXZym8XW3V8qPg1JcvUCh73 +7u3XsWuvRQEhXPgYITjONVHJbKMwYcloTeqILRMiZaX0xBBBQTTDPdO+zhiczsccXHX LkhGV1pxuHw44orX1ta2aG9m0UGMJvfx19DbJboXFIeUROBI0avTvW+gIJv/Hv0yumkA wSsQ== X-Gm-Message-State: AOAM533x/FB+T8RRi+dGYLt12ZLyEe3Z+Sy7VDSWqs5aTnmim3BaXEGP OpTKYwicbl1FJe7lB7mRsOe/kfuA9J8TdCJ7icSfUL7BJ/yvMEzS/Egu+jXNl/ANRNjropSy74I JW4KVroPmP9ySxyoqLywlCnqRyF1IuwQo7j8AjoiC8K4dYhQgUKv8uW5op+Jb 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: kvm@vger.kernel.org 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/testing/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 = 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; /* Read kvm stats header */ - header = malloc(sizeof(*header)); - TEST_ASSERT(header, "Allocate memory for stats header"); - - ret = read(stats_fd, header, sizeof(*header)); - TEST_ASSERT(ret == sizeof(*header), "Read stats header"); - size_desc = sizeof(*stats_desc) + header->name_size; + ret = read(stats_fd, &header, sizeof(header)); + TEST_ASSERT(ret == sizeof(header), "Read stats header"); + size_desc = sizeof(*stats_desc) + header.name_size; /* Read kvm stats id string */ - id = malloc(header->name_size); + id = malloc(header.name_size); TEST_ASSERT(id, "Allocate memory for id string"); - ret = read(stats_fd, id, header->name_size); - TEST_ASSERT(ret == header->name_size, "Read id string"); + ret = read(stats_fd, id, header.name_size); + TEST_ASSERT(ret == header.name_size, "Read id string"); /* 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); /* Sanity check for other fields in header */ - if (header->num_desc == 0) { + if (header.num_desc == 0) { printf("No KVM stats defined!"); return; } /* Check overlap */ - TEST_ASSERT(header->desc_offset > 0 && header->data_offset > 0 - && header->desc_offset >= sizeof(*header) - && header->data_offset >= sizeof(*header), + TEST_ASSERT(header.desc_offset > 0 && header.data_offset > 0 + && header.desc_offset >= sizeof(header) + && header.data_offset >= sizeof(header), "Invalid offset fields in header"); - TEST_ASSERT(header->desc_offset > header->data_offset || - (header->desc_offset + size_desc * header->num_desc <= - header->data_offset), + TEST_ASSERT(header.desc_offset > header.data_offset || + (header.desc_offset + size_desc * header.num_desc <= + header.data_offset), "Descriptor block is overlapped with data block"); /* Allocate memory for stats descriptors */ - stats_desc = calloc(header->num_desc, size_desc); + stats_desc = calloc(header.num_desc, size_desc); TEST_ASSERT(stats_desc, "Allocate memory for stats descriptors"); /* Read kvm stats descriptors */ ret = pread(stats_fd, stats_desc, - size_desc * header->num_desc, header->desc_offset); - TEST_ASSERT(ret == size_desc * header->num_desc, + size_desc * header.num_desc, header.desc_offset); + TEST_ASSERT(ret == size_desc * header.num_desc, "Read KVM stats descriptors"); /* Sanity check for fields in descriptors */ - for (i = 0; i < header->num_desc; ++i) { + for (i = 0; i < header.num_desc; ++i) { pdesc = (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 += pdesc->size * sizeof(*stats_data); } /* Check overlap */ - TEST_ASSERT(header->data_offset >= header->desc_offset - || header->data_offset + size_data <= header->desc_offset, + TEST_ASSERT(header.data_offset >= header.desc_offset + || header.data_offset + size_data <= header.desc_offset, "Data block is overlapped with Descriptor block"); /* Check validity of all stats data size */ - TEST_ASSERT(size_data >= header->num_desc * sizeof(*stats_data), + TEST_ASSERT(size_data >= header.num_desc * sizeof(*stats_data), "Data size is not correct"); /* Check stats offset */ - for (i = 0; i < header->num_desc; ++i) { + for (i = 0; i < header.num_desc; ++i) { pdesc = (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 = malloc(size_data); TEST_ASSERT(stats_data, "Allocate memory for stats data"); /* Read kvm stats data as a bulk */ - ret = pread(stats_fd, stats_data, size_data, header->data_offset); + ret = pread(stats_fd, stats_data, size_data, header.data_offset); TEST_ASSERT(ret == size_data, "Read KVM stats data"); /* Read kvm stats data one by one */ size_data = 0; - for (i = 0; i < header->num_desc; ++i) { + for (i = 0; i < header.num_desc; ++i) { pdesc = (void *)stats_desc + i * size_desc; ret = pread(stats_fd, stats_data, pdesc->size * sizeof(*stats_data), - header->data_offset + size_data); + header.data_offset + size_data); TEST_ASSERT(ret == pdesc->size * sizeof(*stats_data), "Read data of KVM stats: %s", pdesc->name); size_data += 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); } From patchwork Mon Jun 13 21:25:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12880226 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 A8F4BC43334 for ; Mon, 13 Jun 2022 21:30:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245193AbiFMVaK (ORCPT ); Mon, 13 Jun 2022 17:30:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60474 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353141AbiFMV3T (ORCPT ); Mon, 13 Jun 2022 17:29:19 -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 3264E321 for ; Mon, 13 Jun 2022 14:25:30 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id w12-20020a170902e88c00b00168e42facf2so1503833plg.4 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=Y3WbB5U3ZLmlmrpqEbcdLzv98M+Yj7EFavoyBfZz+RRHewH7MSBWdEVlDWd5U5dm1S HPlVHOdAEMJe5uZGleEofzCJLrW9nuaJqIyL/oEly8//ezFMiX+iI5rhQO9xyuyEGmRz oaWdoBiYU32SifJfLm9SEJZN3hJjOarH1LhdSdY/9HtnCO8bdjJvkIai9uRjnxenrM58 TTfgULrydADe2RwUsu3NK0iY7CrOPIOM3FWb64buK+ZYkxnAwSDx0T29Lc6vl7eAIQ5+ U5YssR++Bn2TUNT6i20x6OsafumtZD4UMtUWMTlbVJVNqUnuuKWTF3XuGW3IRYcQ5SLx rUuA== X-Gm-Message-State: AJIora+RHq3Oj1o/X6wMnbOqHUqZ9Hicb0QgsNRm1ezGDMOJSTFLC1dC P6gniliwAQzRf6Yzg+euLRXzFnG0BSqzjUXqjuJ0MLgQ/fjdAKNiOTeNjBGPtiP/fCsVAM65s69 y3wHu0pjgW/nf7XO/4MqA3hvLNDPj5yrEts5eWmMZ41E74PjDWpAwehqoswyP 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: kvm@vger.kernel.org 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/testing/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; } +static inline void read_stats_header(int stats_fd, struct kvm_stats_header *header) +{ + ssize_t ret; + + ret = read(stats_fd, header, sizeof(*header)); + TEST_ASSERT(ret == sizeof(*header), "Read stats header"); +} + void vm_create_irqchip(struct kvm_vm *vm); 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/testing/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; /* Read kvm stats header */ - ret = read(stats_fd, &header, sizeof(header)); - TEST_ASSERT(ret == sizeof(header), "Read stats header"); + read_stats_header(stats_fd, &header); + size_desc = sizeof(*stats_desc) + header.name_size; /* Read kvm stats id string */ From patchwork Mon Jun 13 21:25:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12880229 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 3BDFACCA47B for ; Mon, 13 Jun 2022 21:31:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350901AbiFMVbT (ORCPT ); Mon, 13 Jun 2022 17:31:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60370 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353139AbiFMV3T (ORCPT ); Mon, 13 Jun 2022 17:29:19 -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 F2B9733F for ; Mon, 13 Jun 2022 14:25:31 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id p2-20020a170902e74200b00164081f682cso3635236plf.16 for ; Mon, 13 Jun 2022 14:25:31 -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=69ZbSrTlEuYlqk17SuVHZxYA/K+K8SSmGIe1dKip98+dS1QibGGf10n6cPv9q3P87V Hv3SmsUSGcB7skz5L/jh6YjxrhOKcwAmqSKYNAqXrVkmywGjPympQaf0Tn8F2ULF1E00 N9KpYDtmhMADOR7SrDJKgOEBdzlJFKUDSYe0Sgj8W5u4xLq5ZNMlio+LaaV/ne5fx7RS seP5hXpTNZFcJ5sUCEUHHZy7fJyMZFHU4Ju35haZFCRYEZvNFUcd0Rr2BN6ZU0rNFQCf qpUTN17c5L73iYLkdmKn2wALHwJFXfDjEPiWLFmwoxRmxV6VZ+PPcwc8qGZodzTApM9a X1Iw== X-Gm-Message-State: AJIora94v9HIzg6DUcFXq49ICdGri34hMxfTMgaebxWjpY+/l0qKgotk hSlD5jM4wrs22wsjSNpqkcSwkL1FlzY8C7jF3Q90whY+DLDHJjxYNnJw3v7ZzXJoVRXJnA0+HRV K6D3z0xaixgJ5NLG3v7i/nNDOvaZkl8DxSnSBg09JiU7w78LgxS+RqaUuBLqE 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: kvm@vger.kernel.org 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/testing/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, struct kvm_stats_header *head TEST_ASSERT(ret == sizeof(*header), "Read stats 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 *header) +{ + /* + * 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); 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/testing/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); - size_desc = sizeof(*stats_desc) + header.name_size; + size_desc = get_stats_descriptor_size(&header); /* Read kvm stats id string */ id = 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"); - /* Allocate memory for stats descriptors */ - stats_desc = calloc(header.num_desc, size_desc); - TEST_ASSERT(stats_desc, "Allocate memory for stats descriptors"); /* Read kvm stats descriptors */ - ret = pread(stats_fd, stats_desc, - size_desc * header.num_desc, header.desc_offset); - TEST_ASSERT(ret == size_desc * header.num_desc, - "Read KVM stats descriptors"); + stats_desc = read_stats_descriptors(stats_fd, &header); /* Sanity check for fields in descriptors */ for (i = 0; i < header.num_desc; ++i) { - pdesc = (void *)stats_desc + i * size_desc; + pdesc = get_stats_descriptor(stats_desc, i, &header); /* Check type,unit,base boundaries */ TEST_ASSERT((pdesc->flags & KVM_STATS_TYPE_MASK) <= 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 = 0; i < header.num_desc; ++i) { - pdesc = (void *)stats_desc + i * size_desc; + pdesc = 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 = 0; for (i = 0; i < header.num_desc; ++i) { - pdesc = (void *)stats_desc + i * size_desc; + pdesc = get_stats_descriptor(stats_desc, i, &header); ret = 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/selftests/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_mode mode, size_t size) n = 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 to 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 = get_stats_descriptor_size(header); + total_size = header->num_desc * desc_size; + + stats_desc = calloc(header->num_desc, desc_size); + TEST_ASSERT(stats_desc, "Allocate memory for stats descriptors"); + + ret = pread(stats_fd, stats_desc, total_size, header->desc_offset); + TEST_ASSERT(ret == total_size, "Read KVM stats descriptors"); + + return stats_desc; +} From patchwork Mon Jun 13 21:25:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12880227 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 2CEA5CCA47B for ; Mon, 13 Jun 2022 21:30:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352185AbiFMVaN (ORCPT ); Mon, 13 Jun 2022 17:30:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60462 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353159AbiFMV3W (ORCPT ); Mon, 13 Jun 2022 17:29:22 -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 E57C0394 for ; Mon, 13 Jun 2022 14:25:33 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id i19-20020aa79093000000b0050d44b83506so2828857pfa.22 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=0+D7RsSuho2Lc37bBJe43AsAPEHpg+Nf8DFvlMoMBwq5kdKujr+NnmPjUcyGqLd+yV UJaqeWsIDuNPMSMDA6JH0O6BjqP0DX6QLhjeEMmiPcpVTI1zxUEmW7SaLYitdN53XJ1X OBFmWQTg7sAc21vvh4/FhCsmsJQmbzX6QbDGQjByYA5NVMw5GXTSJOjidCip01UwAFIx 20YQ2vfSJuTudz9SWg5VXBeUCf5+eJOPcZA35CDc0k/5mlOpIR1rWijTwl+lqNt/LirW nZSXx5P8dtnae3sZun+8DmyysO5/u63idB8U3a73dcoEN5eXujWRcjAZfa9gJ3+wNZc0 25bg== X-Gm-Message-State: AJIora9TrYiWh3Nugox4bUhvDA+F5sSuEPd55vs8JPQdkDS5J+t/aze4 I5EiVuHUAw6GKbIxi1zNHlilGPoJqbQlR4d1kbb/314GTy985c5m09NbiwF8OMfOQbhbh4UxiFz vy3iQNDtDyNSTw8FETbi2wU91ZNAFJhxCZG5rjaKw79eiGF2qb1sDOwyGcxuW 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: kvm@vger.kernel.org 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/testing/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 = malloc(header.name_size); TEST_ASSERT(id, "Allocate memory for id string"); + ret = read(stats_fd, id, header.name_size); TEST_ASSERT(ret == header.name_size, "Read id string"); /* 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); /* Sanity check for other fields in header */ if (header.num_desc == 0) { printf("No KVM stats defined!"); return; } - /* Check overlap */ - TEST_ASSERT(header.desc_offset > 0 && header.data_offset > 0 - && header.desc_offset >= sizeof(header) - && header.data_offset >= 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 >= sizeof(header) && + header.data_offset && header.data_offset >= sizeof(header), + "Invalid offset fields in header"); + TEST_ASSERT(header.desc_offset > header.data_offset || - (header.desc_offset + size_desc * header.num_desc <= - header.data_offset), - "Descriptor block is overlapped with data block"); + (header.desc_offset + size_desc * header.num_desc <= header.data_offset), + "Descriptor block is overlapped with data block"); /* Read kvm stats descriptors */ stats_desc = 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 = 0; i < header.num_desc; ++i) { pdesc = get_stats_descriptor(stats_desc, i, &header); + /* Check type,unit,base boundaries */ - TEST_ASSERT((pdesc->flags & KVM_STATS_TYPE_MASK) - <= KVM_STATS_TYPE_MAX, "Unknown KVM stats type"); - TEST_ASSERT((pdesc->flags & KVM_STATS_UNIT_MASK) - <= KVM_STATS_UNIT_MAX, "Unknown KVM stats unit"); - TEST_ASSERT((pdesc->flags & KVM_STATS_BASE_MASK) - <= KVM_STATS_BASE_MAX, "Unknown KVM stats base"); - /* Check exponent for stats unit + TEST_ASSERT((pdesc->flags & KVM_STATS_TYPE_MASK) <= KVM_STATS_TYPE_MAX, + "Unknown KVM stats type"); + TEST_ASSERT((pdesc->flags & KVM_STATS_UNIT_MASK) <= KVM_STATS_UNIT_MAX, + "Unknown KVM stats unit"); + TEST_ASSERT((pdesc->flags & KVM_STATS_BASE_MASK) <= 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 >= 0, - "Unsupported KVM stats unit"); + TEST_ASSERT(pdesc->exponent >= 0, "Unsupported KVM stats unit"); break; case KVM_STATS_UNIT_SECONDS: - TEST_ASSERT(pdesc->exponent <= 0, - "Unsupported KVM stats unit"); + TEST_ASSERT(pdesc->exponent <= 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 += pdesc->size * sizeof(*stats_data); } - /* Check overlap */ - TEST_ASSERT(header.data_offset >= header.desc_offset - || header.data_offset + size_data <= 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 >= header.desc_offset || + header.data_offset + size_data <= header.desc_offset, + "Data block is overlapped with Descriptor block"); + /* Check validity of all stats data size */ TEST_ASSERT(size_data >= header.num_desc * sizeof(*stats_data), - "Data size is not correct"); + "Data size is not correct"); + /* Check stats offset */ for (i = 0; i < header.num_desc; ++i) { pdesc = 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); } /* Allocate memory for stats data */ From patchwork Mon Jun 13 21:25:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12880224 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 B8CD1C43334 for ; Mon, 13 Jun 2022 21:30:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233133AbiFMVaG (ORCPT ); Mon, 13 Jun 2022 17:30:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58868 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353156AbiFMV3W (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 C557B399 for ; Mon, 13 Jun 2022 14:25:35 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id a68-20020a25ca47000000b006605f788ff1so5946829ybg.16 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=jDf8GaQPXkh1DgOF7PpGggBfiEgSGPK9IFnJfJPgfvrMgycrTLEEjGoZuHV2An4k8K EsEiY6uavSil8LJoh338IVVmHmMNRYNdPvEYdCqBcAnh45bePlhag8zo4EijM+lpV9tX OyaLFrXdC/o4yrflu6R9m6KFyuWUL3fcDEria8QXIfFim1PmM+JlUky0D/rqnM6b1Wv0 jng7TUU964zjWjMaGijLRYlMl0GUKdL+9BnmazZA+pTPptbdYviQg0z1KnHLLvn/4J0Y k8+2+e1P2hPePpceSJIQnJfHt9086Nii4Of14ibT7NTO0N8L+hojyNXL9MlFeaz/bM/n oqaA== X-Gm-Message-State: AJIora9QazAM6aqeHpqxa0sHC9s7y5XP5QLvavDl4MmL9hJyxRPWh90u jKTjOdy+DaIFTOLlZrSgmVv7vr5abcmDrl84pVb4N20shE8IJw0G6kYtNBM+BlxLc5LRkLlY58B rLr+zhsJE//kJo5/Ghc5ck/pdRIyH15qu6P4s3VQl4L/DJKaRGPupPfVbCVeu 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: kvm@vger.kernel.org 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/testing/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_descriptor(struct kvm_stats_desc return (void *)stats + index * get_stats_descriptor_size(header); } +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); 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/testing/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 = pread(stats_fd, stats_data, size_data, header.data_offset); TEST_ASSERT(ret == size_data, "Read KVM stats data"); /* Read kvm stats data one by one */ - size_data = 0; for (i = 0; i < header.num_desc; ++i) { pdesc = get_stats_descriptor(stats_desc, i, &header); - ret = pread(stats_fd, stats_data, - pdesc->size * sizeof(*stats_data), - header.data_offset + size_data); - TEST_ASSERT(ret == pdesc->size * sizeof(*stats_data), - "Read data of KVM stats: %s", pdesc->name); - size_data += pdesc->size * sizeof(*stats_data); + read_stat_data(stats_fd, &header, pdesc, stats_data, + pdesc->size); } free(stats_data); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/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 stats_fd, return stats_desc; } + +/* + * Read stat data for a particular stat + * + * Input Args: + * stats_fd - the file descriptor for the binary stats file from which to 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 interface. + */ +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 = min_t(ssize_t, desc->size, max_elements); + size_t size = 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 = pread(stats_fd, data, size, + header->data_offset + desc->offset); + + TEST_ASSERT(ret >= 0, "pread() failed on stat '%s', errno: %i (%s)", + desc->name, errno, strerror(errno)); + TEST_ASSERT(ret == size, + "pread() on stat '%s' read %ld bytes, wanted %lu bytes", + desc->name, size, ret); +} From patchwork Mon Jun 13 21:25:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12880222 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 3507CCCA47D for ; Mon, 13 Jun 2022 21:30:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235607AbiFMVaC (ORCPT ); Mon, 13 Jun 2022 17:30:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32984 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353171AbiFMV3W (ORCPT ); Mon, 13 Jun 2022 17:29:22 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 28FD1C7D for ; Mon, 13 Jun 2022 14:25:37 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id h6-20020a17090a580600b001eab5988770so1507248pji.8 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=v9tSWO8o5nnR6TQ3BYcATcqOww1qTV8szbn8JrsehEACuUOzfy09+1dUS2FD0T6K9K TNz4NYTs2LSEeWPhEg+JZrO6Civqo+JpJJ0tzxHvhpg6xDiD69Nwy04VF0XsHKOks0fa XN9CznZGsqDaOV9Qld5YE+k/IfKPrA6y++gBoBIlPpzHGwr0LwnOXE5A99kd9B3qNdVD zLAyvU/ijtP5doRqUriJ22+C8Aij6AgaFAE6V0TUk+1hsS8emVlIcZ1Y9KbrOUtz4UPb r/imbDPxCIi9EwcrC/VhKieb6lGdxiT0JXSztRg9ZPXQ0RVsWirdTMe4qwOQMy6HO3DC Tcdw== X-Gm-Message-State: AJIora9WzQfCXLpdBzyYBL98FH+MlZ3toDZF+Kgyns1VDBicJeGWNui+ JQVq8G/6h/7uXHotxr4Jgs79VvHAXqDFM8ocGgvend8tu0xxoB58TGR0hEl7sA9PDorJKotNqH+ Y0BYa9vsG7+SuqFdPbc//7VSadlMV2enY4HStYtoKbD7rXeUJzuGyglOFxgpU 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: kvm@vger.kernel.org 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/selftests/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 += lib/s390x/ucall.c LIBKVM_riscv += lib/riscv/processor.c LIBKVM_riscv += lib/riscv/ucall.c +# Non-compiled test targets +TEST_PROGS_x86_64 += x86_64/nx_huge_pages_test.sh + +# Compiled test targets TEST_GEN_PROGS_x86_64 = x86_64/cpuid_test TEST_GEN_PROGS_x86_64 += x86_64/cr4_cpuid_sync_test TEST_GEN_PROGS_x86_64 += x86_64/get_msr_index_features @@ -134,6 +138,9 @@ TEST_GEN_PROGS_x86_64 += steal_time TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test TEST_GEN_PROGS_x86_64 += system_counter_offset_test +# Compiled outputs used by test targets +TEST_GEN_PROGS_EXTENDED_x86_64 += x86_64/nx_huge_pages_test + TEST_GEN_PROGS_aarch64 += aarch64/arch_timer TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list @@ -173,7 +180,9 @@ TEST_GEN_PROGS_riscv += kvm_page_table_test TEST_GEN_PROGS_riscv += set_memory_region_test TEST_GEN_PROGS_riscv += kvm_binary_stats_test +TEST_PROGS += $(TEST_PROGS_$(UNAME_M)) TEST_GEN_PROGS += $(TEST_GEN_PROGS_$(UNAME_M)) +TEST_GEN_PROGS_EXTENDED += $(TEST_GEN_PROGS_EXTENDED_$(UNAME_M)) LIBKVM += $(LIBKVM_$(UNAME_M)) INSTALL_HDR_PATH = $(top_srcdir)/usr @@ -220,6 +229,7 @@ $(LIBKVM_S_OBJ): $(OUTPUT)/%.o: %.S x := $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS)))) $(TEST_GEN_PROGS): $(LIBKVM_OBJS) +$(TEST_GEN_PROGS_EXTENDED): $(LIBKVM_OBJS) cscope: include_paths = $(LINUX_TOOL_INCLUDE) $(LINUX_HDR_PATH) include lib .. cscope: diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/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_header *header, struct kvm_stats_desc *desc, uint64_t *data, size_t max_elements); +void __vm_get_stat(struct kvm_vm *vm, const char *stat_name, uint64_t *data, + size_t max_elements); + +static inline uint64_t vm_get_stat(struct kvm_vm *vm, const char *stat_name) +{ + uint64_t data; + + __vm_get_stat(vm, stat_name, &data, 1); + return data; +} + void vm_create_irqchip(struct kvm_vm *vm); 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/selftests/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_header *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 interface. + */ +void __vm_get_stat(struct kvm_vm *vm, const char *stat_name, uint64_t *data, + 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 = vm_get_stats_fd(vm); + + read_stats_header(stats_fd, &header); + + stats_desc = read_stats_descriptors(stats_fd, &header); + + size_desc = get_stats_descriptor_size(&header); + + for (i = 0; i < header.num_desc; ++i) { + desc = (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/tools/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 = HPAGE_GVA; + uint64_t hpage_2 = hpage_1 + (PAGE_SIZE * 512); + uint64_t hpage_3 = 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 = vm_get_stat(vm, "pages_2m"); + + TEST_ASSERT(actual_pages_2m == 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 = vm_get_stat(vm, "nx_lpage_splits"); + + TEST_ASSERT(actual_splits == 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 = reclaim_period_ms * 5; + ts.tv_sec = reclaim_wait_ms / 1000; + ts.tv_nsec = (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 = 0, token = 0, opt; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + void *hva; + + while ((opt = getopt(argc, argv, "hp:t:")) != -1) { + switch (opt) { + case 'p': + reclaim_period_ms = atoi(optarg); + break; + case 't': + token = atoi(optarg); + break; + case 'h': + default: + help(argv[0]); + break; + } + } + + if (token != 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 = vm_create(1); + vcpu = 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 = 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/tools/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 parameters. +# +# tools/testing/selftests/kvm/nx_huge_page_test.sh +# Copyright (C) 2022, Google LLC. + +set -e + +NX_HUGE_PAGES=$(cat /sys/module/kvm/parameters/nx_huge_pages) +NX_HUGE_PAGES_RECOVERY_RATIO=$(cat /sys/module/kvm/parameters/nx_huge_pages_recovery_ratio) +NX_HUGE_PAGES_RECOVERY_PERIOD=$(cat /sys/module/kvm/parameters/nx_huge_pages_recovery_period_ms) +HUGE_PAGES=$(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-2048kB/nr_hugepages + + "$(dirname $0)"/nx_huge_pages_test -t 887563923 -p 100 +) +RET=$? + +sudo_echo "$NX_HUGE_PAGES" /sys/module/kvm/parameters/nx_huge_pages +sudo_echo "$NX_HUGE_PAGES_RECOVERY_RATIO" /sys/module/kvm/parameters/nx_huge_pages_recovery_ratio +sudo_echo "$NX_HUGE_PAGES_RECOVERY_PERIOD" /sys/module/kvm/parameters/nx_huge_pages_recovery_period_ms +sudo_echo "$HUGE_PAGES" /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages + +exit $RET From patchwork Mon Jun 13 21:25:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12880228 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 2FD7DC43334 for ; Mon, 13 Jun 2022 21:30:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352247AbiFMVaR (ORCPT ); Mon, 13 Jun 2022 17:30:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60388 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353166AbiFMV3W (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 38293DD1 for ; Mon, 13 Jun 2022 14:25:39 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id v127-20020a256185000000b0065cbe0f6999so5958233ybb.22 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=TmZBXmearrvfZVcIXq7Ye9R55lVH/ZbvIcUf0VAGPYILHS83lF4ZVi9654cYJ6vcwu N9YDLdOO9IZrQJOgap6prkv3frdT7Qx/P/6/spV3lxTxFS5IphicXaDz4yFdX1Jxya7R KAS+XBZvPeiBM0xkroFC0ieLNPQLUW82qEtCMv3ezmK40eq7llTxLsv/TKFqHkLGHiiS Mi6ElibBpMlZPaVU03ckmENZj9kIwuc0pHQCa/T1UkwSYV78hw1bWS6dQcd8dDasmfEJ HxmUp0oAtGyIqxMQqzjYxd7PGAWk4vXNmV74p6G8AWEVYuPzpmQnYC/joBF1tNQI+kTX 5AWA== X-Gm-Message-State: AJIora80cjURPwRrYcVTcj9DDK8WGJ34mjlBfazIv5dCGnXKU8v4egdq YLNJffJTbTV80w0o9FTyJMuAgdt3FIyNo9mYBwuoEEBV4YEpM+pZVRBtaM5xOQRlZATVp1q6Kmh LjFDJHHuWZnu51UefsuWknm8DDTE+QQ6LFWIhjkbYqRuTnzMWtvaYEa7Fcra7 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: kvm@vger.kernel.org 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 PMU 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, long ext) if (r < sizeof(struct kvm_xsave)) r = sizeof(struct kvm_xsave); break; + } case KVM_CAP_PMU_CAPABILITY: r = enable_pmu ? KVM_CAP_PMU_VALID_MASK : 0; break; - } case KVM_CAP_DISABLE_QUIRKS2: r = KVM_X86_VALID_QUIRKS; break; From patchwork Mon Jun 13 21:25:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12880223 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 A20C2C433EF for ; Mon, 13 Jun 2022 21:30:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352060AbiFMVaE (ORCPT ); Mon, 13 Jun 2022 17:30:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353181AbiFMV3Y (ORCPT ); Mon, 13 Jun 2022 17:29:24 -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 713ACEB9 for ; Mon, 13 Jun 2022 14:25:40 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id il9-20020a17090b164900b001e31dd8be25so6952248pjb.3 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=NuJInSS4iPAdqoB3DNW/XMs0P8gxNFbttoC1NyczWXabFWOqQY90ompOXmiYcaiVH0 XPk6QOIajN7vdgFdVAONt5M9bwvTaeZ0HhjfpPDBLE9G7TsU2jQLn5CBNAZKrCIv89P5 ZOaftaenwwPrOOz7d4H9BgF4RRjib/K3HtfV71rj7B+9CPBfBzfPn8EBOBNabFBwrrW9 9t5w2lNk+KjilkGkhYwM2Gqq+f4Ntcu3a9fZ0cWszH3uQ3xgv2EboD/QLnKw5cmJsb2t pw9COw5s5nowVTEOobCohsWIfKPE4cvXpQRh6N3w38h8tp+kvzn8mBhsnMExIxo7PoC3 b6OA== X-Gm-Message-State: AOAM532UFrSeOBvKp8SyRhuiUyAw2HmTpglE6dSqEoalP+9HoTWRYl7D UfuLCbkBXtBK/gyxrm+rrukBl0HXNK6s91xOE+3trwAOfv7wKUO3NX8Q6DxJFQ2+7/hjMIIle9A DYqx1mm2bTfPPSd2XgEHSAakmcvyTWhmzkBcsDEafhdhGGoO0uKXHjR6337De 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: kvm@vger.kernel.org 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 for the dump related UV data. Also the vcpu ioctl `KVM_S390_PV_CPU_COMMAND` is available and supports the `KVM_PV_DUMP_CPU` subcommand. +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. 9. Known KVM API problems ========================= diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.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; }; struct kvm_vm_stat { diff --git a/arch/x86/kvm/mmu/mmu_internal.h b/arch/x86/kvm/mmu/mmu_internal.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); 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; } 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 = err & PFERR_USER_MASK, .prefetch = prefetch, .is_tdp = likely(vcpu->arch.mmu->page_fault == kvm_tdp_page_fault), - .nx_huge_page_workaround_enabled = is_nx_huge_page_enabled(), + .nx_huge_page_workaround_enabled = + is_nx_huge_page_enabled(vcpu->kvm), .max_level = KVM_MAX_HUGEPAGE_LEVEL, .req_level = 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_page *sp, spte |= spte_shadow_accessed_mask(spte); if (level > PG_LEVEL_4K && (pte_access & ACC_EXEC_MASK) && - is_nx_huge_page_enabled()) { + is_nx_huge_page_enabled(vcpu->kvm)) { pte_access &= ~ACC_EXEC_MASK; } @@ -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_level, + int index) { u64 child_spte; int child_level; @@ -274,7 +275,7 @@ u64 make_huge_page_split_spte(u64 huge_spte, int huge_level, 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 = make_spte_executable(child_spte); } 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_page *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_level, + 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, struct tdp_iter *iter, * not been linked in yet and thus is not reachable from any other CPU. */ for (i = 0; i < PT64_ENT_PER_PAGE; i++) - sp->spt[i] = make_huge_page_split_spte(huge_spte, level, i); + sp->spt[i] = make_huge_page_split_spte(kvm, huge_spte, level, i); /* * 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, long ext) case KVM_CAP_SYS_ATTRIBUTES: case KVM_CAP_VAPIC: case KVM_CAP_ENABLE_CAP: + case KVM_CAP_VM_DISABLE_NX_HUGE_PAGES: r = 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 = -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 = -EPERM; + break; + } + + if (cap->args[0]) + break; + + mutex_lock(&kvm->lock); + if (!kvm->created_vcpus) { + kvm->arch.disable_nx_huge_pages = true; + r = 0; + } + mutex_unlock(&kvm->lock); + break; default: r = -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 #ifdef KVM_CAP_IRQ_ROUTING From patchwork Mon Jun 13 21:25:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12880225 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 B4BFAC433EF for ; Mon, 13 Jun 2022 21:30:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352126AbiFMVaJ (ORCPT ); Mon, 13 Jun 2022 17:30:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33022 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353193AbiFMV3Z (ORCPT ); Mon, 13 Jun 2022 17:29:25 -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 D3366B8A for ; Mon, 13 Jun 2022 14:25:41 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id t1-20020a170902e84100b001689cab0be3so3656452plg.11 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=GtPmjxAm4kmmvB/yiEmCX15nB90Rq3f2DYSTWxSpjA8F/y2muPwTXyO+FS424Bu785 M9MvhCGqzUP7fedKtXiuLY32TBTnrwCUcPhR5WqHxjufWPEPsH97VV7HrAFgq2f7PLkb UDNY0lEQwmEUgXi5Zf5btDw3J6oHYpDC0auBurtcqprfv9cYRxQVjt8EYXRcdXAFZuT2 WUSBhXKwviLiumwjvpIcRnTiplgMy2drLzWxuCCRStHFekWvMDqemo1JdLytQ8QX2ogu 4nczzi5BOJ4hkUWD6RqKVPrr1vco/zZBHMRV5pVeiOaP7fkVzRiqjeWHW7u7P28Pm16Y f4Eg== X-Gm-Message-State: AOAM530o69BPQJgFVsct8jAK8WIjzNy19290bddEXuNsb0HkwcDfFPhQ 3SYJm8KiIAhsWIhPD+PVw+DXpuhxNvZqzmFmjDBBKrcF6VFmpF0Qh6ToE/xLx1Voss5LSHzzIUM 68YII9xo7URpYlk2OlygO3PAecmAs23TtEObHheApP0960NmpFUiMvQsG/+wD 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: kvm@vger.kernel.org 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/testing/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); } + +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/tools/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); } -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 = 0, token = 0, opt; struct kvm_vcpu *vcpu; struct kvm_vm *vm; void *hva; + int r; - while ((opt = getopt(argc, argv, "hp:t:")) != -1) { - switch (opt) { - case 'p': - reclaim_period_ms = atoi(optarg); - break; - case 't': - token = atoi(optarg); - break; - case 'h': - default: - help(argv[0]); - break; - } - } - - if (token != 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 = vm_create(1); - 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 = __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 == -1 && errno == EPERM, + "This process should not have permission to disable NX huge pages"); + return; + } } - vm = vm_create(1); vcpu = vm_vcpu_add(vm, 0, guest_code); 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); /* * 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); /* 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); /* 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. + * + * 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); /* @@ -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); 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 pages.\n"); + puts(""); + exit(0); +} + +int main(int argc, char **argv) +{ + int reclaim_period_ms = 0, token = 0, opt; + bool reboot_permissions = false; + + while ((opt = getopt(argc, argv, "hp:t:r")) != -1) { + switch (opt) { + case 'p': + reclaim_period_ms = atoi(optarg); + break; + case 't': + token = atoi(optarg); + break; + case 'r': + reboot_permissions = true; + break; + case 'h': + default: + help(argv[0]); + break; + } + } + + if (token != 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); return 0; } diff --git a/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh b/tools/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 } +NXECUTABLE="$(dirname $0)/nx_huge_pages_test" + ( set -e @@ -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-2048kB/nr_hugepages - "$(dirname $0)"/nx_huge_pages_test -t 887563923 -p 100 + # Test with reboot permissions + if [ $(whoami) != "root" ] ; then + sudo setcap cap_sys_boot+ep $NXECUTABLE + fi + $NXECUTABLE -t 887563923 -p 100 -r + + # Test without reboot permissions + if [ $(whoami) != "root" ] ; then + sudo setcap cap_sys_boot-ep $NXECUTABLE + $NXECUTABLE -t 887563923 -p 100 + fi ) RET=$? From patchwork Mon Jun 13 21:25:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12880230 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 61414CCA47C for ; Mon, 13 Jun 2022 21:31:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352400AbiFMVbZ (ORCPT ); Mon, 13 Jun 2022 17:31:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32894 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353199AbiFMV31 (ORCPT ); Mon, 13 Jun 2022 17:29:27 -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 78E1995 for ; Mon, 13 Jun 2022 14:25:43 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id c11-20020a17090a4d0b00b001e4e081d525so6938983pjg.7 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=q13/eXUgsLzD7+1MnvxN0pziwk3sqvbVDQRfArL/uHoMETkB1dMKBsgrVTOuwrxGCm FtbFW9SnwGYseR1lNQ3NFlfXP+AMnBg+q2lx7UXNpiY0h44BAYGpb4wOrrxRTHDP0QPL 0p4j7J+/e7Ldau5AwwWbbwxt1UCxMCK4I5xkWhYoNHOuQAXpJ/6rbNuViteQrTIctU72 fc4MM7onkmvygRTZ6evXOUgEMi6kxo05bxx2W6MX6LfGKNwTvVs6zlelSty+30WpK1XZ dY+7BmFiHAE/2zvbOGUVk6I4A/cy7hEbuVXPJaWnl7F7MB7+OSlhCM1DEV9UtbP6Kr4T 3qyQ== X-Gm-Message-State: AJIora97BwvHGak9x7prd9JhvD2EAWHdXdcU90FMKaCFYtLXsDZeZ60o ezUTeOoH2kV5+u2oQVlMnTQRz8H/+LH0NkQaQqg716H96j6CX0Mg+9eClw+1bJpMA/JhYdOcVFw EaYxpVBTAodgdg17hY8ouRyrzDaY/RGZdFDoIG+Mi9UlQgbzjKd0b91GLNx/V 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: kvm@vger.kernel.org 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/testing/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; }; diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/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 == NULL) return; + /* 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 *data, 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 = vm_get_stats_fd(vm); - - read_stats_header(stats_fd, &header); - - stats_desc = read_stats_descriptors(stats_fd, &header); + if (!vm->stats_fd) { + vm->stats_fd = vm_get_stats_fd(vm); + read_stats_header(vm->stats_fd, &vm->stats_header); + vm->stats_desc = read_stats_descriptors(vm->stats_fd, + &vm->stats_header); + } - size_desc = get_stats_descriptor_size(&header); + size_desc = get_stats_descriptor_size(&vm->stats_header); - for (i = 0; i < header.num_desc; ++i) { - desc = (void *)stats_desc + (i * size_desc); + for (i = 0; i < vm->stats_header.num_desc; ++i) { + desc = (void *)vm->stats_desc + (i * size_desc); if (strcmp(desc->name, stat_name)) continue; - read_stat_data(stats_fd, &header, desc, data, max_elements); + read_stat_data(vm->stats_fd, &vm->stats_header, desc, + data, max_elements); break; } - - free(stats_desc); - close(stats_fd); }