aboutsummaryrefslogtreecommitdiff
path: root/accel/kvm
diff options
context:
space:
mode:
authorGavin Shan <gshan@redhat.com>2023-05-09 12:21:22 +1000
committerPaolo Bonzini <pbonzini@redhat.com>2023-05-18 08:53:51 +0200
commit856e23a0fb92b0949eace7f43a521e0214246735 (patch)
tree22e110619c6faadf6c79500378cbff22325f4b47 /accel/kvm
parent3794cb9485ca52a65494c6eb108ff280a7e98dbc (diff)
kvm: Enable dirty ring for arm64
arm64 has different capability from x86 to enable the dirty ring, which is KVM_CAP_DIRTY_LOG_RING_ACQ_REL. Besides, arm64 also needs the backup bitmap extension (KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP) when 'kvm-arm-gicv3' or 'arm-its-kvm' device is enabled. Here the extension is always enabled and the unnecessary overhead to do the last stage of dirty log synchronization when those two devices aren't used is introduced, but the overhead should be very small and acceptable. The benefit is cover future cases where those two devices are used without modifying the code. Signed-off-by: Gavin Shan <gshan@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Tested-by: Zhenyu Zhang <zhenyzha@redhat.com> Reviewed-by: Peter Xu <peterx@redhat.com> Message-Id: <20230509022122.20888-5-gshan@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'accel/kvm')
-rw-r--r--accel/kvm/kvm-all.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 5d0de9d0a8..7679f397ae 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1466,6 +1466,7 @@ 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);
+ unsigned int capability = KVM_CAP_DIRTY_LOG_RING;
int ret;
s->kvm_dirty_ring_size = 0;
@@ -1480,7 +1481,12 @@ static int kvm_dirty_ring_init(KVMState *s)
* 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);
+ ret = kvm_vm_check_extension(s, capability);
+ if (ret <= 0) {
+ capability = KVM_CAP_DIRTY_LOG_RING_ACQ_REL;
+ ret = kvm_vm_check_extension(s, capability);
+ }
+
if (ret <= 0) {
warn_report("KVM dirty ring not available, using bitmap method");
return 0;
@@ -1493,13 +1499,26 @@ static int kvm_dirty_ring_init(KVMState *s)
return -EINVAL;
}
- ret = kvm_vm_enable_cap(s, KVM_CAP_DIRTY_LOG_RING, 0, ring_bytes);
+ ret = kvm_vm_enable_cap(s, capability, 0, ring_bytes);
if (ret) {
error_report("Enabling of KVM dirty ring failed: %s. "
"Suggested minimum value is 1024.", strerror(-ret));
return -EIO;
}
+ /* Enable the backup bitmap if it is supported */
+ ret = kvm_vm_check_extension(s, KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP);
+ if (ret > 0) {
+ ret = kvm_vm_enable_cap(s, KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP, 0);
+ if (ret) {
+ error_report("Enabling of KVM dirty ring's backup bitmap failed: "
+ "%s. ", strerror(-ret));
+ return -EIO;
+ }
+
+ s->kvm_dirty_ring_with_bitmap = true;
+ }
+
s->kvm_dirty_ring_size = ring_size;
s->kvm_dirty_ring_bytes = ring_bytes;