| Message ID | 20251103062825.9084-1-dayss1224@gmail.com |
|---|---|
| State | Accepted |
| Headers | show |
| Series | KVM: riscv: Support enabling dirty log gradually in small chunks | expand |
On Mon, Nov 3, 2025 at 11:58 AM <dayss1224@gmail.com> wrote: > > From: Dong Yang <dayss1224@gmail.com> > > There is already support of enabling dirty log gradually in small chunks > for x86 in commit 3c9bd4006bfc ("KVM: x86: enable dirty log gradually in > small chunks") and c862626 ("KVM: arm64: Support enabling dirty log > gradually in small chunks"). This adds support for riscv. > > x86 and arm64 writes protect both huge pages and normal pages now, so > riscv protect also protects both huge pages and normal pages. > > On a nested virtualization setup (RISC-V KVM running inside a QEMU VM > on an [Intel® Core™ i5-12500H] host), I did some tests with a 2G Linux > VM using different backing page sizes. The time taken for > memory_global_dirty_log_start in the L2 QEMU is listed below: > > Page Size Before After Optimization > 4K 4490.23ms 31.94ms > 2M 48.97ms 45.46ms > 1G 28.40ms 30.93ms > > Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn> > Signed-off-by: Dong Yang <dayss1224@gmail.com> LGTM. Reviewed-by: Anup Patel <anup@brainfault.org> Queued this patch for Linux-6.19 Thanks, Anup > --- > Documentation/virt/kvm/api.rst | 2 +- > arch/riscv/include/asm/kvm_host.h | 3 +++ > arch/riscv/kvm/mmu.c | 5 ++++- > 3 files changed, 8 insertions(+), 2 deletions(-) > > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst > index 57061fa29e6a..3b621c3ae67c 100644 > --- a/Documentation/virt/kvm/api.rst > +++ b/Documentation/virt/kvm/api.rst > @@ -8028,7 +8028,7 @@ will be initialized to 1 when created. This also improves performance because > dirty logging can be enabled gradually in small chunks on the first call > to KVM_CLEAR_DIRTY_LOG. KVM_DIRTY_LOG_INITIALLY_SET depends on > KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (it is also only available on > -x86 and arm64 for now). > +x86, arm64 and riscv for now). > > KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 was previously available under the name > KVM_CAP_MANUAL_DIRTY_LOG_PROTECT, but the implementation had bugs that make > diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h > index 4d794573e3db..848b63f87001 100644 > --- a/arch/riscv/include/asm/kvm_host.h > +++ b/arch/riscv/include/asm/kvm_host.h > @@ -59,6 +59,9 @@ > BIT(IRQ_VS_TIMER) | \ > BIT(IRQ_VS_EXT)) > > +#define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \ > + KVM_DIRTY_LOG_INITIALLY_SET) > + > struct kvm_vm_stat { > struct kvm_vm_stat_generic generic; > }; > diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c > index 525fb5a330c0..a194eee256d8 100644 > --- a/arch/riscv/kvm/mmu.c > +++ b/arch/riscv/kvm/mmu.c > @@ -161,8 +161,11 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, > * allocated dirty_bitmap[], dirty pages will be tracked while > * the memory slot is write protected. > */ > - if (change != KVM_MR_DELETE && new->flags & KVM_MEM_LOG_DIRTY_PAGES) > + if (change != KVM_MR_DELETE && new->flags & KVM_MEM_LOG_DIRTY_PAGES) { > + if (kvm_dirty_log_manual_protect_and_init_set(kvm)) > + return; > mmu_wp_memory_region(kvm, new->id); > + } > } > > int kvm_arch_prepare_memory_region(struct kvm *kvm, > -- > 2.34.1 >
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 57061fa29e6a..3b621c3ae67c 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -8028,7 +8028,7 @@ will be initialized to 1 when created. This also improves performance because dirty logging can be enabled gradually in small chunks on the first call to KVM_CLEAR_DIRTY_LOG. KVM_DIRTY_LOG_INITIALLY_SET depends on KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (it is also only available on -x86 and arm64 for now). +x86, arm64 and riscv for now). KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 was previously available under the name KVM_CAP_MANUAL_DIRTY_LOG_PROTECT, but the implementation had bugs that make diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h index 4d794573e3db..848b63f87001 100644 --- a/arch/riscv/include/asm/kvm_host.h +++ b/arch/riscv/include/asm/kvm_host.h @@ -59,6 +59,9 @@ BIT(IRQ_VS_TIMER) | \ BIT(IRQ_VS_EXT)) +#define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \ + KVM_DIRTY_LOG_INITIALLY_SET) + struct kvm_vm_stat { struct kvm_vm_stat_generic generic; }; diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c index 525fb5a330c0..a194eee256d8 100644 --- a/arch/riscv/kvm/mmu.c +++ b/arch/riscv/kvm/mmu.c @@ -161,8 +161,11 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, * allocated dirty_bitmap[], dirty pages will be tracked while * the memory slot is write protected. */ - if (change != KVM_MR_DELETE && new->flags & KVM_MEM_LOG_DIRTY_PAGES) + if (change != KVM_MR_DELETE && new->flags & KVM_MEM_LOG_DIRTY_PAGES) { + if (kvm_dirty_log_manual_protect_and_init_set(kvm)) + return; mmu_wp_memory_region(kvm, new->id); + } } int kvm_arch_prepare_memory_region(struct kvm *kvm,