[PATCH v2 0/3] KVM: x86/mmu: Repurpose MMU shrinker into page cache shrinker

Vipin Sharma posted 3 patches 1 month, 3 weeks ago
arch/x86/include/asm/kvm_host.h               |   7 +-
arch/x86/kvm/mmu/mmu.c                        | 139 ++++-----
arch/x86/kvm/mmu/paging_tmpl.h                |  14 +-
include/linux/kvm_host.h                      |   1 +
tools/testing/selftests/kvm/Makefile          |   1 +
.../testing/selftests/kvm/include/test_util.h |   5 +
tools/testing/selftests/kvm/lib/test_util.c   |  51 ++++
.../selftests/kvm/x86_64/mmu_shrinker_test.c  | 269 ++++++++++++++++++
virt/kvm/kvm_main.c                           |   8 +-
9 files changed, 404 insertions(+), 91 deletions(-)
create mode 100644 tools/testing/selftests/kvm/x86_64/mmu_shrinker_test.c
[PATCH v2 0/3] KVM: x86/mmu: Repurpose MMU shrinker into page cache shrinker
Posted by Vipin Sharma 1 month, 3 weeks ago
This series is extracted out from the NUMA aware page table series[1].
MMU shrinker changes were in patches 1 to 9 in the old series.

This series is changing KVM MMU shrinker behaviour by emptying MMU page
caches which are used during page fault and MMU load operations. It also
incorporates feedback from the NUMA aware page table series[1] regarding
MMU shrinker.

KVM MMU shrinker has not been very effective in alleviating pain under
memory pressure. It frees up the pages actively being used which results
in VM degradation. VM will take fault and bring them again in page
tables. More discussions happened at [2]. Overall, consensus was to
reprupose it into the code which frees pages from KVM MMU page caches.

Recently [3], there was a discussion to disable shrinker for TDP MMU.
Revival of this series is result of that discussion.

There are two major differences from the old series.
1. There is no global accounting of cache pages. It is dynamically
   calculated in mmu_shrink_count(). This has two effects; i) counting will
   be inaccurate but code is much simpler, and ii) kvm_lock being used
   here, this should be fine as mmu_shrink_scan() also holds the lock
   for its operation.
2. Only empty mmu_shadow_page_cache and mmu_shadowed_info_cache. This
   version doesn't empty split_shadow_page_cache as it is used only
   during dirty logging operation and is one per VM unlike other two
   which are per vCPU. I am not fully convinced that adding it is needed
   as it will add the cost of adding one more mutex and synchronizing it
   in shrinker. Also, if a VM is being dirty tracked most likely it will
   be migrated (memory pressure might be the reason in the first place)
   so better to not hinder migration effort and let vCPUs free up their
   caches. If someone convinces me to add split cache as well then I can
   send a separate patch to add that as well.

[1] https://lore.kernel.org/kvm/20230306224127.1689967-1-vipinsh@google.com/
[2] https://lore.kernel.org/lkml/Y45dldZnI6OIf+a5@google.com/
[3] https://lore.kernel.org/kvm/20240819214014.GA2313467.vipinsh@google.com/#t

Note to maintainers: scripts/checkpatch.pl is complaining about few
things on selftest (patch 3). These are just false positives.

1. Prefer strscpy() over strcpy(). 
   This kernel API and not general libc userspace API.
2. Unnecessary whitespace before a quoted new line.
   Just the way help string is written for selftests to align output of
   help.
3. Prefer using '"%s...", __func__'
   Because I wrote "help" word in the printf().

v2:
- Add a new selftest, mmu_shrinker_test.

v1: https://lore.kernel.org/kvm/20240913214316.1945951-1-vipinsh@google.com/
- No global counting of pages in cache. As this number might not remain
  same between calls of mmu_shrink_count() and mmu_shrink_scan().
- Count cache pages in mmu_shrink_count(). KVM can tolerate inaccuracy
  here.
- Empty mmu_shadow_page_cache and mmu_shadowed_info_cache only. Don't
  empty split_shadow_page_cache.

v0: Patches 1-9 from NUMA aware page table series.
https://lore.kernel.org/kvm/20230306224127.1689967-1-vipinsh@google.com/

Vipin Sharma (3):
  KVM: x86/mmu: Change KVM mmu shrinker to no-op
  KVM: x86/mmu: Use MMU shrinker to shrink KVM MMU memory caches
  KVM: selftests: Add a test to invoke MMU shrinker on KVM VMs

 arch/x86/include/asm/kvm_host.h               |   7 +-
 arch/x86/kvm/mmu/mmu.c                        | 139 ++++-----
 arch/x86/kvm/mmu/paging_tmpl.h                |  14 +-
 include/linux/kvm_host.h                      |   1 +
 tools/testing/selftests/kvm/Makefile          |   1 +
 .../testing/selftests/kvm/include/test_util.h |   5 +
 tools/testing/selftests/kvm/lib/test_util.c   |  51 ++++
 .../selftests/kvm/x86_64/mmu_shrinker_test.c  | 269 ++++++++++++++++++
 virt/kvm/kvm_main.c                           |   8 +-
 9 files changed, 404 insertions(+), 91 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/x86_64/mmu_shrinker_test.c


base-commit: 12680d7b8ac4db2eba6237a21a93d2b0e78a52a6
-- 
2.47.0.rc0.187.ge670bccf7e-goog