Skip to content

KVM: Dirty ring interface

Peter Xu kvm lkml 16 versions – New

Get series with b4
b4 am [email protected]

Versions newest first · linked by author and title

  1. v15 Latest14 patches 0 repliesNew
  2. v1414 patches 0 repliesSuperseded
  3. v1314 patches 7 repliesApplied
Earlier versions · 13
VersionPostedPatchesRepliesStatus
v1213 patches2 repliesSuperseded
v1113 patches2 repliesSuperseded
v1014 patches10 repliesSuperseded
v914 patches4 repliesSuperseded
v814 patches15 repliesSuperseded
v714 patches13 repliesSuperseded
v614 patches15 repliesSuperseded
v514 patches6 repliesSuperseded
v414 patches10 repliesSuperseded
v321 patches58 repliesApplied
v2 posting 2/217 patches27 repliesSuperseded
v2 posting 1/217 patches3 repliesSuperseded
v1 RFC15 patches105 repliesSuperseded

Changes in v15 from the cover letter

- rebase to kvm tree tag kvm-5.10-1/for-upstream

Patches in v15 No applies recorded yet

#Subject and filesSizeRepliesApplied
1/14KVM: Documentation: Update entry for KVM_X86_SET_MSR_FILTERDocumentation/virt/kvm/api.rst+1 -10 replies
2/14KVM: Documentation: Update entry for KVM_CAP_ENFORCE_PV_CPUIDDocumentation/virt/kvm/api.rst+1 -20 replies
3/14KVM: X86: Don't track dirty for KVM_SET_[TSS_ADDR|IDENTITY_MAP_ADDR]arch/x86/include/asm/kvm_host.h arch/x86/kvm/svm/avic.c arch/x86/kvm/vmx/vmx.c +1 more+81 -560 replies
4/14KVM: Pass in kvm pointer into mark_page_dirty_in_slot()arch/x86/kvm/mmu/tdp_mmu.c include/linux/kvm_host.h virt/kvm/kvm_main.c+19 -150 replies
5/14KVM: X86: Implement ring-based dirty memory trackingDocumentation/virt/kvm/api.rst arch/x86/include/asm/kvm_host.h arch/x86/include/uapi/asm/kvm.h +10 more+688 -30 replies
6/14KVM: Make dirty ring exclusive to dirty bitmap logDocumentation/virt/kvm/api.rst virt/kvm/kvm_main.c+19 -00 replies
7/14KVM: Don't allocate dirty bitmap if dirty ring is enabledarch/x86/kvm/mmu/mmu.c include/linux/kvm_host.h virt/kvm/kvm_main.c+8 -30 replies
8/14KVM: selftests: Always clear dirty bitmap after iterationtools/testing/selftests/kvm/dirty_log_test.c+1 -10 replies
9/14KVM: selftests: Sync uapi/linux/kvm.h to tools/tools/include/uapi/linux/kvm.h+76 -20 replies
10/14KVM: selftests: Use a single binary for dirty/clear log testtools/testing/selftests/kvm/Makefile tools/testing/selftests/kvm/clear_dirty_log_test.c tools/testing/selftests/kvm/dirty_log_test.c+156 -390 replies
11/14KVM: selftests: Introduce after_vcpu_run hook for dirty log testtools/testing/selftests/kvm/dirty_log_test.c+24 -120 replies
12/14KVM: selftests: Add dirty ring buffer testtools/testing/selftests/kvm/dirty_log_test.c tools/testing/selftests/kvm/include/kvm_util.h tools/testing/selftests/kvm/lib/kvm_util.c +1 more+278 -40 replies
13/14KVM: selftests: Let dirty_log_test async for dirty ring testtools/testing/selftests/kvm/dirty_log_test.c tools/testing/selftests/kvm/include/kvm_util.h tools/testing/selftests/kvm/lib/kvm_util.c+106 -300 replies
14/14KVM: selftests: Add "-c" parameter to dirty log testtools/testing/selftests/kvm/dirty_log_test.c+10 -30 replies

Reviews trailers per patch

6 of 14 patches have a Reviewed-by or Acked-by.

PatchSean ChristophersonAndrew Jones
1/14
2/14
3/14R-b
4/14
5/14
6/14
7/14
8/14R-b
9/14
10/14R-b
11/14R-b
12/14
13/14R-b
14/14R-b

Trailers given in replies are filled; those carried in the patches from earlier versions are outlined with dashes.

Read the v15 thread

Cover letter [PATCH v15 00/14] KVM: Dirty ring interface

Paolo:

I'm rebasing again to the next merge window branch of kvm, assuming it's kvm-5.10-1/upstream tag. I don't know whether you'd like to merge it for this merge window. Just in case you still would like to, so you'll have something to pick up very easily based on the new tdp mmu changes.

I feel a bit sorry for disturbing reviewers on recent frequent repostings. It's just a way to try move this forward a bit since I still think it's a quite useful thing to have upstream for not yet another logging interface, but also a chance to improve auto-converge and maybe it could be useful to solve some huge vm issues. Anyway, I guess this is the last attempt if I won't get more review comments out of this series, and I'll hold until so.

In all cases, please consider to squash patch1/2 into corresponding patches in kvm-next because the numbers are wrong in current tree.

Thanks.

----------

KVM branch:
https://github.com/xzpeter/linux/tree/kvm-dirty-ring

QEMU branch for testing:
https://github.com/xzpeter/qemu/tree/kvm-dirty-ring

v15:
- rebase to kvm tree tag kvm-5.10-1/for-upstream

v14:
- fix a testcase race reported by kernel test robot. More can be found at:
https://lore.kernel.org/kvm/20201007204525.GF6026@xz-x1/

v13:
- rebase to kvm/queue rather than 5.9-rc7. I think, kvm/queue is broken. I can only test the dirty ring after I revert 3eb900173c71 ("KVM: x86: VMX:
Prevent MSR passthrough when MSR access is denied", 2020-09-28), otherwise the guest will hang on vcpu0 looping forever during boot Linux.
- added another trivial patch "KVM: Documentation: Update entry for KVM_X86_SET_MSR_FILTER". It should be squashed into 1a155254ff93 ("KVM: x86:
Introduce MSR filtering", 2020-09-28) directly.

v12:
- add r-bs for Sean
- rebase

v11:
- rebased to kvm/queue (seems the newest)
- removed kvm_dirty_ring_waitqueue() tracepoint since not used
- set memslot->as_id in kvm_delete_memslot() [Sean]
- let __copy_to_user() always return -EFAULT [Sean]
- rename 'r' in alloc_apic_access_page into 'hva' [Sean]

For previous versions, please refer to:

V1: https://lore.kernel.org/kvm/[email protected]
V2: https://lore.kernel.org/kvm/[email protected]
V3: https://lore.kernel.org/kvm/[email protected]
V4: https://lore.kernel.org/kvm/[email protected]
V5: https://lore.kernel.org/kvm/[email protected]
V6: https://lore.kernel.org/kvm/[email protected]
V7: https://lore.kernel.org/kvm/[email protected]
V8: https://lore.kernel.org/kvm/[email protected]
V9: https://lore.kernel.org/kvm/[email protected]
V10: https://lore.kernel.org/kvm/[email protected]/

Overview
============

This is a continued work from Lei Cao <[email protected]> and Paolo Bonzini on the KVM dirty ring interface.

The new dirty ring interface is another way to collect dirty pages for the virtual machines. It is different from the existing dirty logging interface in a few ways, majorly:

- Data format: The dirty data was in a ring format rather than a bitmap format, so dirty bits to sync for dirty logging does not depend on the size of guest memory any more, but speed of dirtying. Also, the dirty ring is per-vcpu, while the dirty bitmap is per-vm.

- Data copy: The sync of dirty pages does not need data copy any more, but instead the ring is shared between the userspace and kernel by page sharings (mmap() on vcpu fd)

- Interface: Instead of using the old KVM_GET_DIRTY_LOG, KVM_CLEAR_DIRTY_LOG interfaces, the new ring uses the new KVM_RESET_DIRTY_RINGS ioctl when we want to reset the collected dirty pages to protected mode again (works like KVM_CLEAR_DIRTY_LOG, but ring based). To collecting dirty bits, we only need to read the ring data, no ioctl is needed.

Ring Layout
===========

KVM dirty ring is per-vcpu. Each ring is an array of kvm_dirty_gfn defined as:

struct kvm_dirty_gfn {
        __u32 flags;
        __u32 slot; /* as_id | slot_id */
        __u64 offset;
};

Each GFN is a state machine itself. The state is embeded in the flags field, as defined in the uapi header:

/*
* KVM dirty GFN flags, defined as:
*

 * |---------------+---------------+--------------|
 * | bit 1 (reset) | bit 0 (dirty) | Status       |
 * |---------------+---------------+--------------|
 * |             0 |             0 | Invalid GFN  |
 * |             0 |             1 | Dirty GFN    |
 * |             1 |             X | GFN to reset |
 * |---------------+---------------+--------------|
 *
 * Lifecycle of a dirty GFN goes like:
 *
 *      dirtied         collected        reset
 * 00 -----------> 01 -------------> 1X -------+
 *  ^                                          |
 *  |                                          |
 *  +------------------------------------------+

*
* The userspace program is only responsible for the 01->1X state
* conversion (to collect dirty bits). Also, it must not skip any
* dirty bits so that dirty bits are always collected in sequence. */

Testing
=======

This series provided both the implementation of the KVM dirty ring and the test case. Also I've implemented the QEMU counterpart that can run with the new KVM, link can be found at the top of the cover letter. However that's still a very initial version which is prone to change and future optimizations.

I did some measurement with the new method with 24G guest running some dirty workload, I don't see any speedup so far, even in some heavy dirty load it'll be slower (e.g., when 800MB/s random dirty rate, kvm dirty ring takes average of ~73s to complete migration while dirty logging only needs average of ~55s). However that's understandable because 24G guest means only 1M dirty bitmap, that's still a suitable case for dirty logging. Meanwhile heavier workload means worst case for dirty ring.

More tests are welcomed if there's bigger host/guest, especially on COLO-like workload.

Please review, thanks.

Peter Xu (14):
KVM: Documentation: Update entry for KVM_X86_SET_MSR_FILTER
KVM: Documentation: Update entry for KVM_CAP_ENFORCE_PV_CPUID
KVM: X86: Don't track dirty for KVM_SET_[TSS_ADDR|IDENTITY_MAP_ADDR]
KVM: Pass in kvm pointer into mark_page_dirty_in_slot()
KVM: X86: Implement ring-based dirty memory tracking
KVM: Make dirty ring exclusive to dirty bitmap log
KVM: Don't allocate dirty bitmap if dirty ring is enabled
KVM: selftests: Always clear dirty bitmap after iteration
KVM: selftests: Sync uapi/linux/kvm.h to tools/
KVM: selftests: Use a single binary for dirty/clear log test
KVM: selftests: Introduce after_vcpu_run hook for dirty log test
KVM: selftests: Add dirty ring buffer test
KVM: selftests: Let dirty_log_test async for dirty ring test
KVM: selftests: Add "-c" parameter to dirty log test

 Documentation/virt/kvm/api.rst                | 129 ++++-
 arch/x86/include/asm/kvm_host.h               |   6 +-
 arch/x86/include/uapi/asm/kvm.h               |   1 +
 arch/x86/kvm/Makefile                         |   3 +-
 arch/x86/kvm/mmu/mmu.c                        |  10 +-
 arch/x86/kvm/mmu/tdp_mmu.c                    |   2 +-
 arch/x86/kvm/svm/avic.c                       |   9 +-
 arch/x86/kvm/vmx/vmx.c                        |  96 ++--
 arch/x86/kvm/x86.c                            |  46 +-
 include/linux/kvm_dirty_ring.h                | 103 ++++
 include/linux/kvm_host.h                      |  21 +-
 include/trace/events/kvm.h                    |  63 +++
 include/uapi/linux/kvm.h                      |  53 ++
 tools/include/uapi/linux/kvm.h                |  78 ++-
 tools/testing/selftests/kvm/Makefile          |   2 -
 .../selftests/kvm/clear_dirty_log_test.c      |   6 -
 tools/testing/selftests/kvm/dirty_log_test.c  | 516 ++++++++++++++++--
 .../testing/selftests/kvm/include/kvm_util.h  |   4 +
 tools/testing/selftests/kvm/lib/kvm_util.c    |  72 ++-
 .../selftests/kvm/lib/kvm_util_internal.h     |   4 +
 virt/kvm/dirty_ring.c                         | 197 +++++++
 virt/kvm/kvm_main.c                           | 158 +++++-
 22 files changed, 1438 insertions(+), 141 deletions(-)
 create mode 100644 include/linux/kvm_dirty_ring.h
 delete mode 100644 tools/testing/selftests/kvm/clear_dirty_log_test.c
 create mode 100644 virt/kvm/dirty_ring.c
Signature · 1 line
2.26.2