accel/kvm: refactor dirty ring setup
Refactor setting up of dirty ring code in kvm_init() so that is can be reused in the future patchsets. Signed-off-by: Ani Sinha <anisinha@redhat.com> Link: https://lore.kernel.org/r/20240912061838.4501-1-anisinha@redhat.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
f9423e9f0a
commit
28ed7f9761
@ -2435,6 +2435,55 @@ static int find_kvm_machine_type(MachineState *ms)
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int kvm_setup_dirty_ring(KVMState *s)
|
||||||
|
{
|
||||||
|
uint64_t dirty_log_manual_caps;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable KVM dirty ring if supported, otherwise fall back to
|
||||||
|
* dirty logging mode
|
||||||
|
*/
|
||||||
|
ret = kvm_dirty_ring_init(s);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is not needed when dirty ring is
|
||||||
|
* enabled. More importantly, KVM_DIRTY_LOG_INITIALLY_SET will assume no
|
||||||
|
* page is wr-protected initially, which is against how kvm dirty ring is
|
||||||
|
* usage - kvm dirty ring requires all pages are wr-protected at the very
|
||||||
|
* beginning. Enabling this feature for dirty ring causes data corruption.
|
||||||
|
*
|
||||||
|
* TODO: Without KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 and kvm clear dirty log,
|
||||||
|
* we may expect a higher stall time when starting the migration. In the
|
||||||
|
* future we can enable KVM_CLEAR_DIRTY_LOG to work with dirty ring too:
|
||||||
|
* instead of clearing dirty bit, it can be a way to explicitly wr-protect
|
||||||
|
* guest pages.
|
||||||
|
*/
|
||||||
|
if (!s->kvm_dirty_ring_size) {
|
||||||
|
dirty_log_manual_caps =
|
||||||
|
kvm_check_extension(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
|
||||||
|
dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
|
||||||
|
KVM_DIRTY_LOG_INITIALLY_SET);
|
||||||
|
s->manual_dirty_log_protect = dirty_log_manual_caps;
|
||||||
|
if (dirty_log_manual_caps) {
|
||||||
|
ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0,
|
||||||
|
dirty_log_manual_caps);
|
||||||
|
if (ret) {
|
||||||
|
warn_report("Trying to enable capability %"PRIu64" of "
|
||||||
|
"KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 but failed. "
|
||||||
|
"Falling back to the legacy mode. ",
|
||||||
|
dirty_log_manual_caps);
|
||||||
|
s->manual_dirty_log_protect = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int kvm_init(MachineState *ms)
|
static int kvm_init(MachineState *ms)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||||
@ -2454,7 +2503,6 @@ static int kvm_init(MachineState *ms)
|
|||||||
const KVMCapabilityInfo *missing_cap;
|
const KVMCapabilityInfo *missing_cap;
|
||||||
int ret;
|
int ret;
|
||||||
int type;
|
int type;
|
||||||
uint64_t dirty_log_manual_caps;
|
|
||||||
|
|
||||||
qemu_mutex_init(&kml_slots_lock);
|
qemu_mutex_init(&kml_slots_lock);
|
||||||
|
|
||||||
@ -2566,47 +2614,11 @@ static int kvm_init(MachineState *ms)
|
|||||||
s->coalesced_pio = s->coalesced_mmio &&
|
s->coalesced_pio = s->coalesced_mmio &&
|
||||||
kvm_check_extension(s, KVM_CAP_COALESCED_PIO);
|
kvm_check_extension(s, KVM_CAP_COALESCED_PIO);
|
||||||
|
|
||||||
/*
|
ret = kvm_setup_dirty_ring(s);
|
||||||
* Enable KVM dirty ring if supported, otherwise fall back to
|
|
||||||
* dirty logging mode
|
|
||||||
*/
|
|
||||||
ret = kvm_dirty_ring_init(s);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is not needed when dirty ring is
|
|
||||||
* enabled. More importantly, KVM_DIRTY_LOG_INITIALLY_SET will assume no
|
|
||||||
* page is wr-protected initially, which is against how kvm dirty ring is
|
|
||||||
* usage - kvm dirty ring requires all pages are wr-protected at the very
|
|
||||||
* beginning. Enabling this feature for dirty ring causes data corruption.
|
|
||||||
*
|
|
||||||
* TODO: Without KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 and kvm clear dirty log,
|
|
||||||
* we may expect a higher stall time when starting the migration. In the
|
|
||||||
* future we can enable KVM_CLEAR_DIRTY_LOG to work with dirty ring too:
|
|
||||||
* instead of clearing dirty bit, it can be a way to explicitly wr-protect
|
|
||||||
* guest pages.
|
|
||||||
*/
|
|
||||||
if (!s->kvm_dirty_ring_size) {
|
|
||||||
dirty_log_manual_caps =
|
|
||||||
kvm_check_extension(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
|
|
||||||
dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
|
|
||||||
KVM_DIRTY_LOG_INITIALLY_SET);
|
|
||||||
s->manual_dirty_log_protect = dirty_log_manual_caps;
|
|
||||||
if (dirty_log_manual_caps) {
|
|
||||||
ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0,
|
|
||||||
dirty_log_manual_caps);
|
|
||||||
if (ret) {
|
|
||||||
warn_report("Trying to enable capability %"PRIu64" of "
|
|
||||||
"KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 but failed. "
|
|
||||||
"Falling back to the legacy mode. ",
|
|
||||||
dirty_log_manual_caps);
|
|
||||||
s->manual_dirty_log_protect = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef KVM_CAP_VCPU_EVENTS
|
#ifdef KVM_CAP_VCPU_EVENTS
|
||||||
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
|
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user