From patchwork Wed Apr 20 17:35:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12820607 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 250BFC433EF for ; Wed, 20 Apr 2022 17:35:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381140AbiDTRiI (ORCPT ); Wed, 20 Apr 2022 13:38:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53144 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381127AbiDTRiF (ORCPT ); Wed, 20 Apr 2022 13:38:05 -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 0925412AD3 for ; Wed, 20 Apr 2022 10:35:19 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id t3-20020a656083000000b0039cf337edd6so1361948pgu.18 for ; Wed, 20 Apr 2022 10:35:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=/lytJlVZ1asZQvqccJjy8nnnVMvt29QnZJwrlfaEIOo=; b=sEbAflrSLpDDn4tKeGnsCqqsull8tQvNHOdl/uizSD4lm6uwOJbZWDggSCIucVnffx 7dHs2gsgDIIPIoXXrcKEZuly6+3NJpHYh+invAOzr+A2Ac1T/zsbRI7GOiq8rwoPgpMh 8PU1GVTBmneZ70dAqO8M2k/qdOvZpRA1dD6MuECsXgABTwDLPjnGwNWmxB8NfARJT/2s 3tC9QbMg6o/4vUF6upko50KlqML1M1ujKfwCHKnGCdBjtFRijaI2AiaW8uRaHhEBKvJ0 a2SX9jeTZPdQKDaai8HtVCVlysI7givX29OhNyvL4oOK/39GLaf4OpW3evcNJkLDUvyv Dilw== 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=/lytJlVZ1asZQvqccJjy8nnnVMvt29QnZJwrlfaEIOo=; b=XoiaAfV/s4RX/rX0oD42deHQ3eody4dBRorr+oJc1EKZYp3BDwaRYdcBtLdoiLSr9m wqDmgmcL41AmW0fltWNAKf3y5Dl0r+pZyfxmV2YRPgfO2G7wqu91TLzqopEcHYTd5/0T AQjigpCu2qqzP7LPfJa0w18mXtGDyYQ5oB/s6qaOVMGtlHrIddkAYsL7W1Du3zHCvLfn AGgWgUdlOE8IisDOSwOoXrBBZgbdqhgKaJnV4CYogEGkgxLlxSHaOAvkxrXiTGTgUpmT 47yWEfowhg/SjDBZa8RVeU7rEVR50JZW4Ubb4C3sWK8t2sbTel4IYnvvnwx09qPSB/xu zO5w== X-Gm-Message-State: AOAM530aMdqWHzIEB4rh18cRqEh6YtDABslKQ+c1wqV2DhxydFDFUPoT Uk1xmr357lRRCtdxe9/qck3rIbDr3HxK X-Google-Smtp-Source: ABdhPJwgyW+5qidvzRQitkcVQZlSueRHFJvOqKMxORsvHXFeVoDvfkO+zQTaOHosoaW2iz0YNtokqHhN6r9z X-Received: from bgardon.sea.corp.google.com ([2620:15c:100:202:6ea6:489a:aad6:761c]) (user=bgardon job=sendgmr) by 2002:a65:6b8e:0:b0:39d:6761:300f with SMTP id d14-20020a656b8e000000b0039d6761300fmr20839090pgw.42.1650476118477; Wed, 20 Apr 2022 10:35:18 -0700 (PDT) Date: Wed, 20 Apr 2022 10:35:04 -0700 In-Reply-To: <20220420173513.1217360-1-bgardon@google.com> Message-Id: <20220420173513.1217360-2-bgardon@google.com> Mime-Version: 1.0 References: <20220420173513.1217360-1-bgardon@google.com> X-Mailer: git-send-email 2.36.0.rc0.470.gd361397f0d-goog Subject: [PATCH v6 01/10] KVM: selftests: Remove dynamic memory allocation for stats header From: Ben Gardon To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , 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 Signed-off-by: Ben Gardon Reviewed-by: Peter Xu --- .../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 17f65d514915..dad34d8a41fe 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -26,56 +26,53 @@ static void stats_test(int stats_fd) int i; size_t size_desc; size_t size_data = 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 Wed Apr 20 17:35:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12820608 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 23641C433EF for ; Wed, 20 Apr 2022 17:35:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381145AbiDTRiK (ORCPT ); Wed, 20 Apr 2022 13:38:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53244 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381135AbiDTRiH (ORCPT ); Wed, 20 Apr 2022 13:38:07 -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 EE0A113FB8 for ; Wed, 20 Apr 2022 10:35:20 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id m12-20020a170902d18c00b001589ea4e0d6so1203556plb.12 for ; Wed, 20 Apr 2022 10:35:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=3hrVtKxiHbpz+NEaukEgKfo35soXVBenGEmfstwEEVg=; b=c92/D0tTK6mgxclzC4mkN1Z+Dd4UUec5FITmwETokYfH34YQTRAExgqJy+oRv9Pb4b 8Ldc2CH8j9nSF0gp0ESyVcrLTmHaTW5PjLbVcz/oN7BPsys5tV812WIkE/UNWy1hPE7Y bsi/C7MuVkLPq36Qqrna2QjXXnw2Ry/n9IwElWKuH1NElZ8V/l/4shEQPx8KHe4TxVdK ACmcYmLYeulOT57i0J0MnYLGkb9MCL7JjziqLaroH00w4dud63DQ48ZIaksYK1dmFrD1 m4Pm3IOVa7QG3GBhXfgAhCLvUQMMACNLzeJjuHqu6H32A7dOZd2L8dXcaJBsxLw7W+jw h46g== 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=3hrVtKxiHbpz+NEaukEgKfo35soXVBenGEmfstwEEVg=; b=qTofSIpPnE7UzaOsWoHfs94qk7CeHHKQi/9TXAMJ3c2z8msNakGuzsGxPLCuLOh8s3 risv69WGOWOZrFDvlZpPNaxe6O84eUqYUe4ABLUDyL4xjTyQ9qEP74Ub5e1gQTad/+RG hajgaBM0huaronKXRjkfY8kHu9R2B3uaXRx1kvoZtIOIq0oK4tG2Om3t3cVnUTG2/rbO 97GOXgutvR1Su4CfpjN8IyrCpdJLmOdSVZTGxnOTQjiPA+CE2/zG2PnFSxsS4ECgsagp lEuNB/YT0zAfHMWFAehXSynIUrOA8Y4T13+RRuzby0VIaUjGELeqXZ2EewOE+9t8pGXo t+Gg== X-Gm-Message-State: AOAM533Zj173bUfmljxMjZTMOOSPGiOU6ZfEdqDn7BxCwciHNycscyM0 sYgQZdQKj8GL4pxjpkAG88Cnrr3W7JrY X-Google-Smtp-Source: ABdhPJw7eHr1qhn7c2BfQ+hyrDFgTWTh4w8N0NJRzArOEZocpnHXiaEqecWXU2fQT+mTQNFgzLoKZno2S7x4 X-Received: from bgardon.sea.corp.google.com ([2620:15c:100:202:6ea6:489a:aad6:761c]) (user=bgardon job=sendgmr) by 2002:a05:6a00:884:b0:4fe:134d:81cc with SMTP id q4-20020a056a00088400b004fe134d81ccmr24602772pfj.57.1650476120419; Wed, 20 Apr 2022 10:35:20 -0700 (PDT) Date: Wed, 20 Apr 2022 10:35:05 -0700 In-Reply-To: <20220420173513.1217360-1-bgardon@google.com> Message-Id: <20220420173513.1217360-3-bgardon@google.com> Mime-Version: 1.0 References: <20220420173513.1217360-1-bgardon@google.com> X-Mailer: git-send-email 2.36.0.rc0.470.gd361397f0d-goog Subject: [PATCH v6 02/10] KVM: selftests: Read binary stats header in lib From: Ben Gardon To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , 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 Signed-off-by: Ben Gardon Reviewed-by: Peter Xu --- .../selftests/kvm/include/kvm_util_base.h | 1 + .../selftests/kvm/kvm_binary_stats_test.c | 4 ++-- tools/testing/selftests/kvm/lib/kvm_util.c | 21 +++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 92cef0ffb19e..749cded9b157 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -400,6 +400,7 @@ void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid); int vm_get_stats_fd(struct kvm_vm *vm); int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vcpuid); +void read_stats_header(int stats_fd, struct kvm_stats_header *header); uint32_t guest_get_vcpuid(void); diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c index dad34d8a41fe..fb511b42a03e 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -33,8 +33,8 @@ static void stats_test(int stats_fd) struct kvm_stats_desc *pdesc; /* 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 */ diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 1665a220abcb..1d75d41f92dc 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -2556,3 +2556,24 @@ int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vcpuid) return ioctl(vcpu->fd, KVM_GET_STATS_FD, NULL); } + +/* + * Read binary stats header + * + * Input Args: + * stats_fd - the file descriptor for the binary stats file from which to read + * + * Output Args: + * header - a binary stats metadata header to be filled with data + * + * Return: void + * + * Read a header for the binary stats interface. + */ +void read_stats_header(int stats_fd, struct kvm_stats_header *header) +{ + ssize_t ret; + + ret = read(stats_fd, header, sizeof(*header)); + TEST_ASSERT(ret == sizeof(*header), "Read stats header"); +} From patchwork Wed Apr 20 17:35:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12820609 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 C49D9C433FE for ; Wed, 20 Apr 2022 17:35:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381155AbiDTRiO (ORCPT ); Wed, 20 Apr 2022 13:38:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53366 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381141AbiDTRiJ (ORCPT ); Wed, 20 Apr 2022 13:38:09 -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 9A98414095 for ; Wed, 20 Apr 2022 10:35:22 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id w3-20020a17090ac98300b001b8b914e91aso1252508pjt.0 for ; Wed, 20 Apr 2022 10:35:22 -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=IFGVGXrPp0JKSYr31Wh7oCBYK9LScbz2jTaBX8GqLkA=; b=EunJ/c1twOmedQgxPOPLKjh6UDM8DxR2YwbC3zz4KwPz+61o3j6KS571FUEAiB1rfX UD2QoAfDkgPDX1AgRQy2cY/C7lZobRi5aidT06jQ6TagwA+XiW9FLo4nkfmiLfDmnkhN HAbaGLk5r4NeCKuOCepjg+VMqJHuWRhTvr15QtgND8aBslOtyQ7RH4B/TaEbhtehIUiI tIQH5Lt3r6WYO78h0DB5DZvRdtaNAcdhyYm1rGcH52k+6JwcwZQfONN8XFEkN2qqyDQP uy83RGoWnoD2gRWCMV3XsQ5w7jc6a6FwwT476Zd7TDOxhl+03+bhbAKP2P8cQcq/wSfH W5sQ== 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=IFGVGXrPp0JKSYr31Wh7oCBYK9LScbz2jTaBX8GqLkA=; b=CDC0YrG4dpHga8tmj60ohL1nHQrpEUHgFpviH4JXwc+aPAjibvrRlwwjMvI2nP5Zqm TT+ocGptv9RlujEJl3/0VVBcDYTL1ElqMFTgDxDwAkvZM+qCpDx0rwOMaT16gTWuuDuG HBUoblJUK+2xuWdGRArRDdphhgEDWHKP64TdC02vy8KP3233TFqjQuywBLTE5jH6/h/p /NUVFtuUDz01RNm6aNIb8vSDE2+kEGjq36vm+Q+QedeSYXQmDeH0efbcnFpu+dL9TpVN N2hXZgQqv5s9wsk5/9NNxTf51f3lEDIeySXwojjkTc/ZgJYgzA/tvk+NZdtSpAlGPBf/ cd7w== X-Gm-Message-State: AOAM533fHwI5BEGrbNlReACn66yUsYHbIZwajVxW9ctFs0mSYIArLUvt ciEuFzXZOJXIe9GlhBAPRa6DDwesfaTf X-Google-Smtp-Source: ABdhPJw3BsCmwNNPj2DBXjtCbOyEoA2UFwm1nio4l/na63GTm4jZti88uWVQS74x8QcsTwokWYc99hM64MvX X-Received: from bgardon.sea.corp.google.com ([2620:15c:100:202:6ea6:489a:aad6:761c]) (user=bgardon job=sendgmr) by 2002:a17:90a:2e0d:b0:1c9:b839:af02 with SMTP id q13-20020a17090a2e0d00b001c9b839af02mr5620989pjd.122.1650476122112; Wed, 20 Apr 2022 10:35:22 -0700 (PDT) Date: Wed, 20 Apr 2022 10:35:06 -0700 In-Reply-To: <20220420173513.1217360-1-bgardon@google.com> Message-Id: <20220420173513.1217360-4-bgardon@google.com> Mime-Version: 1.0 References: <20220420173513.1217360-1-bgardon@google.com> X-Mailer: git-send-email 2.36.0.rc0.470.gd361397f0d-goog Subject: [PATCH v6 03/10] KVM: selftests: Read binary stats desc in lib From: Ben Gardon To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , 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 Signed-off-by: Ben Gardon Reviewed-by: Peter Xu --- .../selftests/kvm/include/kvm_util_base.h | 2 + .../selftests/kvm/kvm_binary_stats_test.c | 8 +--- tools/testing/selftests/kvm/lib/kvm_util.c | 38 +++++++++++++++++++ 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 749cded9b157..fabe46ddc1b2 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -401,6 +401,8 @@ void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid); int vm_get_stats_fd(struct kvm_vm *vm); int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vcpuid); void read_stats_header(int stats_fd, struct kvm_stats_header *header); +struct kvm_stats_desc *read_stats_desc(int stats_fd, + struct kvm_stats_header *header); uint32_t guest_get_vcpuid(void); diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c index fb511b42a03e..b49fae45db1e 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -62,14 +62,8 @@ 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_desc(stats_fd, &header); /* Sanity check for fields in descriptors */ for (i = 0; i < header.num_desc; ++i) { diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 1d75d41f92dc..12fa8cc88043 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -2577,3 +2577,41 @@ void read_stats_header(int stats_fd, struct kvm_stats_header *header) ret = read(stats_fd, header, sizeof(*header)); TEST_ASSERT(ret == sizeof(*header), "Read stats header"); } + +static ssize_t stats_descs_size(struct kvm_stats_header *header) +{ + return header->num_desc * + (sizeof(struct kvm_stats_desc) + header->name_size); +} + +/* + * 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_desc(int stats_fd, + struct kvm_stats_header *header) +{ + struct kvm_stats_desc *stats_desc; + ssize_t ret; + + stats_desc = malloc(stats_descs_size(header)); + TEST_ASSERT(stats_desc, "Allocate memory for stats descriptors"); + + ret = pread(stats_fd, stats_desc, stats_descs_size(header), + header->desc_offset); + TEST_ASSERT(ret == stats_descs_size(header), + "Read KVM stats descriptors"); + + return stats_desc; +} From patchwork Wed Apr 20 17:35:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12820611 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 2E64CC433F5 for ; Wed, 20 Apr 2022 17:35:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381184AbiDTRiV (ORCPT ); Wed, 20 Apr 2022 13:38:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53464 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381151AbiDTRiM (ORCPT ); Wed, 20 Apr 2022 13:38:12 -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 DE8B71C908 for ; Wed, 20 Apr 2022 10:35:24 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id n1-20020a654881000000b003a367d46721so1388154pgs.4 for ; Wed, 20 Apr 2022 10:35:24 -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=/WN+yQl9cRZbs0/aNri7VlZHQDfluYCzOSG0WstbyTE=; b=IdRdrVfW6zavsuxkVXPnJzXeo2nzapoQdyuhyUVdK59hwA12/+DIxIusvzG1Pgw1rY y33iLnu2Turp/on+QGE7p4SVQu/kFIrOPYhSa4JEmicJeeGUuHTNh9HBjGZnrAtKCyC+ Bi1pjf2gV8OIUOKS/DFlx4Mf3DOcxgd93DdJcLt+1IhUVcCudKZ6j5kjf/jQcVzhs7k/ iw8mz3BmDYzsTzINpIpQK5zRk42tGb8lIBR2Xs5n7QVP7W8VLWeZj93ikMeYZBouwv4Y Fp0I6v2667StwjFBDb32NrEoavujzCXFyIQCsm4Yp3q5XTFojTUXzX6hZl0qYFk9zdme II8A== 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=/WN+yQl9cRZbs0/aNri7VlZHQDfluYCzOSG0WstbyTE=; b=T5dcMFLSUR6lx5PELhmg/2jXEZ0kIbvBfBSWE3vLuF6EiiaYjqK8aofUXPtex1wW3O LYbu9NZnGujgtNlkOjlzw/rVpeKDZso+pVU7Nltrg4TJF4v5rG4wPX/UDbyXi5msZtiX iBZkykN8IFeoh/EctiizdjK0FbqflWKODCjCIk2CleU/Cph38oJPaVoUvo0164fU/BCv iUaCjoqdo0IyAa+1fiiNeSofj8ckAQrov23vbn7UZMMrOYOkiC5DsT1qbov6G2sVF2EV 2jxfxOrLku+nKcIRivJ3T4laAylpZfT84H3yQkp+hz490PwQOl5ZJ+jCh8Pyy90yVpGS Ag/A== X-Gm-Message-State: AOAM531hRF+PD5hxEW+rTo3tDcM07hY3Jh09fnhloxRZDBxrxcFSDw34 o5GnrMqclyRxDnjcZ1SG1gffBh2HMAfN X-Google-Smtp-Source: ABdhPJzXAeRMx6UDOA4niT29o66r3ow8bEfxQ/t864dKCjYXPRz2a5XhBz92ea/OoSzjbBm0oxWyi1OQSoh9 X-Received: from bgardon.sea.corp.google.com ([2620:15c:100:202:6ea6:489a:aad6:761c]) (user=bgardon job=sendgmr) by 2002:a17:90b:2384:b0:1cb:5223:9dc4 with SMTP id mr4-20020a17090b238400b001cb52239dc4mr80977pjb.1.1650476124026; Wed, 20 Apr 2022 10:35:24 -0700 (PDT) Date: Wed, 20 Apr 2022 10:35:07 -0700 In-Reply-To: <20220420173513.1217360-1-bgardon@google.com> Message-Id: <20220420173513.1217360-5-bgardon@google.com> Mime-Version: 1.0 References: <20220420173513.1217360-1-bgardon@google.com> X-Mailer: git-send-email 2.36.0.rc0.470.gd361397f0d-goog Subject: [PATCH v6 04/10] KVM: selftests: Clean up coding style in binary stats test From: Ben Gardon To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , 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 | 91 ++++++++++++------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c index b49fae45db1e..8b31f8fc7e08 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -35,47 +35,64 @@ static void stats_test(int stats_fd) /* Read kvm stats header */ read_stats_header(stats_fd, &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. + * But, the size of name is constant for a given instance of KVM and + * is provided by KVM in the overall stats header. + */ size_desc = sizeof(*stats_desc) + header.name_size; /* 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_desc(stats_fd, &header); /* Sanity check for fields in descriptors */ for (i = 0; i < header.num_desc; ++i) { + /* + * Note, size_desc includes the of the name field, which is + * variable, i.e. this is NOT equivalent to &stats_desc[i]. + */ pdesc = (void *)stats_desc + i * size_desc; - /* 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 + + /* Check type, unit, and 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 * 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 +103,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 = (void *)stats_desc + i * size_desc; 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 Wed Apr 20 17:35:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12820610 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 D2602C433EF for ; Wed, 20 Apr 2022 17:35:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381177AbiDTRiU (ORCPT ); Wed, 20 Apr 2022 13:38:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53484 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381154AbiDTRiN (ORCPT ); Wed, 20 Apr 2022 13:38:13 -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 861511E3DE for ; Wed, 20 Apr 2022 10:35:26 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id m8-20020a17090aab0800b001cb1320ef6eso3606506pjq.3 for ; Wed, 20 Apr 2022 10:35:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=2gtKOU35OdURDLf2vQT2shOzxYpqDt8gAksR5jX1bwc=; b=UerDsJvqa+wjYvw3RmbKSKCag/gLiIUrxMEtyPzWi98n6Txmyb9L0p4f6C/xpvujt/ 4n0UBt++725LBe3gMgr4uUovUw6nE+Hw4QtwonboW1shQ8kUTq9NM4THEMu9xupN5p8Q h0lMY8GOcEfBG9Jd+VD9WSBbh0m9vcagXxpQdSBwD/m2oW9zQML5rioZE1fRrGuNI7XP cfJcUOM8YKcJziaSlz14VdViSGv0Y0EFdCG+8GofENoqBBvwl4TG8oFplLlEGBZymozj FRLdJM6kQZibiIFtYct8U5D6CVmUycMqjiu5J4ansFXN4VivyCqxQ8gYvzCZNqQtp2Vl xDWw== 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=2gtKOU35OdURDLf2vQT2shOzxYpqDt8gAksR5jX1bwc=; b=h6jloA6dHxidU9y0DfPQwbMful/WLtxDJ8YS5klSPuFU/OW7CnGJwhSRWhEnc8Zs5k 9QstOz0kfNp2CXxmPMTIwCze+JCsV2brXRWesem0uN80HhLRQQGZJkTKduGQ6sbI/N/v VNfCzIZfZHWUbMhESZdMuCxLdWcRKDxaKs6YI40Kdxlyry5umxTjtTVmSYuK/2CDt/EP 30OgFnBDHf9Q4RlyeyV/ZqOqT9M991eKbdJYh4YBdIzfANUIm3uq22GpjvjPo3ZoQ9r6 70sWgtPMbM4cDimjNY2y3SKy4kDstcROINhZE0TK0p4lNMIdWzMPkkKsWzNFicE1KhUO SJLw== X-Gm-Message-State: AOAM531cMNDdDj52RXXfW+ihCSSKFm+40C/V1CEd/uBKuB4mMkiDxENJ En/Pw0ZajGTy/1z/JP4sqMTlbcenjLOf X-Google-Smtp-Source: ABdhPJymfloTy7XRp3ZJVIqCgiFCZHKjPQQqzUk2UH9hwRmzj7Aft1fc3NOFXJsNrgjFBZge2vJSLIJb+4Hv X-Received: from bgardon.sea.corp.google.com ([2620:15c:100:202:6ea6:489a:aad6:761c]) (user=bgardon job=sendgmr) by 2002:aa7:9019:0:b0:4fa:7532:9551 with SMTP id m25-20020aa79019000000b004fa75329551mr24877253pfo.26.1650476126053; Wed, 20 Apr 2022 10:35:26 -0700 (PDT) Date: Wed, 20 Apr 2022 10:35:08 -0700 In-Reply-To: <20220420173513.1217360-1-bgardon@google.com> Message-Id: <20220420173513.1217360-6-bgardon@google.com> Mime-Version: 1.0 References: <20220420173513.1217360-1-bgardon@google.com> X-Mailer: git-send-email 2.36.0.rc0.470.gd361397f0d-goog Subject: [PATCH v6 05/10] KVM: selftests: Read binary stat data in lib From: Ben Gardon To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , 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. No functional change intended. Reviewed-by: David Matlack Signed-off-by: Ben Gardon Reviewed-by: Peter Xu --- .../selftests/kvm/include/kvm_util_base.h | 3 ++ .../selftests/kvm/kvm_binary_stats_test.c | 7 ++-- tools/testing/selftests/kvm/lib/kvm_util.c | 36 +++++++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index fabe46ddc1b2..2a3a4d9ed8e3 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -403,6 +403,9 @@ int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vcpuid); void read_stats_header(int stats_fd, struct kvm_stats_header *header); struct kvm_stats_desc *read_stats_desc(int stats_fd, struct kvm_stats_header *header); +int read_stat_data(int stats_fd, struct kvm_stats_header *header, + struct kvm_stats_desc *desc, uint64_t *data, + ssize_t max_elements); uint32_t guest_get_vcpuid(void); diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c index 8b31f8fc7e08..59677fae26e5 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -160,11 +160,8 @@ static void stats_test(int stats_fd) size_data = 0; 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); - TEST_ASSERT(ret == pdesc->size * sizeof(*stats_data), - "Read data of KVM stats: %s", pdesc->name); + read_stat_data(stats_fd, &header, pdesc, stats_data, + pdesc->size); size_data += pdesc->size * sizeof(*stats_data); } diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 12fa8cc88043..ea4ab64e5997 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -2615,3 +2615,39 @@ struct kvm_stats_desc *read_stats_desc(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 + * + * Return: + * The number of data elements read into data or -ERRNO on error. + * + * Read the data values of a specified stat from the binary stats interface. + */ +int read_stat_data(int stats_fd, struct kvm_stats_header *header, + struct kvm_stats_desc *desc, uint64_t *data, + ssize_t max_elements) +{ + ssize_t size = min_t(ssize_t, desc->size, max_elements); + ssize_t ret; + + ret = pread(stats_fd, data, size * sizeof(*data), + header->data_offset + desc->offset); + + /* ret from pread is in bytes. */ + ret = ret / sizeof(*data); + + TEST_ASSERT(ret == size, + "Read data of KVM stats: %s", desc->name); + + return ret; +} From patchwork Wed Apr 20 17:35:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12820612 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 423A0C433EF for ; Wed, 20 Apr 2022 17:35:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381151AbiDTRiX (ORCPT ); Wed, 20 Apr 2022 13:38:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53546 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381136AbiDTRiR (ORCPT ); Wed, 20 Apr 2022 13:38:17 -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 5423F1C12F for ; Wed, 20 Apr 2022 10:35:28 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id y23-20020a62b517000000b004fd8affa86aso1608403pfe.12 for ; Wed, 20 Apr 2022 10:35: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=rxOyftFjuKDO9GheWZ+1hRlXO4qObtEuXZzpkIuZqXU=; b=BEDmq7MukwIVcVLTHw8TfhL29aIo6eeFswW4VObgpA9Hwmxalmsbfnt9oB0+CXZ5sb MX7x4zv3sA85SMikaZWTtMqFIo43NLQI1VWahardQ7aE+fJs+LXIH3RDdhB6P+S1QI6V dTJJNxwkOF1LwBOsKrFVZFgHXgvKqSdgZlMbiSMraIDT2w9W5UO7aGKKX5BFngTftWLD bVM5jAMC+8qSJPESpsaIz0HaZ+UTmwMWjICVPpGwm/KhdojtC2e3JLNpNxizEwHywz2c c/nd1ZGQ0IEpCIaq0L5pxz1wtMTuCSfNaDIi+jER5A8Co6EOu1NXL0noqs8QL4FASKbm owZg== 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=rxOyftFjuKDO9GheWZ+1hRlXO4qObtEuXZzpkIuZqXU=; b=LW2zePxo28gHVSCPvelca6IoAJfP4+/913excmURKIYZwwOaASdKXnmLEBV3MTF3Sk EKN09rRW+cubYQLPQPLxvVDjom/N2x7A1cGI+KPGIBG8etNRLXZPnJopNcO1o9WyrCD+ qM79CWlf2D6JVgYuPrMMR4COf2j58nTPcaauy5HoIgwtUgCKPCgRfqD4epGrVw7zQrQa 133u34dR0231S4CWKat2VDB1dL0EU3scpwYuDp5cQUYAy4Inkngy4UG8CLsSSpeAkmBd J759xMxtcWChkzBtele6zYbbGVGk0cD65vqLlCxQ/NGB00xBCJqS1khjaK+aXKoYts+F /Z3Q== X-Gm-Message-State: AOAM530DB2yHZuGyUOH5iLKqXxim8yizRWA/Gon2prF1b19w82kv0YOv I1SkWecnmTfNi7eSPMSFDCM5qHD0m5mn X-Google-Smtp-Source: ABdhPJygeQYB7dsDA6ZNx1F8dn8eYPKVPbfwvU99GbDclTbwlihsHWxjeY+wIer/TFt+hodZrVkaR0bGmiXS X-Received: from bgardon.sea.corp.google.com ([2620:15c:100:202:6ea6:489a:aad6:761c]) (user=bgardon job=sendgmr) by 2002:a05:6a00:1346:b0:50a:8fad:2b6d with SMTP id k6-20020a056a00134600b0050a8fad2b6dmr12541073pfu.79.1650476127840; Wed, 20 Apr 2022 10:35:27 -0700 (PDT) Date: Wed, 20 Apr 2022 10:35:09 -0700 In-Reply-To: <20220420173513.1217360-1-bgardon@google.com> Message-Id: <20220420173513.1217360-7-bgardon@google.com> Mime-Version: 1.0 References: <20220420173513.1217360-1-bgardon@google.com> X-Mailer: git-send-email 2.36.0.rc0.470.gd361397f0d-goog Subject: [PATCH v6 06/10] KVM: selftests: Add NX huge pages test From: Ben Gardon To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , 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. Reviewed-by: David Matlack Signed-off-by: Ben Gardon --- tools/testing/selftests/kvm/Makefile | 10 + .../selftests/kvm/include/kvm_util_base.h | 1 + tools/testing/selftests/kvm/lib/kvm_util.c | 78 ++++++++ .../selftests/kvm/x86_64/nx_huge_pages_test.c | 177 ++++++++++++++++++ .../kvm/x86_64/nx_huge_pages_test.sh | 25 +++ 5 files changed, 291 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/Makefile b/tools/testing/selftests/kvm/Makefile index af582d168621..9bb9bce4df37 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -43,6 +43,10 @@ LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c lib/aarch64/handler LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c lib/s390x/diag318_test_handler.c LIBKVM_riscv = lib/riscv/processor.c 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 @@ -104,6 +108,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 @@ -142,7 +149,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 @@ -193,6 +202,7 @@ $(OUTPUT)/libkvm.a: $(LIBKVM_OBJS) x := $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS)))) all: $(STATIC_LIBS) $(TEST_GEN_PROGS): $(STATIC_LIBS) +$(TEST_GEN_PROGS_EXTENDED): $(STATIC_LIBS) 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 2a3a4d9ed8e3..001b55ae25f8 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -406,6 +406,7 @@ struct kvm_stats_desc *read_stats_desc(int stats_fd, int read_stat_data(int stats_fd, struct kvm_stats_header *header, struct kvm_stats_desc *desc, uint64_t *data, ssize_t max_elements); +uint64_t vm_get_stat(struct kvm_vm *vm, const char *stat_name); uint32_t guest_get_vcpuid(void); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index ea4ab64e5997..9896cc49eb54 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -2651,3 +2651,81 @@ int read_stat_data(int stats_fd, struct kvm_stats_header *header, return 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 + * + * Return: + * The number of data elements read into data or -ERRNO on error. + * + * Read the data values of a specified stat from the binary stats interface. + */ +static int __vm_get_stat(struct kvm_vm *vm, const char *stat_name, + uint64_t *data, ssize_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 ret = -EINVAL; + int i; + + stats_fd = vm_get_stats_fd(vm); + + read_stats_header(stats_fd, &header); + + stats_desc = read_stats_desc(stats_fd, &header); + + size_desc = sizeof(struct kvm_stats_desc) + header.name_size; + + /* Read kvm stats data one by one */ + for (i = 0; i < header.num_desc; ++i) { + desc = (void *)stats_desc + (i * size_desc); + + if (strcmp(desc->name, stat_name)) + continue; + + ret = read_stat_data(stats_fd, &header, desc, data, + max_elements); + } + + free(stats_desc); + close(stats_fd); + return ret; +} + +/* + * Read the value 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 + * + * Output Args: None + * + * Return: + * The value of the stat + * + * Reads the value of the named stat through the binary stat interface. If + * the named stat has multiple data elements, only the first will be returned. + */ +uint64_t vm_get_stat(struct kvm_vm *vm, const char *stat_name) +{ + uint64_t data; + int ret; + + ret = __vm_get_stat(vm, stat_name, &data, 1); + TEST_ASSERT(ret == 1, + "Stat %s expected to have 1 element, but %d returned", + stat_name, ret); + return data; +} 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..1c14368500b7 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c @@ -0,0 +1,177 @@ +// 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" + +#define HPAGE_SLOT 10 +#define HPAGE_GVA (23*1024*1024) +#define HPAGE_GPA (10*1024*1024) +#define HPAGE_SLOT_NPAGES (512 * 3) +#define PAGE_SIZE 4096 + +/* + * 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 + +/* + * Exit the VM after each memory access so that the userspace component of the + * test can make assertions about the pages backing the VM. + */ +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); + + ((void (*)(void)) hpage_1)(); + GUEST_SYNC(3); + + ((void (*)(void)) 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 lpage split count. Expected %d, got %d", + expected_splits, actual_splits); +} + +int main(int argc, char **argv) +{ + struct kvm_vm *vm; + struct timespec ts; + void *hva; + + if (argc != 2 || strtol(argv[1], NULL, 0) != MAGIC_TOKEN) { + printf("This test must be run through nx_huge_pages_test.sh"); + return KSFT_SKIP; + } + + vm = vm_create_default(0, 0, guest_code); + + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS_HUGETLB, + HPAGE_GPA, HPAGE_SLOT, + HPAGE_SLOT_NPAGES, 0); + + virt_map(vm, HPAGE_GVA, HPAGE_GPA, HPAGE_SLOT_NPAGES); + + hva = addr_gpa2hva(vm, HPAGE_GPA); + memset(hva, RETURN_OPCODE, HPAGE_SLOT_NPAGES * PAGE_SIZE); + + check_2m_page_count(vm, 0); + check_split_count(vm, 0); + + /* + * The guest code will first read from the first hugepage, resulting + * in a huge page mapping being created. + */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 1); + check_split_count(vm, 0); + + /* + * Then the guest code will read from the second hugepage, resulting + * in another huge page mapping being created. + */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 2); + check_split_count(vm, 0); + + /* + * Next, the guest will execute from the first huge page, causing it + * to be remapped at 4k. + */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 1); + check_split_count(vm, 1); + + /* + * Executing from the third huge page (previously unaccessed) will + * cause part to be mapped at 4k. + */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 1); + check_split_count(vm, 2); + + /* Reading from the first huge page again should have no effect. */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 1); + check_split_count(vm, 2); + + /* + * Give recovery thread time to run. The wrapper script sets + * recovery_period_ms to 100, so wait 5x that. + */ + ts.tv_sec = 0; + ts.tv_nsec = 500000000; + nanosleep(&ts, NULL); + + /* + * Now that the reclaimer has run, all the split pages should be gone. + */ + check_2m_page_count(vm, 1); + check_split_count(vm, 0); + + /* + * The 4k mapping on hpage 3 should have been removed, so check that + * reading from it causes a huge page mapping to be installed. + */ + vcpu_run(vm, 0); + check_2m_page_count(vm, 2); + check_split_count(vm, 0); + + kvm_vm_free(vm); + + return 0; +} + diff --git a/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh b/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh new file mode 100755 index 000000000000..c2429ad8066a --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-only */ + +# tools/testing/selftests/kvm/nx_huge_page_test.sh +# Copyright (C) 2022, Google LLC. + +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) + +echo 1 > /sys/module/kvm/parameters/nx_huge_pages +echo 1 > /sys/module/kvm/parameters/nx_huge_pages_recovery_ratio +echo 100 > /sys/module/kvm/parameters/nx_huge_pages_recovery_period_ms +echo 200 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages + +"$(dirname $0)"/nx_huge_pages_test 887563923 +RET=$? + +echo $NX_HUGE_PAGES > /sys/module/kvm/parameters/nx_huge_pages +echo $NX_HUGE_PAGES_RECOVERY_RATIO > /sys/module/kvm/parameters/nx_huge_pages_recovery_ratio +echo $NX_HUGE_PAGES_RECOVERY_PERIOD > /sys/module/kvm/parameters/nx_huge_pages_recovery_period_ms +echo $HUGE_PAGES > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages + +exit $RET From patchwork Wed Apr 20 17:35:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12820613 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 017C8C433EF for ; Wed, 20 Apr 2022 17:35:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381195AbiDTRi1 (ORCPT ); Wed, 20 Apr 2022 13:38:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53556 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381169AbiDTRiR (ORCPT ); Wed, 20 Apr 2022 13:38:17 -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 3B681201BD for ; Wed, 20 Apr 2022 10:35:30 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id z18-20020a631912000000b003a392265b64so1393717pgl.2 for ; Wed, 20 Apr 2022 10:35: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=Oj7z6gF3UmFPqpARpPyMhAnqQVwNhos0ksWVaS2glIE=; b=BHW4MoPP2qr6KkJ/bv2IsG+E7kEQXfxOROPLzA/Q0FGDcoBzR8RG3LaCyDgc+N/VZD ebM5y3USor/huYodLjYAIrwk+3trvOyQqnp/3EC2drn0LDVzJNrGW8kjD8kAueuW1sCv 9SqEOSQTgoVR5UMh2Ggs4IzpLD3upFTu8YsObU3SkgGfjoSNkRzyw7tiqIWKO/1y60PD dkJDpj3NgVL9l9i36GP4khKUbxDXLDKKaTmeZaADvtYr1NiPrMNl/FVAKN7Kki3AQ3VM SjFcdRFoq2Mzy+dyYsA+ZUCkiTDeAMTcmYg9Sub9vwJqwC6vKt9J4BIu5yhgMpo9WgPi Xn+A== 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=Oj7z6gF3UmFPqpARpPyMhAnqQVwNhos0ksWVaS2glIE=; b=EuXjcmgh1XK8Lxdn31WtWi/ukdXwA+zAvKo8DacgPvY3z7ryvkPZLQrqeWy+K5rRcK oVhodz7zIry198+CPgNNUObEKkOUuclp41hb2h4U9WkG3w/Up7roFico75Xp78jrS4UJ I8bNaEbsOA0uC7AqGNYlEREW1nam2NBMHIRhj7wrXXXGW9ybn6pWCbVs/Ml26E9mAiJ9 2f46jfcuFFzz2c+CkDutOFzcSk2GjlGwbfMuPBSOImJQGh+grTRCWsa42e7qw9rdB2ai UzlScVYFgVX8NOvoti43webuzOpy4kPod9wv2KkGCv9GFtlHS7umpxhuNX60emB7uCdB uz7Q== X-Gm-Message-State: AOAM533UGm0jUe/Fjrjtc7DTQI4AVpZkMJfPnh0pue/yaKSLzkyZmOKT kpoCIxM4qFPe/Qlh2FdWU57YEuFtm5Mj X-Google-Smtp-Source: ABdhPJzDSmuusSkVSzZvaX/pcqMXPsz/BlZMEv7jAS+fuTBtjfO8rwJ48kCEMy1Q77d2R6RIlL4rmKwZsKAJ X-Received: from bgardon.sea.corp.google.com ([2620:15c:100:202:6ea6:489a:aad6:761c]) (user=bgardon job=sendgmr) by 2002:a17:90b:33ca:b0:1d4:d5ab:40b0 with SMTP id lk10-20020a17090b33ca00b001d4d5ab40b0mr3119586pjb.96.1650476129737; Wed, 20 Apr 2022 10:35:29 -0700 (PDT) Date: Wed, 20 Apr 2022 10:35:10 -0700 In-Reply-To: <20220420173513.1217360-1-bgardon@google.com> Message-Id: <20220420173513.1217360-8-bgardon@google.com> Mime-Version: 1.0 References: <20220420173513.1217360-1-bgardon@google.com> X-Mailer: git-send-email 2.36.0.rc0.470.gd361397f0d-goog Subject: [PATCH v6 07/10] KVM: x86: Fix errant brace in KVM capability handling From: Ben Gardon To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , 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 Signed-off-by: Ben Gardon Reviewed-by: Peter Xu --- 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 ab336f7c82e4..665c1fa8bb57 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4382,10 +4382,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 Wed Apr 20 17:35:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12820614 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 D496EC433F5 for ; Wed, 20 Apr 2022 17:35:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381204AbiDTRib (ORCPT ); Wed, 20 Apr 2022 13:38:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53546 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381170AbiDTRiT (ORCPT ); Wed, 20 Apr 2022 13:38:19 -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 068D11A822 for ; Wed, 20 Apr 2022 10:35:32 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id f124-20020a62db82000000b0050a453457e6so1594708pfg.22 for ; Wed, 20 Apr 2022 10:35: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=Pb69So25pghqr3yKx0xBM1J+DZG/4lmWXWSjSGs/cvE=; b=V0xvGAHtONnivxs1A5sK7OQuKU9MuGAjkzAznuRuZxklsbvCmB/7bcgdVGpfbaOIgH x2KarfDdiu61adqy52bHoyKn66w9O8AanPtEKZ5IQh2sUsiNrnqDd+qxyj1QxOt7Z/Uj MeRQNGHrUKFMdsFBYn9afcRNLXmWqlRXWudK3Pfr/oP22yiV5nCAlcwea85dg1LGZ39E +qQbj9IEDH4G/qwAmp2HX60BHhp+axhyh13r1a78l+dRqGGTQJt+Y6ci11IW1Pb3WGGZ 6eBNeNZDbVRI1kwC34LJ6Ajfaq5eA4YFT55/+gCmWkdpicb3kaOltqixfxKi1eozPqFd 0Tag== 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=Pb69So25pghqr3yKx0xBM1J+DZG/4lmWXWSjSGs/cvE=; b=AtYe2Zd9a5fdJPppwvhw/ByWxNt5S3ifsnrDgSlB7QePEO3r8w8AfdjLMA246Y2785 /ZoFurWierR44XqSNTvGzWtuN4FB+R9sEYGp6gSVAyARsgJjo09XCO639Se2vdMlWo9B 4555nyeqC9gsFBE4JpWi3eEH/ZejtsgN1i0998nNJCPrzG3zmn3e/72FrGGKVte8sns3 Z/V2OnziNDjVMhb3so+ntJJwMLjsC0qFtrx226Guhp87eDdtrBmKat7Dntox/0BH25wt 9yAGPRpyX3DBioSdxfWE0MiafcX3ud1kpwi+mcWt+ja6gxPh/9+yEQlpv6MtU3SlFCU/ e/zg== X-Gm-Message-State: AOAM5325/TVwLGu3qRGIBDL1TR32AAVy2OWXLiEmgkd+qFUii04/klqk XPCGEfl5IMBngIVdtZwmSGzYuqQNm3MN X-Google-Smtp-Source: ABdhPJxJyS53NuRmzHHu1kQo6KlmPF7da27Hiz4rRUNk9VIjSo438WuXkeqZze/PCH9WC8o8IC5aS3vk58cR X-Received: from bgardon.sea.corp.google.com ([2620:15c:100:202:6ea6:489a:aad6:761c]) (user=bgardon job=sendgmr) by 2002:a63:5013:0:b0:399:5816:fd0d with SMTP id e19-20020a635013000000b003995816fd0dmr20113498pgb.68.1650476131563; Wed, 20 Apr 2022 10:35:31 -0700 (PDT) Date: Wed, 20 Apr 2022 10:35:11 -0700 In-Reply-To: <20220420173513.1217360-1-bgardon@google.com> Message-Id: <20220420173513.1217360-9-bgardon@google.com> Mime-Version: 1.0 References: <20220420173513.1217360-1-bgardon@google.com> X-Mailer: git-send-email 2.36.0.rc0.470.gd361397f0d-goog Subject: [PATCH v6 08/10] KVM: x86/MMU: Allow NX huge pages to be disabled on a per-vm basis From: Ben Gardon To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , 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 Signed-off-by: Ben Gardon Reviewed-by: Peter Xu --- Documentation/virt/kvm/api.rst | 17 +++++++++++++++++ arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/mmu.h | 8 ++++---- 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 | 29 +++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 1 + 8 files changed, 60 insertions(+), 9 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 72183ae628f7..b1ed4e260163 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -7855,6 +7855,23 @@ At this time, KVM_PMU_CAP_DISABLE is the only capability. Setting this capability will disable PMU virtualization for that VM. Usermode should adjust CPUID leaf 0xA to reflect that the PMU is disabled. +8.36 KVM_CAP_VM_DISABLE_NX_HUGE_PAGES +--------------------------- + +:Capability KVM_CAP_PMU_CAPABILITY +: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 2c20f715f009..b8ab4fa7d4b2 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1240,6 +1240,8 @@ struct kvm_arch { hpa_t hv_root_tdp; spinlock_t hv_root_tdp_lock; #endif + + bool disable_nx_huge_pages; }; struct kvm_vm_stat { diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 671cfeccf04e..36c6d8c3561b 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -173,9 +173,9 @@ struct kvm_page_fault { int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault); 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; } static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, @@ -191,8 +191,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, .goal_level = PG_LEVEL_4K, diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c index 4739b53c9734..877ad30bc7ad 100644 --- a/arch/x86/kvm/mmu/spte.c +++ b/arch/x86/kvm/mmu/spte.c @@ -116,7 +116,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; } @@ -215,7 +215,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; @@ -243,7 +244,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 73f12615416f..e4142caff4b1 100644 --- a/arch/x86/kvm/mmu/spte.h +++ b/arch/x86/kvm/mmu/spte.h @@ -415,7 +415,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 566548a3efa7..63a1111916c3 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -1469,7 +1469,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 665c1fa8bb57..1a718270a8ae 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4286,6 +4286,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: @@ -6079,6 +6080,34 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, } mutex_unlock(&kvm->lock); break; + case KVM_CAP_VM_DISABLE_NX_HUGE_PAGES: + r = -EINVAL; + if (cap->args[0]) + break; + + /* + * 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; + } + + 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 dd1d8167e71f..7155488164bd 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1148,6 +1148,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PMU_CAPABILITY 212 #define KVM_CAP_DISABLE_QUIRKS2 213 #define KVM_CAP_VM_TSC_CONTROL 214 +#define KVM_CAP_VM_DISABLE_NX_HUGE_PAGES 215 #ifdef KVM_CAP_IRQ_ROUTING From patchwork Wed Apr 20 17:35:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12820616 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 4BF64C433EF for ; Wed, 20 Apr 2022 17:35:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381215AbiDTRie (ORCPT ); Wed, 20 Apr 2022 13:38:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53560 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381180AbiDTRiU (ORCPT ); Wed, 20 Apr 2022 13:38:20 -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 D51DA3969C for ; Wed, 20 Apr 2022 10:35:33 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id u8-20020a170903124800b0015195a5826cso1212654plh.4 for ; Wed, 20 Apr 2022 10:35: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=F7BTz3UYuckCYc6h4+8BkViO+YHmKFw1VG8oiYkTzgM=; b=sCbgwuLgrv/khlU2vBDG9v2HoneCXMOefIYAuUa2j8GPOgjPwbLpi3He5El5tUNQWE sn3aLRY2eF2M6d2nMevXGxh+c4CUTrgq+r04sTXUr6kpDOWM++gCGLNFXYDM5mFIDN9a e3J3FMxgXibPjcmAuViSZAWDf67HQoB4CHv8RtQvFnCPHfwcl3ZQFpmMJmIahfGtxzPe 5LzxUo+Vw79XjvPzwxjJyKVRWSEomgNehatsabJbFPOxeUQ38HJlEtEGYruM9HcBqzYa yNjLH82tSmw0QzYVndCUBnfgOvDOt2I9wji+bK31sqetJEgwM2tcXfDA4FqEAehLrrAd LirA== 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=F7BTz3UYuckCYc6h4+8BkViO+YHmKFw1VG8oiYkTzgM=; b=z/oU5M3gPU+YluO4JhpS+0So9kbJpuk8GQBxwsCSbB1KcXCmWScehH29APMsJ2wxiC b3EVLFI+QJ3sHx4h3RjVu7hKeqwroA8r7dj3F23fwcCxfc+NsFpLDK75s1l123qyJFMR rTzoSg110sQfRGypD32X/W7GpZyLigrFozkKf1jSINSSNSz4H9DXgWAT5fsf8afc/U1j PsvuJY/LqOARFjD9iGFglbAuaUMx/Qq96FPTlMxbnCfb/ZrLI4ODo57tA+0ryI+Yss60 gChbEp/uzLdOMJYx1pMJPWO+v1HU4DlRrj4bYWtJRDf4WjgHosoxUhFy2NaA+qtIyDov rB/A== X-Gm-Message-State: AOAM5312jMaPmBW+ipg3ePsuAXAacySGhstRZYgNdsBibFRZPV9CfGul VMIX1V6yjtQEp195A38hGhxu3lTlLeVT X-Google-Smtp-Source: ABdhPJza1o9TizJ9V4m5v3pPsQ19ezTv5C2RbqVG53c878oDXhLABn9JLz07ry5Y2Xh7dwlngHlQjg66I0Qa X-Received: from bgardon.sea.corp.google.com ([2620:15c:100:202:6ea6:489a:aad6:761c]) (user=bgardon job=sendgmr) by 2002:a17:90b:4a92:b0:1d2:8f4c:feee with SMTP id lp18-20020a17090b4a9200b001d28f4cfeeemr5654544pjb.41.1650476133363; Wed, 20 Apr 2022 10:35:33 -0700 (PDT) Date: Wed, 20 Apr 2022 10:35:12 -0700 In-Reply-To: <20220420173513.1217360-1-bgardon@google.com> Message-Id: <20220420173513.1217360-10-bgardon@google.com> Mime-Version: 1.0 References: <20220420173513.1217360-1-bgardon@google.com> X-Mailer: git-send-email 2.36.0.rc0.470.gd361397f0d-goog Subject: [PATCH v6 09/10] KVM: selftests: Factor out calculation of pages needed for a VM From: Ben Gardon To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , 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 Factor out the calculation of the number of pages needed for a VM to make it easier to separate creating the VM and adding vCPUs. Reviewed-by: David Matlack Signed-off-by: Ben Gardon Reviewed-by: Peter Xu --- .../selftests/kvm/include/kvm_util_base.h | 4 ++ tools/testing/selftests/kvm/lib/kvm_util.c | 59 ++++++++++++++----- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 001b55ae25f8..1dac3c6607f1 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -312,6 +312,10 @@ vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, vm_paddr_t paddr_min, uint32_t memslot); vm_paddr_t vm_alloc_page_table(struct kvm_vm *vm); +uint64_t vm_pages_needed(enum vm_guest_mode mode, uint32_t nr_vcpus, + uint64_t slot0_mem_pages, uint64_t extra_mem_pages, + uint32_t num_percpu_pages); + /* * Create a VM with reasonable defaults * diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 9896cc49eb54..392abd3c323d 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -377,7 +377,7 @@ struct kvm_vm *vm_create_without_vcpus(enum vm_guest_mode mode, uint64_t pages) } /* - * VM Create with customized parameters + * Get the number of pages needed for a VM * * Input Args: * mode - VM Mode (e.g. VM_MODE_P52V48_4K) @@ -385,27 +385,17 @@ struct kvm_vm *vm_create_without_vcpus(enum vm_guest_mode mode, uint64_t pages) * slot0_mem_pages - Slot0 physical memory size * extra_mem_pages - Non-slot0 physical memory total size * num_percpu_pages - Per-cpu physical memory pages - * guest_code - Guest entry point - * vcpuids - VCPU IDs * * Output Args: None * * Return: - * Pointer to opaque structure that describes the created VM. - * - * Creates a VM with the mode specified by mode (e.g. VM_MODE_P52V48_4K), - * with customized slot0 memory size, at least 512 pages currently. - * extra_mem_pages is only used to calculate the maximum page table size, - * no real memory allocation for non-slot0 memory in this function. + * The number of pages needed for the VM. */ -struct kvm_vm *vm_create_with_vcpus(enum vm_guest_mode mode, uint32_t nr_vcpus, - uint64_t slot0_mem_pages, uint64_t extra_mem_pages, - uint32_t num_percpu_pages, void *guest_code, - uint32_t vcpuids[]) +uint64_t vm_pages_needed(enum vm_guest_mode mode, uint32_t nr_vcpus, + uint64_t slot0_mem_pages, uint64_t extra_mem_pages, + uint32_t num_percpu_pages) { uint64_t vcpu_pages, extra_pg_pages, pages; - struct kvm_vm *vm; - int i; /* Force slot0 memory size not small than DEFAULT_GUEST_PHY_PAGES */ if (slot0_mem_pages < DEFAULT_GUEST_PHY_PAGES) @@ -421,11 +411,48 @@ struct kvm_vm *vm_create_with_vcpus(enum vm_guest_mode mode, uint32_t nr_vcpus, extra_pg_pages = (slot0_mem_pages + extra_mem_pages + vcpu_pages) / PTES_PER_MIN_PAGE * 2; pages = slot0_mem_pages + vcpu_pages + extra_pg_pages; + pages = vm_adjust_num_guest_pages(mode, pages); + + return pages; +} + +/* + * VM Create with customized parameters + * + * Input Args: + * mode - VM Mode (e.g. VM_MODE_P52V48_4K) + * nr_vcpus - VCPU count + * slot0_mem_pages - Slot0 physical memory size + * extra_mem_pages - Non-slot0 physical memory total size + * num_percpu_pages - Per-cpu physical memory pages + * guest_code - Guest entry point + * vcpuids - VCPU IDs + * + * Output Args: None + * + * Return: + * Pointer to opaque structure that describes the created VM. + * + * Creates a VM with the mode specified by mode (e.g. VM_MODE_P52V48_4K), + * with customized slot0 memory size, at least 512 pages currently. + * extra_mem_pages is only used to calculate the maximum page table size, + * no real memory allocation for non-slot0 memory in this function. + */ +struct kvm_vm *vm_create_with_vcpus(enum vm_guest_mode mode, uint32_t nr_vcpus, + uint64_t slot0_mem_pages, uint64_t extra_mem_pages, + uint32_t num_percpu_pages, void *guest_code, + uint32_t vcpuids[]) +{ + uint64_t pages; + struct kvm_vm *vm; + int i; + TEST_ASSERT(nr_vcpus <= kvm_check_cap(KVM_CAP_MAX_VCPUS), "nr_vcpus = %d too large for host, max-vcpus = %d", nr_vcpus, kvm_check_cap(KVM_CAP_MAX_VCPUS)); - pages = vm_adjust_num_guest_pages(mode, pages); + pages = vm_pages_needed(mode, nr_vcpus, slot0_mem_pages, + extra_mem_pages, num_percpu_pages); vm = vm_create_without_vcpus(mode, pages); From patchwork Wed Apr 20 17:35:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Gardon X-Patchwork-Id: 12820615 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 901E4C433EF for ; Wed, 20 Apr 2022 17:35:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381209AbiDTRid (ORCPT ); Wed, 20 Apr 2022 13:38:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53544 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381185AbiDTRiW (ORCPT ); Wed, 20 Apr 2022 13:38: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 B488120182 for ; Wed, 20 Apr 2022 10:35:35 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id w3-20020a17090ac98300b001b8b914e91aso1252738pjt.0 for ; Wed, 20 Apr 2022 10:35: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=t1qdKpsCnPq2yg+IbIgoIM3FH9J2c/2rFr+NjJBX138=; b=BzLL3VXYf4ndvrHhCti6YaW7JZJj5Xv+KCCU2qP47itKN60iWZzI8RSw4m00HDsxNQ gdguMcmVFq/ktoIGahb5zRZ/zN3VZSkPbNKlQmUkz4d0B14tMaNz/zFWgXBN14mWJ4Km Fg8REazcd4iTQv3+DfYRhntLs/GqnqCVHBXwfgzS4NtW7NB9WRlwtGij3TLSWtZr9KsL tVJZxrSslYjS30KCQl1Blzwuk7VHs4d6KJXBoWClwPpWBDfM8dGxTTI0y2AyTdktVKCn MR0sOE571B5LSNNErWqRA9K8eJrIDfXQvF3nU9b8tE3jVrhCvoeCH4VMiMLW0Gmtu4Sv 9qbQ== 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=t1qdKpsCnPq2yg+IbIgoIM3FH9J2c/2rFr+NjJBX138=; b=YJpeMx0NBK4n1CZ24HIWCb1fXBJvdTvI5udEEZR9OqkHRL00dBiehUq9uGULSF4nZR CtmaSvnDfUFfRBmxcNau9NNDX9J20TR2wkE2/k6fPas8smPtJDG4rf4yBbrcuZKMtc7j blUhxMEPfkywW38GRqMxayAFEzdxmw5AlOfbwGFv850rw4AoEmcTQT1x7VJFWVhfChBv Zd/cZ8lodFq5N4x0BZ4QHTQ8kTmFAmIJBDIO2XW1tM16yNFAXNzHXKcSXlJtt0nf4/p6 b8IS/Mmidveh2ZVjJlLpXRiez3fzihCoLujt4+cRUOCg9Ztu7noDtoLGrNWKckc1RVbU Ms3g== X-Gm-Message-State: AOAM5335JbxpJ+3WzIxnkeLK/z2xu8746hvzl8gUln0hfXI5pat67TrG yzFevZAyu/HcCJOIDwa4/Z654Nbjdl35 X-Google-Smtp-Source: ABdhPJyIPe8Zwza+xW/aDTMdJP2bDzL1LCb4zN48ZpvL5g0mQxKhr/6n1V2w1tLSW7XWdrXysAKEchMVMTC2 X-Received: from bgardon.sea.corp.google.com ([2620:15c:100:202:6ea6:489a:aad6:761c]) (user=bgardon job=sendgmr) by 2002:a05:6a00:ad0:b0:4e1:2d96:2ab0 with SMTP id c16-20020a056a000ad000b004e12d962ab0mr24396722pfl.3.1650476135250; Wed, 20 Apr 2022 10:35:35 -0700 (PDT) Date: Wed, 20 Apr 2022 10:35:13 -0700 In-Reply-To: <20220420173513.1217360-1-bgardon@google.com> Message-Id: <20220420173513.1217360-11-bgardon@google.com> Mime-Version: 1.0 References: <20220420173513.1217360-1-bgardon@google.com> X-Mailer: git-send-email 2.36.0.rc0.470.gd361397f0d-goog Subject: [PATCH v6 10/10] KVM: selftests: Test disabling NX hugepages on a VM From: Ben Gardon To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , 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 | 2 + tools/testing/selftests/kvm/lib/kvm_util.c | 16 +++- .../selftests/kvm/x86_64/nx_huge_pages_test.c | 75 +++++++++++++++---- .../kvm/x86_64/nx_huge_pages_test.sh | 39 ++++++---- 4 files changed, 104 insertions(+), 28 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 1dac3c6607f1..8f6aad253392 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -414,4 +414,6 @@ uint64_t vm_get_stat(struct kvm_vm *vm, const char *stat_name); uint32_t guest_get_vcpuid(void); +int vm_disable_nx_huge_pages(struct kvm_vm *vm); + #endif /* SELFTEST_KVM_UTIL_BASE_H */ diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 392abd3c323d..96faa14f4f32 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -112,6 +112,11 @@ int vm_check_cap(struct kvm_vm *vm, long cap) return ret; } +static int __vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap) +{ + return ioctl(vm->fd, KVM_ENABLE_CAP, cap); +} + /* VM Enable Capability * * Input Args: @@ -128,7 +133,7 @@ int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap) { int ret; - ret = ioctl(vm->fd, KVM_ENABLE_CAP, cap); + ret = __vm_enable_cap(vm, cap); TEST_ASSERT(ret == 0, "KVM_ENABLE_CAP IOCTL failed,\n" " rc: %i errno: %i", ret, errno); @@ -2756,3 +2761,12 @@ uint64_t vm_get_stat(struct kvm_vm *vm, const char *stat_name) stat_name, ret); return data; } + +int vm_disable_nx_huge_pages(struct kvm_vm *vm) +{ + struct kvm_enable_cap cap = { 0 }; + + cap.cap = KVM_CAP_VM_DISABLE_NX_HUGE_PAGES; + cap.args[0] = 0; + return __vm_enable_cap(vm, &cap); +} 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 1c14368500b7..41b228b8cac3 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 @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include "kvm_util.h" @@ -86,18 +88,45 @@ static void check_split_count(struct kvm_vm *vm, int expected_splits) expected_splits, actual_splits); } -int main(int argc, char **argv) +void run_test(bool disable_nx_huge_pages) { struct kvm_vm *vm; struct timespec ts; + uint64_t pages; void *hva; - - if (argc != 2 || strtol(argv[1], NULL, 0) != MAGIC_TOKEN) { - printf("This test must be run through nx_huge_pages_test.sh"); - return KSFT_SKIP; + int r; + + pages = vm_pages_needed(VM_MODE_DEFAULT, 1, DEFAULT_GUEST_PHY_PAGES, + 0, 0); + vm = vm_create_without_vcpus(VM_MODE_DEFAULT, pages); + + if (disable_nx_huge_pages) { + kvm_check_cap(KVM_CAP_VM_DISABLE_NX_HUGE_PAGES); + + /* + * Check if this process has the reboot permissions needed to + * disable NX huge pages on a VM. + * + * The reboot call below will never have any effect because + * the magic values are not set correctly, however the + * permission check is done before the magic value check. + */ + r = syscall(SYS_reboot, 0, 0, 0, NULL); + if (r && errno == EPERM) { + r = vm_disable_nx_huge_pages(vm); + TEST_ASSERT(errno == EPERM, + "This process should not have permission to disable NX huge pages"); + return; + } + + TEST_ASSERT(r && errno == EINVAL, + "Reboot syscall should fail with -EINVAL"); + + r = vm_disable_nx_huge_pages(vm); + TEST_ASSERT(!r, "Disabling NX huge pages should succeed if process has reboot permissions"); } - vm = vm_create_default(0, 0, guest_code); + vm_vcpu_add_default(vm, 0, guest_code); vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS_HUGETLB, HPAGE_GPA, HPAGE_SLOT, @@ -130,23 +159,27 @@ int main(int argc, char **argv) /* * Next, the guest will execute from the first huge page, causing it * to be remapped at 4k. + * + * If NX huge pages are disabled, this should have no effect. */ vcpu_run(vm, 0); - check_2m_page_count(vm, 1); - check_split_count(vm, 1); + check_2m_page_count(vm, disable_nx_huge_pages ? 2 : 1); + check_split_count(vm, disable_nx_huge_pages ? 0 : 1); /* * Executing from the third huge page (previously unaccessed) will * cause part to be mapped at 4k. + * + * If NX huge pages are disabled, it should be mapped at 2M. */ vcpu_run(vm, 0); - check_2m_page_count(vm, 1); - check_split_count(vm, 2); + check_2m_page_count(vm, disable_nx_huge_pages ? 3 : 1); + check_split_count(vm, disable_nx_huge_pages ? 0 : 2); /* Reading from the first huge page again should have no effect. */ vcpu_run(vm, 0); - check_2m_page_count(vm, 1); - check_split_count(vm, 2); + check_2m_page_count(vm, disable_nx_huge_pages ? 3 : 1); + check_split_count(vm, disable_nx_huge_pages ? 0 : 2); /* * Give recovery thread time to run. The wrapper script sets @@ -158,8 +191,11 @@ int main(int argc, char **argv) /* * 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); /* @@ -167,10 +203,21 @@ int main(int argc, char **argv) * reading from it causes a huge page mapping to be installed. */ vcpu_run(vm, 0); - check_2m_page_count(vm, 2); + check_2m_page_count(vm, disable_nx_huge_pages ? 3 : 2); check_split_count(vm, 0); kvm_vm_free(vm); +} + +int main(int argc, char **argv) +{ + if (argc != 2 || strtol(argv[1], NULL, 0) != MAGIC_TOKEN) { + printf("This test must be run through nx_huge_pages_test.sh"); + return KSFT_SKIP; + } + + run_test(false); + run_test(true); 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 c2429ad8066a..b23993f3aab1 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 @@ -4,22 +4,35 @@ # tools/testing/selftests/kvm/nx_huge_page_test.sh # Copyright (C) 2022, Google LLC. -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) +NX_HUGE_PAGES=$(sudo cat /sys/module/kvm/parameters/nx_huge_pages) +NX_HUGE_PAGES_RECOVERY_RATIO=$(sudo cat /sys/module/kvm/parameters/nx_huge_pages_recovery_ratio) +NX_HUGE_PAGES_RECOVERY_PERIOD=$(sudo cat /sys/module/kvm/parameters/nx_huge_pages_recovery_period_ms) +HUGE_PAGES=$(sudo cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages) -echo 1 > /sys/module/kvm/parameters/nx_huge_pages -echo 1 > /sys/module/kvm/parameters/nx_huge_pages_recovery_ratio -echo 100 > /sys/module/kvm/parameters/nx_huge_pages_recovery_period_ms -echo 200 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages +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 200 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages + +NXECUTABLE="$(dirname $0)/nx_huge_pages_test" + +# Test with reboot permissions +sudo setcap cap_sys_boot+ep $NXECUTABLE +$NXECUTABLE 887563923 -"$(dirname $0)"/nx_huge_pages_test 887563923 RET=$? -echo $NX_HUGE_PAGES > /sys/module/kvm/parameters/nx_huge_pages -echo $NX_HUGE_PAGES_RECOVERY_RATIO > /sys/module/kvm/parameters/nx_huge_pages_recovery_ratio -echo $NX_HUGE_PAGES_RECOVERY_PERIOD > /sys/module/kvm/parameters/nx_huge_pages_recovery_period_ms -echo $HUGE_PAGES > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages +if [ $RET -eq 0 ]; then + # Test without reboot permissions + sudo setcap cap_sys_boot-ep $NXECUTABLE + $NXECUTABLE 887563923 + + RET=$? +fi + +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