Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp3748317pxv; Mon, 26 Jul 2021 10:57:45 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxrgRnCCrht1ZJa0h/BUDjFKpb6/V5jg7nOITzbRSeeVSiHtLZzTQ6Mjnfsm7mgxlq460Mk X-Received: by 2002:a17:906:57d0:: with SMTP id u16mr18692641ejr.468.1627322264967; Mon, 26 Jul 2021 10:57:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1627322264; cv=none; d=google.com; s=arc-20160816; b=nXdWFhS7C7JXwawBhPCnhc+yxQgIufnHb2l7/y4wr6SQPaZj5yUHJMbBndXwj7aVJ7 PZWSYnaK5etRhVodn7VodzvFgDGxfPk8i4wzzODYDAzHkVZhICIv8nG3Ma9LAwMVQn/m d+RQilc30VznAe3MC5ArxUSoWBLKti2wa5oGs0q0yBiBnyTsHBI6NdW0kX6hB8FPgatL TZnSCyh4Iw9ixm2B/SLk698AMP6FVSKFqdlQ2YoiHegY7As9lzL1qa2XxuxicX9NH6OL bvEjY7lxxiQ0m3Mq8FkCzIkcdnF39orxm+xjLw6qUnAkSgKZ0sWC3Ct6U7f8MqYviq/W NFcA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:reply-to:dkim-signature; bh=9UyZrt9F1H6UN7DWee5vqzeFLel0aRWyUB8vgzqX0Ms=; b=qd4PQAf4v8ZR0p9KxFzZIA1irPQCtP0YdQk1482SJJ1geSYDhg5dnWq9fgVUj/AlTH /UOPa/u/c5jCSqB6uk3czMbHCVhZKDeevjTs5i330nCQE7k4NfTWj1PQLN+hP4SFNX2b Ah7ipOlKhzNJ+Mr2VcDhdzztx+wI+MlovzrPzqEXAOWAJzG/oIEuvC0/Xx0/NbJ5jRxK nrIuVC1vhX85FBqqA8giMZc55Fe4SoyyzxxLCI0UW0PNnYuIPW9trvyfDcvw5qhWnM1x 5py4rVRi/h3ABAtDDl+xt0uXcbOb4RMZbChp8mpE2+BrVQ19oH50ou13MBmzdAR0237y MdKQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=eI5TOmA8; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id hp8si491463ejc.333.2021.07.26.10.57.21; Mon, 26 Jul 2021 10:57:44 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=eI5TOmA8; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232324AbhGZRNu (ORCPT + 99 others); Mon, 26 Jul 2021 13:13:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49066 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231844AbhGZRNl (ORCPT ); Mon, 26 Jul 2021 13:13:41 -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 6872EC061760 for ; Mon, 26 Jul 2021 10:54:10 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id f9-20020a1709028609b0290128bcba6be7so9632838plo.18 for ; Mon, 26 Jul 2021 10:54:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=9UyZrt9F1H6UN7DWee5vqzeFLel0aRWyUB8vgzqX0Ms=; b=eI5TOmA8cwqdrXnJArhmXblYtZhE1vsNTjiaWeGN2b+tKFMKoCYQ+9CHHnw/VHWrfQ HxE03JlHXg8QtmW9QqJ52cfJlz8mWhjmkzbqePt7/EkGovaDwykeUdzXl1/BDmaYC64X FB15w3exP2vS5X7BDDbNXm02Y6zyNDp9RgpXjYb2ddH4UcZRYlF1Gy030e9h5Ia0dUMx /wpSC4RBVfPmCkjxAULrtg7OrC66/HUQTn8ZfZdaHNBSD6w1v0sJV/8in10KXCR+75Ni j+AnNPcJx12hAQ6f4ZpAcAPIe4DHqZOaI1D86ac23gAzjvQC4h1iQaqletdAvQbwyily 430Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=9UyZrt9F1H6UN7DWee5vqzeFLel0aRWyUB8vgzqX0Ms=; b=IzbrOKkTQGp+vmbxCLq8HxQ72RZeddMs2DzdmOPYPma8XQo+CDFigy8ynaK/dtA42d uy0MWnC2Rv9Qrk/mdUOBICNvp/wd/o81KszZ8hhcj6EHTUTDeWW8J4XL2tOme8GWBumQ W9cjmBkRHHPfuVP2X/3JWVbnzCWwbNaW4f3IhCDsjClGWopf6MUCMf9z2ieF5svDsYro ZoetOLvqSGmTkVCrO1a5M5f/lm8wEaG+8bMN/GoArPCM/OSyycNsqWPdZy3Ers4r7Sti 4F6vdwCi2JHZW8AIAr8zT+NSwe3f+KrolpAAt8895+wovz4LcxvnnXt0Tm8pEZ97ldu0 CcBA== X-Gm-Message-State: AOAM530Al1Ns1hl1xi11vm9SxVUGK2Y9mReUFetWy9ovNJXRbHwZWHU7 GoCy4Ib+7BdhUwYFDIBcZLS6SYEpO/Ak X-Received: from mihenry-linux-desktop.kir.corp.google.com ([2620:15c:29:204:93c5:105:4dbc:13cf]) (user=mizhang job=sendgmr) by 2002:a17:902:6509:b029:12b:5175:43b8 with SMTP id b9-20020a1709026509b029012b517543b8mr15461131plk.60.1627322049848; Mon, 26 Jul 2021 10:54:09 -0700 (PDT) Reply-To: Mingwei Zhang Date: Mon, 26 Jul 2021 10:53:57 -0700 In-Reply-To: <20210726175357.1572951-1-mizhang@google.com> Message-Id: <20210726175357.1572951-4-mizhang@google.com> Mime-Version: 1.0 References: <20210726175357.1572951-1-mizhang@google.com> X-Mailer: git-send-email 2.32.0.432.gabb21c7263-goog Subject: [PATCH v2 3/3] KVM: x86/mmu: Add detailed page size stats From: Mingwei Zhang To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Ben Gardon , Mingwei Zhang , Jing Zhang Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Existing KVM code tracks the number of large pages regardless of their sizes. Therefore, when large page of 1GB (or larger) is adopted, the information becomes less useful because lpages counts a mix of 1G and 2M pages. So remove the lpages since it is easy for user space to aggregate the info. Instead, provide a comprehensive page stats of all sizes from 4K to 512G. Suggested-by: Ben Gardon Suggested-by: Jing Zhang Signed-off-by: Mingwei Zhang --- arch/x86/include/asm/kvm_host.h | 10 +++++++++- arch/x86/kvm/mmu.h | 2 ++ arch/x86/kvm/mmu/mmu.c | 32 +++++++++++++++++++------------- arch/x86/kvm/mmu/tdp_mmu.c | 15 ++------------- arch/x86/kvm/x86.c | 7 +++++-- 5 files changed, 37 insertions(+), 29 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 974cbfb1eefe..2e4b6fd36e62 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1206,9 +1206,17 @@ struct kvm_vm_stat { u64 mmu_recycled; u64 mmu_cache_miss; u64 mmu_unsync; - u64 lpages; u64 nx_lpage_splits; u64 max_mmu_page_hash_collisions; + union { + struct { + atomic64_t pages_4k; + atomic64_t pages_2m; + atomic64_t pages_1g; + atomic64_t pages_512g; + }; + atomic64_t pages[4]; + } page_stats; }; struct kvm_vcpu_stat { diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 83e6c6965f1e..ad5638815311 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -240,4 +240,6 @@ static inline bool kvm_memslots_have_rmaps(struct kvm *kvm) return smp_load_acquire(&kvm->arch.memslots_have_rmaps); } +void kvm_update_page_stats(struct kvm *kvm, int level, int count); + #endif diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 442cc554ebd6..7e0fc760739b 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -588,16 +588,22 @@ static bool mmu_spte_update(u64 *sptep, u64 new_spte) return flush; } +void kvm_update_page_stats(struct kvm *kvm, int level, int count) +{ + atomic64_add(count, &kvm->stat.page_stats.pages[level - 1]); +} + /* * Rules for using mmu_spte_clear_track_bits: * It sets the sptep from present to nonpresent, and track the * state bits, it is used to clear the last level sptep. * Returns non-zero if the PTE was previously valid. */ -static int mmu_spte_clear_track_bits(u64 *sptep) +static int mmu_spte_clear_track_bits(struct kvm *kvm, u64 *sptep) { kvm_pfn_t pfn; u64 old_spte = *sptep; + int level = sptep_to_sp(sptep)->role.level; if (!spte_has_volatile_bits(old_spte)) __update_clear_spte_fast(sptep, 0ull); @@ -607,6 +613,9 @@ static int mmu_spte_clear_track_bits(u64 *sptep) if (!is_shadow_present_pte(old_spte)) return 0; + if (is_last_spte(old_spte, level)) + kvm_update_page_stats(kvm, level, -1); + pfn = spte_to_pfn(old_spte); /* @@ -984,9 +993,10 @@ static void __pte_list_remove(u64 *spte, struct kvm_rmap_head *rmap_head) } } -static void pte_list_remove(struct kvm_rmap_head *rmap_head, u64 *sptep) +static void pte_list_remove(struct kvm *kvm, struct kvm_rmap_head *rmap_head, + u64 *sptep) { - mmu_spte_clear_track_bits(sptep); + mmu_spte_clear_track_bits(kvm, sptep); __pte_list_remove(sptep, rmap_head); } @@ -1119,7 +1129,7 @@ static u64 *rmap_get_next(struct rmap_iterator *iter) static void drop_spte(struct kvm *kvm, u64 *sptep) { - if (mmu_spte_clear_track_bits(sptep)) + if (mmu_spte_clear_track_bits(kvm, sptep)) rmap_remove(kvm, sptep); } @@ -1129,7 +1139,6 @@ static bool __drop_large_spte(struct kvm *kvm, u64 *sptep) if (is_large_pte(*sptep)) { WARN_ON(sptep_to_sp(sptep)->role.level == PG_LEVEL_4K); drop_spte(kvm, sptep); - --kvm->stat.lpages; return true; } @@ -1386,7 +1395,7 @@ static bool kvm_zap_rmapp(struct kvm *kvm, struct kvm_rmap_head *rmap_head, while ((sptep = rmap_get_first(rmap_head, &iter))) { rmap_printk("spte %p %llx.\n", sptep, *sptep); - pte_list_remove(rmap_head, sptep); + pte_list_remove(kvm, rmap_head, sptep); flush = true; } @@ -1421,13 +1430,13 @@ static bool kvm_set_pte_rmapp(struct kvm *kvm, struct kvm_rmap_head *rmap_head, need_flush = 1; if (pte_write(pte)) { - pte_list_remove(rmap_head, sptep); + pte_list_remove(kvm, rmap_head, sptep); goto restart; } else { new_spte = kvm_mmu_changed_pte_notifier_make_spte( *sptep, new_pfn); - mmu_spte_clear_track_bits(sptep); + mmu_spte_clear_track_bits(kvm, sptep); mmu_spte_set(sptep, new_spte); } } @@ -2232,8 +2241,6 @@ static int mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp, if (is_shadow_present_pte(pte)) { if (is_last_spte(pte, sp->role.level)) { drop_spte(kvm, spte); - if (is_large_pte(pte)) - --kvm->stat.lpages; } else { child = to_shadow_page(pte & PT64_BASE_ADDR_MASK); drop_parent_pte(child, spte); @@ -2692,8 +2699,7 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, trace_kvm_mmu_set_spte(level, gfn, sptep); if (!was_rmapped) { - if (is_large_pte(*sptep)) - ++vcpu->kvm->stat.lpages; + kvm_update_page_stats(vcpu->kvm, level, 1); rmap_count = rmap_add(vcpu, sptep, gfn); if (rmap_count > RMAP_RECYCLE_THRESHOLD) rmap_recycle(vcpu, sptep, gfn); @@ -5669,7 +5675,7 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm, if (sp->role.direct && !kvm_is_reserved_pfn(pfn) && sp->role.level < kvm_mmu_max_mapping_level(kvm, slot, sp->gfn, pfn, PG_LEVEL_NUM)) { - pte_list_remove(rmap_head, sptep); + pte_list_remove(kvm, rmap_head, sptep); if (kvm_available_flush_tlb_with_range()) kvm_flush_remote_tlbs_with_address(kvm, sp->gfn, diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index cba2ab5db2a0..eae404c15364 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -413,7 +413,6 @@ static void __handle_changed_spte(struct kvm *kvm, int as_id, gfn_t gfn, bool was_leaf = was_present && is_last_spte(old_spte, level); bool is_leaf = is_present && is_last_spte(new_spte, level); bool pfn_changed = spte_to_pfn(old_spte) != spte_to_pfn(new_spte); - bool was_large, is_large; WARN_ON(level > PT64_ROOT_MAX_LEVEL); WARN_ON(level < PG_LEVEL_4K); @@ -472,18 +471,8 @@ static void __handle_changed_spte(struct kvm *kvm, int as_id, gfn_t gfn, return; } - /* - * Update large page stats if a large page is being zapped, created, or - * is replacing an existing shadow page. - */ - was_large = was_leaf && is_large_pte(old_spte); - is_large = is_leaf && is_large_pte(new_spte); - if (was_large != is_large) { - if (was_large) - atomic64_sub(1, (atomic64_t *)&kvm->stat.lpages); - else - atomic64_add(1, (atomic64_t *)&kvm->stat.lpages); - } + if (is_leaf != was_leaf) + kvm_update_page_stats(kvm, level, is_leaf ? 1 : -1); if (was_leaf && is_dirty_spte(old_spte) && (!is_present || !is_dirty_spte(new_spte) || pfn_changed)) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 8166ad113fb2..3858d36d3c49 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -235,9 +235,12 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = { STATS_DESC_COUNTER(VM, mmu_recycled), STATS_DESC_COUNTER(VM, mmu_cache_miss), STATS_DESC_ICOUNTER(VM, mmu_unsync), - STATS_DESC_ICOUNTER(VM, lpages), STATS_DESC_ICOUNTER(VM, nx_lpage_splits), - STATS_DESC_PCOUNTER(VM, max_mmu_page_hash_collisions) + STATS_DESC_PCOUNTER(VM, max_mmu_page_hash_collisions), + STATS_DESC_ICOUNTER(VM, page_stats.pages_4k), + STATS_DESC_ICOUNTER(VM, page_stats.pages_2m), + STATS_DESC_ICOUNTER(VM, page_stats.pages_1g), + STATS_DESC_ICOUNTER(VM, page_stats.pages_512g) }; static_assert(ARRAY_SIZE(kvm_vm_stats_desc) == sizeof(struct kvm_vm_stat) / sizeof(u64)); -- 2.32.0.432.gabb21c7263-goog