mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 15:41:36 +00: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
@ -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 New Issue
Block a user