mirror of https://github.com/xemu-project/xemu.git
kvm: Add helper kvm_dirty_ring_init()
Due to multiple capabilities associated with the dirty ring for different architectures: KVM_CAP_DIRTY_{LOG_RING, LOG_RING_ACQ_REL} for x86 and arm64 separately. There will be more to be done in order to support the dirty ring for arm64. Lets add helper kvm_dirty_ring_init() to enable the dirty ring. With this, the code looks a bit clean. No functional change intended. Signed-off-by: Gavin Shan <gshan@redhat.com> Reviewed-by: Peter Xu <peterx@redhat.com> Tested-by: Zhenyu Zhang <zhenyzha@redhat.com> Message-Id: <20230509022122.20888-4-gshan@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
b20cc77692
commit
3794cb9485
|
@ -1462,6 +1462,50 @@ static int kvm_dirty_ring_reaper_init(KVMState *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_dirty_ring_init(KVMState *s)
|
||||
{
|
||||
uint32_t ring_size = s->kvm_dirty_ring_size;
|
||||
uint64_t ring_bytes = ring_size * sizeof(struct kvm_dirty_gfn);
|
||||
int ret;
|
||||
|
||||
s->kvm_dirty_ring_size = 0;
|
||||
s->kvm_dirty_ring_bytes = 0;
|
||||
|
||||
/* Bail if the dirty ring size isn't specified */
|
||||
if (!ring_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the max supported pages. Fall back to dirty logging mode
|
||||
* if the dirty ring isn't supported.
|
||||
*/
|
||||
ret = kvm_vm_check_extension(s, KVM_CAP_DIRTY_LOG_RING);
|
||||
if (ret <= 0) {
|
||||
warn_report("KVM dirty ring not available, using bitmap method");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ring_bytes > ret) {
|
||||
error_report("KVM dirty ring size %" PRIu32 " too big "
|
||||
"(maximum is %ld). Please use a smaller value.",
|
||||
ring_size, (long)ret / sizeof(struct kvm_dirty_gfn));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = kvm_vm_enable_cap(s, KVM_CAP_DIRTY_LOG_RING, 0, ring_bytes);
|
||||
if (ret) {
|
||||
error_report("Enabling of KVM dirty ring failed: %s. "
|
||||
"Suggested minimum value is 1024.", strerror(-ret));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
s->kvm_dirty_ring_size = ring_size;
|
||||
s->kvm_dirty_ring_bytes = ring_bytes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kvm_region_add(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
|
@ -2531,35 +2575,9 @@ static int kvm_init(MachineState *ms)
|
|||
* Enable KVM dirty ring if supported, otherwise fall back to
|
||||
* dirty logging mode
|
||||
*/
|
||||
if (s->kvm_dirty_ring_size > 0) {
|
||||
uint64_t ring_bytes;
|
||||
|
||||
ring_bytes = s->kvm_dirty_ring_size * sizeof(struct kvm_dirty_gfn);
|
||||
|
||||
/* Read the max supported pages */
|
||||
ret = kvm_vm_check_extension(s, KVM_CAP_DIRTY_LOG_RING);
|
||||
if (ret > 0) {
|
||||
if (ring_bytes > ret) {
|
||||
error_report("KVM dirty ring size %" PRIu32 " too big "
|
||||
"(maximum is %ld). Please use a smaller value.",
|
||||
s->kvm_dirty_ring_size,
|
||||
(long)ret / sizeof(struct kvm_dirty_gfn));
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = kvm_vm_enable_cap(s, KVM_CAP_DIRTY_LOG_RING, 0, ring_bytes);
|
||||
if (ret) {
|
||||
error_report("Enabling of KVM dirty ring failed: %s. "
|
||||
"Suggested minimum value is 1024.", strerror(-ret));
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->kvm_dirty_ring_bytes = ring_bytes;
|
||||
} else {
|
||||
warn_report("KVM dirty ring not available, using bitmap method");
|
||||
s->kvm_dirty_ring_size = 0;
|
||||
}
|
||||
ret = kvm_dirty_ring_init(s);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue