Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: arm64: Enable ring-based dirty memory tracking

Enable ring-based dirty memory tracking on ARM64:

- Enable CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL.

- Enable CONFIG_NEED_KVM_DIRTY_RING_WITH_BITMAP.

- Set KVM_DIRTY_LOG_PAGE_OFFSET for the ring buffer's physical page
offset.

- Add ARM64 specific kvm_arch_allow_write_without_running_vcpu() to
keep the site of saving vgic/its tables out of the no-running-vcpu
radar.

Signed-off-by: Gavin Shan <gshan@redhat.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20221110104914.31280-5-gshan@redhat.com

authored by

Gavin Shan and committed by
Marc Zyngier
9cb1096f 86bdf3eb

+28 -1
+1 -1
Documentation/virt/kvm/api.rst
··· 7921 7921 8.29 KVM_CAP_DIRTY_LOG_RING/KVM_CAP_DIRTY_LOG_RING_ACQ_REL 7922 7922 ---------------------------------------------------------- 7923 7923 7924 - :Architectures: x86 7924 + :Architectures: x86, arm64 7925 7925 :Parameters: args[0] - size of the dirty log ring 7926 7926 7927 7927 KVM is capable of tracking dirty memory using ring buffers that are
+1
arch/arm64/include/uapi/asm/kvm.h
··· 43 43 #define __KVM_HAVE_VCPU_EVENTS 44 44 45 45 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 46 + #define KVM_DIRTY_LOG_PAGE_OFFSET 64 46 47 47 48 #define KVM_REG_SIZE(id) \ 48 49 (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
+2
arch/arm64/kvm/Kconfig
··· 32 32 select KVM_VFIO 33 33 select HAVE_KVM_EVENTFD 34 34 select HAVE_KVM_IRQFD 35 + select HAVE_KVM_DIRTY_RING_ACQ_REL 36 + select NEED_KVM_DIRTY_RING_WITH_BITMAP 35 37 select HAVE_KVM_MSI 36 38 select HAVE_KVM_IRQCHIP 37 39 select HAVE_KVM_IRQ_ROUTING
+3
arch/arm64/kvm/arm.c
··· 746 746 747 747 if (kvm_check_request(KVM_REQ_SUSPEND, vcpu)) 748 748 return kvm_vcpu_suspend(vcpu); 749 + 750 + if (kvm_dirty_ring_check_request(vcpu)) 751 + return 0; 749 752 } 750 753 751 754 return 1;
+20
arch/arm64/kvm/vgic/vgic-its.c
··· 2743 2743 static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr) 2744 2744 { 2745 2745 const struct vgic_its_abi *abi = vgic_its_get_abi(its); 2746 + struct vgic_dist *dist = &kvm->arch.vgic; 2746 2747 int ret = 0; 2747 2748 2748 2749 if (attr == KVM_DEV_ARM_VGIC_CTRL_INIT) /* Nothing to do */ ··· 2763 2762 vgic_its_reset(kvm, its); 2764 2763 break; 2765 2764 case KVM_DEV_ARM_ITS_SAVE_TABLES: 2765 + dist->save_its_tables_in_progress = true; 2766 2766 ret = abi->save_tables(its); 2767 + dist->save_its_tables_in_progress = false; 2767 2768 break; 2768 2769 case KVM_DEV_ARM_ITS_RESTORE_TABLES: 2769 2770 ret = abi->restore_tables(its); ··· 2776 2773 mutex_unlock(&its->its_lock); 2777 2774 mutex_unlock(&kvm->lock); 2778 2775 return ret; 2776 + } 2777 + 2778 + /* 2779 + * kvm_arch_allow_write_without_running_vcpu - allow writing guest memory 2780 + * without the running VCPU when dirty ring is enabled. 2781 + * 2782 + * The running VCPU is required to track dirty guest pages when dirty ring 2783 + * is enabled. Otherwise, the backup bitmap should be used to track the 2784 + * dirty guest pages. When vgic/its tables are being saved, the backup 2785 + * bitmap is used to track the dirty guest pages due to the missed running 2786 + * VCPU in the period. 2787 + */ 2788 + bool kvm_arch_allow_write_without_running_vcpu(struct kvm *kvm) 2789 + { 2790 + struct vgic_dist *dist = &kvm->arch.vgic; 2791 + 2792 + return dist->save_its_tables_in_progress; 2779 2793 } 2780 2794 2781 2795 static int vgic_its_set_attr(struct kvm_device *dev,
+1
include/kvm/arm_vgic.h
··· 263 263 struct vgic_io_device dist_iodev; 264 264 265 265 bool has_its; 266 + bool save_its_tables_in_progress; 266 267 267 268 /* 268 269 * Contains the attributes and gpa of the LPI configuration table.