From: Quan Zhou <zhouquan@iscas.ac.cn>
Enable ring-based dirty memory tracking on riscv:
- Enable CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL as riscv is weakly
ordered.
- Set KVM_DIRTY_LOG_PAGE_OFFSET for the ring buffer's physical page
offset.
- Add a check to kvm_vcpu_kvm_riscv_check_vcpu_requests for checking
whether the dirty ring is soft full.
To handle vCPU requests that cause exits to userspace, modified the
`kvm_riscv_check_vcpu_requests` to return a value (currently only
returns 0 or 1).
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
---
Documentation/virt/kvm/api.rst | 2 +-
arch/riscv/include/uapi/asm/kvm.h | 1 +
arch/riscv/kvm/Kconfig | 1 +
arch/riscv/kvm/vcpu.c | 18 ++++++++++++++++--
4 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 1bd2d42e6424..5de0fbfe2fc0 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -8316,7 +8316,7 @@ core crystal clock frequency, if a non-zero CPUID 0x15 is exposed to the guest.
7.36 KVM_CAP_DIRTY_LOG_RING/KVM_CAP_DIRTY_LOG_RING_ACQ_REL
----------------------------------------------------------
-:Architectures: x86, arm64
+:Architectures: x86, arm64, riscv
:Type: vm
:Parameters: args[0] - size of the dirty log ring
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index 5f59fd226cc5..ef27d4289da1 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -18,6 +18,7 @@
#define __KVM_HAVE_IRQ_LINE
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#define KVM_DIRTY_LOG_PAGE_OFFSET 64
#define KVM_INTERRUPT_SET -1U
#define KVM_INTERRUPT_UNSET -2U
diff --git a/arch/riscv/kvm/Kconfig b/arch/riscv/kvm/Kconfig
index 704c2899197e..5a62091b0809 100644
--- a/arch/riscv/kvm/Kconfig
+++ b/arch/riscv/kvm/Kconfig
@@ -25,6 +25,7 @@ config KVM
select HAVE_KVM_MSI
select HAVE_KVM_VCPU_ASYNC_IOCTL
select HAVE_KVM_READONLY_MEM
+ select HAVE_KVM_DIRTY_RING_ACQ_REL
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_GENERIC_HARDWARE_ENABLING
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index e0a01af426ff..0502125efb30 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -690,7 +690,14 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
}
}
-static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu)
+/**
+ * check_vcpu_requests - check and handle pending vCPU requests
+ * @vcpu: the VCPU pointer
+ *
+ * Return: 1 if we should enter the guest
+ * 0 if we should exit to userspace
+ */
+static int kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu)
{
struct rcuwait *wait = kvm_arch_vcpu_get_wait(vcpu);
@@ -735,7 +742,12 @@ static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu)
if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu))
kvm_riscv_vcpu_record_steal_time(vcpu);
+
+ if (kvm_dirty_ring_check_request(vcpu))
+ return 0;
}
+
+ return 1;
}
static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu)
@@ -917,7 +929,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
kvm_riscv_gstage_vmid_update(vcpu);
- kvm_riscv_check_vcpu_requests(vcpu);
+ ret = kvm_riscv_check_vcpu_requests(vcpu);
+ if (ret <= 0)
+ continue;
preempt_disable();
--
2.34.1
On Fri, Jun 13, 2025 at 5:08 PM <zhouquan@iscas.ac.cn> wrote: > > From: Quan Zhou <zhouquan@iscas.ac.cn> > > Enable ring-based dirty memory tracking on riscv: > > - Enable CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL as riscv is weakly > ordered. > - Set KVM_DIRTY_LOG_PAGE_OFFSET for the ring buffer's physical page > offset. > - Add a check to kvm_vcpu_kvm_riscv_check_vcpu_requests for checking > whether the dirty ring is soft full. > > To handle vCPU requests that cause exits to userspace, modified the > `kvm_riscv_check_vcpu_requests` to return a value (currently only > returns 0 or 1). > > Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn> LGTM. Reviewed-by: Anup Patel <anup@brainfault.org> Queued this patch for Linux-6.17 Thanks, Anup > --- > Documentation/virt/kvm/api.rst | 2 +- > arch/riscv/include/uapi/asm/kvm.h | 1 + > arch/riscv/kvm/Kconfig | 1 + > arch/riscv/kvm/vcpu.c | 18 ++++++++++++++++-- > 4 files changed, 19 insertions(+), 3 deletions(-) > > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst > index 1bd2d42e6424..5de0fbfe2fc0 100644 > --- a/Documentation/virt/kvm/api.rst > +++ b/Documentation/virt/kvm/api.rst > @@ -8316,7 +8316,7 @@ core crystal clock frequency, if a non-zero CPUID 0x15 is exposed to the guest. > 7.36 KVM_CAP_DIRTY_LOG_RING/KVM_CAP_DIRTY_LOG_RING_ACQ_REL > ---------------------------------------------------------- > > -:Architectures: x86, arm64 > +:Architectures: x86, arm64, riscv > :Type: vm > :Parameters: args[0] - size of the dirty log ring > > diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h > index 5f59fd226cc5..ef27d4289da1 100644 > --- a/arch/riscv/include/uapi/asm/kvm.h > +++ b/arch/riscv/include/uapi/asm/kvm.h > @@ -18,6 +18,7 @@ > #define __KVM_HAVE_IRQ_LINE > > #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 > +#define KVM_DIRTY_LOG_PAGE_OFFSET 64 > > #define KVM_INTERRUPT_SET -1U > #define KVM_INTERRUPT_UNSET -2U > diff --git a/arch/riscv/kvm/Kconfig b/arch/riscv/kvm/Kconfig > index 704c2899197e..5a62091b0809 100644 > --- a/arch/riscv/kvm/Kconfig > +++ b/arch/riscv/kvm/Kconfig > @@ -25,6 +25,7 @@ config KVM > select HAVE_KVM_MSI > select HAVE_KVM_VCPU_ASYNC_IOCTL > select HAVE_KVM_READONLY_MEM > + select HAVE_KVM_DIRTY_RING_ACQ_REL > select KVM_COMMON > select KVM_GENERIC_DIRTYLOG_READ_PROTECT > select KVM_GENERIC_HARDWARE_ENABLING > diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c > index e0a01af426ff..0502125efb30 100644 > --- a/arch/riscv/kvm/vcpu.c > +++ b/arch/riscv/kvm/vcpu.c > @@ -690,7 +690,14 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) > } > } > > -static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu) > +/** > + * check_vcpu_requests - check and handle pending vCPU requests > + * @vcpu: the VCPU pointer > + * > + * Return: 1 if we should enter the guest > + * 0 if we should exit to userspace > + */ > +static int kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu) > { > struct rcuwait *wait = kvm_arch_vcpu_get_wait(vcpu); > > @@ -735,7 +742,12 @@ static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu) > > if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu)) > kvm_riscv_vcpu_record_steal_time(vcpu); > + > + if (kvm_dirty_ring_check_request(vcpu)) > + return 0; > } > + > + return 1; > } > > static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu) > @@ -917,7 +929,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) > > kvm_riscv_gstage_vmid_update(vcpu); > > - kvm_riscv_check_vcpu_requests(vcpu); > + ret = kvm_riscv_check_vcpu_requests(vcpu); > + if (ret <= 0) > + continue; > > preempt_disable(); > > -- > 2.34.1 >
© 2016 - 2025 Red Hat, Inc.