mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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
			
			
This commit is contained in:
		
							parent
							
								
									86bdf3ebcf
								
							
						
					
					
						commit
						9cb1096f85
					
				
					 6 changed files with 28 additions and 1 deletions
				
			
		| 
						 | 
					@ -7921,7 +7921,7 @@ regardless of what has actually been exposed through the CPUID leaf.
 | 
				
			||||||
8.29 KVM_CAP_DIRTY_LOG_RING/KVM_CAP_DIRTY_LOG_RING_ACQ_REL
 | 
					8.29 KVM_CAP_DIRTY_LOG_RING/KVM_CAP_DIRTY_LOG_RING_ACQ_REL
 | 
				
			||||||
----------------------------------------------------------
 | 
					----------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:Architectures: x86
 | 
					:Architectures: x86, arm64
 | 
				
			||||||
:Parameters: args[0] - size of the dirty log ring
 | 
					:Parameters: args[0] - size of the dirty log ring
 | 
				
			||||||
 | 
					
 | 
				
			||||||
KVM is capable of tracking dirty memory using ring buffers that are
 | 
					KVM is capable of tracking dirty memory using ring buffers that are
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,7 @@
 | 
				
			||||||
#define __KVM_HAVE_VCPU_EVENTS
 | 
					#define __KVM_HAVE_VCPU_EVENTS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 | 
					#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 | 
				
			||||||
 | 
					#define KVM_DIRTY_LOG_PAGE_OFFSET 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define KVM_REG_SIZE(id)						\
 | 
					#define KVM_REG_SIZE(id)						\
 | 
				
			||||||
	(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
 | 
						(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,8 @@ menuconfig KVM
 | 
				
			||||||
	select KVM_VFIO
 | 
						select KVM_VFIO
 | 
				
			||||||
	select HAVE_KVM_EVENTFD
 | 
						select HAVE_KVM_EVENTFD
 | 
				
			||||||
	select HAVE_KVM_IRQFD
 | 
						select HAVE_KVM_IRQFD
 | 
				
			||||||
 | 
						select HAVE_KVM_DIRTY_RING_ACQ_REL
 | 
				
			||||||
 | 
						select NEED_KVM_DIRTY_RING_WITH_BITMAP
 | 
				
			||||||
	select HAVE_KVM_MSI
 | 
						select HAVE_KVM_MSI
 | 
				
			||||||
	select HAVE_KVM_IRQCHIP
 | 
						select HAVE_KVM_IRQCHIP
 | 
				
			||||||
	select HAVE_KVM_IRQ_ROUTING
 | 
						select HAVE_KVM_IRQ_ROUTING
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -746,6 +746,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
 | 
							if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
 | 
				
			||||||
			return kvm_vcpu_suspend(vcpu);
 | 
								return kvm_vcpu_suspend(vcpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (kvm_dirty_ring_check_request(vcpu))
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2743,6 +2743,7 @@ static int vgic_its_has_attr(struct kvm_device *dev,
 | 
				
			||||||
static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr)
 | 
					static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct vgic_its_abi *abi = vgic_its_get_abi(its);
 | 
						const struct vgic_its_abi *abi = vgic_its_get_abi(its);
 | 
				
			||||||
 | 
						struct vgic_dist *dist = &kvm->arch.vgic;
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (attr == KVM_DEV_ARM_VGIC_CTRL_INIT) /* Nothing to do */
 | 
						if (attr == KVM_DEV_ARM_VGIC_CTRL_INIT) /* Nothing to do */
 | 
				
			||||||
| 
						 | 
					@ -2762,7 +2763,9 @@ static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr)
 | 
				
			||||||
		vgic_its_reset(kvm, its);
 | 
							vgic_its_reset(kvm, its);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case KVM_DEV_ARM_ITS_SAVE_TABLES:
 | 
						case KVM_DEV_ARM_ITS_SAVE_TABLES:
 | 
				
			||||||
 | 
							dist->save_its_tables_in_progress = true;
 | 
				
			||||||
		ret = abi->save_tables(its);
 | 
							ret = abi->save_tables(its);
 | 
				
			||||||
 | 
							dist->save_its_tables_in_progress = false;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case KVM_DEV_ARM_ITS_RESTORE_TABLES:
 | 
						case KVM_DEV_ARM_ITS_RESTORE_TABLES:
 | 
				
			||||||
		ret = abi->restore_tables(its);
 | 
							ret = abi->restore_tables(its);
 | 
				
			||||||
| 
						 | 
					@ -2775,6 +2778,23 @@ static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr)
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * kvm_arch_allow_write_without_running_vcpu - allow writing guest memory
 | 
				
			||||||
 | 
					 * without the running VCPU when dirty ring is enabled.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The running VCPU is required to track dirty guest pages when dirty ring
 | 
				
			||||||
 | 
					 * is enabled. Otherwise, the backup bitmap should be used to track the
 | 
				
			||||||
 | 
					 * dirty guest pages. When vgic/its tables are being saved, the backup
 | 
				
			||||||
 | 
					 * bitmap is used to track the dirty guest pages due to the missed running
 | 
				
			||||||
 | 
					 * VCPU in the period.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool kvm_arch_allow_write_without_running_vcpu(struct kvm *kvm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct vgic_dist *dist = &kvm->arch.vgic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return dist->save_its_tables_in_progress;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int vgic_its_set_attr(struct kvm_device *dev,
 | 
					static int vgic_its_set_attr(struct kvm_device *dev,
 | 
				
			||||||
			     struct kvm_device_attr *attr)
 | 
								     struct kvm_device_attr *attr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -263,6 +263,7 @@ struct vgic_dist {
 | 
				
			||||||
	struct vgic_io_device	dist_iodev;
 | 
						struct vgic_io_device	dist_iodev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool			has_its;
 | 
						bool			has_its;
 | 
				
			||||||
 | 
						bool			save_its_tables_in_progress;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Contains the attributes and gpa of the LPI configuration table.
 | 
						 * Contains the attributes and gpa of the LPI configuration table.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue