From: Leonardo Bras <leo.bras@arm.com>
To: Tian Zheng <zhengtian10@huawei.com>
Cc: Leonardo Bras <leo.bras@arm.com>,
maz@kernel.org, oupton@kernel.org, catalin.marinas@arm.com,
will@kernel.org, corbet@lwn.net, pbonzini@redhat.com,
yuzenghui@huawei.com, wangzhou1@hisilicon.com,
yangjinqian1@huawei.com, caijian11@h-partners.com,
liuyonglong@huawei.com, tangchengchang@huawei.com,
yezhenyu2@huawei.com, yubihong@huawei.com, linuxarm@huawei.com,
joey.gouly@arm.com, kvmarm@lists.linux.dev, kvm@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, seiden@linux.ibm.com,
suzuki.poulose@arm.com, fuad.tabba@linux.dev,
mark.rutland@arm.com, seanjc@google.com, rdunlap@infradead.org,
linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org,
skhan@linuxfoundation.org
Subject: Re: [PATCH v5 08/15] KVM: arm64: Flush the HDBSS buffer on VM exit
Date: Tue, 27 Oct 2026 18:13:35 +0000 [thread overview]
Message-ID: <auDpyRNpeDNzIk3W@LeoBrasDK> (raw)
In-Reply-To: <20260929103655.85107-9-zhengtian10@huawei.com>
On Tue, Sep 29, 2026 at 06:36:48PM +0800, Tian Zheng wrote:
> From: Eillon <yezhenyu2@huawei.com>
>
> HDBSS entries accumulate in the per-vCPU buffer while the guest runs,
> and must be drained into the dirty bitmap or dirty ring before
> userspace can observe them.
>
> Drain the buffer at a single point: kvm_arch_vcpu_ioctl_run() flushes
> it on every VM exit, before the exit reason is handled. Flushing
> inside the run loop keeps the dirty-ring feedback timely: when a flush
> pushes the ring past its soft limit, kvm_dirty_ring_push() raises
> KVM_REQ_DIRTY_RING_SOFT_FULL, which check_vcpu_requests() observes at
> the top of the next loop iteration, so the vCPU exits to userspace for
> the harvest before re-entering the guest.
>
> kvm_arch_sync_dirty_log() relies on the exit path to flush: it kicks
> vCPUs out of guest mode, and the GET/CLEAR protocol tolerates
> concurrent bitmap writes, so the snapshot is complete without extra
> synchronization.
>
> Signed-off-by: Eillon <yezhenyu2@huawei.com>
> Signed-off-by: Tian Zheng <zhengtian10@huawei.com>
> ---
> arch/arm64/include/asm/kvm_dirty_bit.h | 15 +++++++++
> arch/arm64/kvm/arm.c | 20 ++++++++++++
> arch/arm64/kvm/dirty_bit.c | 45 ++++++++++++++++++++++++++
> 3 files changed, 80 insertions(+)
>
> diff --git a/arch/arm64/include/asm/kvm_dirty_bit.h b/arch/arm64/include/asm/kvm_dirty_bit.h
> index fe703f02626b..d828e6b43fe9 100644
> --- a/arch/arm64/include/asm/kvm_dirty_bit.h
> +++ b/arch/arm64/include/asm/kvm_dirty_bit.h
> @@ -13,6 +13,9 @@
> #include <asm/sysreg.h>
> #include <linux/sizes.h>
>
> +#define HDBSS_ENTRY_VALID BIT(0)
> +#define HDBSS_ENTRY_IPA GENMASK_ULL(55, 12)
> +
> #define KVM_ARM_HDBSS_DEFAULT_SIZE PAGE_SIZE
> #define KVM_ARM_HDBSS_MAX_SIZE SZ_2M
>
> @@ -22,7 +25,19 @@ static inline u32 kvm_hdbss_buffer_size(struct kvm *kvm)
> return kvm->arch.hdbss_buffer_size ?: KVM_ARM_HDBSS_DEFAULT_SIZE;
> }
>
> +static inline bool kvm_hdbss_enabled(struct kvm *kvm)
> +{
> + return kvm->arch.mmu.vtcr & VTCR_EL2_HDBSS;
> +}
> +
> +static inline bool vcpu_hdbss_enabled(struct kvm_vcpu *vcpu)
> +{
> + return vcpu->arch.hw_mmu &&
> + (vcpu->arch.hw_mmu->vtcr & VTCR_EL2_HDBSS);
> +}
> +
IIUC, arch.mmu is always the canonical s2_mmu, while hw_mmu can be the
nested s2_mmu, if enabled.
Was that your intend here?
If not, we could use only kvm* version, which can be called with vcpu->kvm.
If it was, then I would like to understand the logic here, as IIUC the
buffer is accessible only for the non-nested guest, as it's
allocated in a per-vcpu structure. (vcpu->arch)
> int kvm_arm_vcpu_alloc_hdbss(struct kvm_vcpu *vcpu);
> void kvm_arm_vcpu_free_hdbss(struct kvm_vcpu *vcpu);
> +void kvm_flush_hdbss_buffer(struct kvm_vcpu *vcpu);
>
> #endif /* __ARM64_KVM_DIRTY_BIT_H__ */
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 5ea4ac26995e..9d7bdece149a 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -1430,6 +1430,14 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
>
> trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu));
>
> + /*
> + * Drain the HDBSS buffer before the exit is handled, so
> + * entries pushed to the dirty ring are accounted for by
> + * dirty_ring_check_request() on the next iteration.
> + */
> + if (vcpu_hdbss_enabled(vcpu))
> + kvm_flush_hdbss_buffer(vcpu);
> +
> /* Exit types that need handling before we can be preempted */
> handle_exit_early(vcpu, ret);
>
looks the correct place, haven't looked too much on that, though.
> @@ -2017,7 +2025,19 @@ long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,
>
> void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
> {
> + unsigned long i;
> + struct kvm_vcpu *vcpu;
>
> + if (!kvm_hdbss_enabled(kvm))
> + return;
> +
> + /*
> + * The buffer is drained on every VM exit, so kicking running
> + * vCPUs is enough to flush them; the dirty-log GET/CLEAR
> + * protocol tolerates bits set concurrently with the snapshot.
> + */
> + kvm_for_each_vcpu(i, vcpu, kvm)
> + kvm_vcpu_kick(vcpu);
> }
>
> static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
> diff --git a/arch/arm64/kvm/dirty_bit.c b/arch/arm64/kvm/dirty_bit.c
> index f9aeb9f34ad0..be0d12555c84 100644
> --- a/arch/arm64/kvm/dirty_bit.c
> +++ b/arch/arm64/kvm/dirty_bit.c
> @@ -13,6 +13,7 @@
> #include <linux/kconfig.h>
> #include <linux/log2.h>
> #include <linux/mm.h>
> +#include <linux/srcu.h>
>
Out of curiosity, could you please explain you reasoning on selecting srcu
as locking here?
(Like, what are you protecting against, and why srcu is a good choice)
> int kvm_arm_vcpu_alloc_hdbss(struct kvm_vcpu *vcpu)
> {
> @@ -53,3 +54,47 @@ void kvm_arm_vcpu_free_hdbss(struct kvm_vcpu *vcpu)
> vcpu->arch.hdbss.hdbss_pg = NULL;
> vcpu->arch.hdbss.hdbssbr_el2 = 0;
> }
> +
> +void kvm_flush_hdbss_buffer(struct kvm_vcpu *vcpu)
> +{
> + int idx, curr_idx;
> + u64 prod;
> + u32 entries;
> + u64 *hdbss_buf;
> + struct kvm *kvm = vcpu->kvm;
> + int srcu_idx;
> +
> + if (!vcpu_hdbss_enabled(vcpu))
> + return;
You test this before calling, is it really necessary to test it again, just
after calling?
> +
> + prod = read_sysreg_s(SYS_HDBSSPROD_EL2);
> + curr_idx = HDBSSPROD_IDX(prod);
> +
> + if (curr_idx == 0 || !vcpu->arch.hdbss.hdbss_pg)
> + return;
> +
> + hdbss_buf = page_address(vcpu->arch.hdbss.hdbss_pg);
> + if (!hdbss_buf)
> + return;
> +
> + entries = kvm_hdbss_buffer_size(kvm) / sizeof(u64);
> +
> + /* kvm_vcpu_mark_page_dirty() resolves the memslot under SRCU. */
> + srcu_idx = srcu_read_lock(&kvm->srcu);
> + for (idx = 0; idx < min_t(u32, curr_idx, entries); idx++) {
> + u64 gpa;
> +
> + gpa = hdbss_buf[idx];
> + if (!(gpa & HDBSS_ENTRY_VALID))
> + continue;
> +
> + gpa &= HDBSS_ENTRY_IPA;
> + kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
> + }
> + srcu_read_unlock(&kvm->srcu, srcu_idx);
> +
> + prod &= ~HDBSSPROD_EL2_INDEX_MASK;
> + write_sysreg_s(prod, SYS_HDBSSPROD_EL2);
> + vcpu->arch.hdbss.hdbssprod_el2 = prod;
> + isb();
> +}
> --
> 2.43.0
>
Thanks!
Leo
next prev parent reply other threads:[~2026-10-27 18:13 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 10:36 [PATCH v5 00/15] KVM: arm64: FEAT_HDBSS support for stage-2 dirty tracking Tian Zheng
2026-09-29 10:36 ` [PATCH v5 01/15] KVM: arm64: pgtables: Change write bit from S2AP_W to DBM Tian Zheng
2026-09-30 0:25 ` Oliver Upton
2026-09-30 2:44 ` Tian Zheng
2026-10-26 15:02 ` Leonardo Bras
2026-10-29 7:08 ` Tian Zheng
2026-09-29 10:36 ` [PATCH v5 02/15] KVM: arm64: Add KVM_PGTABLE_PROT_DIRTY Tian Zheng
2026-09-30 0:35 ` Oliver Upton
2026-09-30 2:57 ` Tian Zheng
2026-09-29 10:36 ` [PATCH v5 03/15] KVM: arm64: Introduce a dedicated walker for stage2 write-protect Tian Zheng
2026-09-29 10:36 ` [PATCH v5 04/15] KVM: arm64: Add KVM_REQ_RELOAD_STAGE2 Tian Zheng
2026-09-29 10:50 ` sashiko-bot
2026-09-30 1:44 ` Tian Zheng
2026-09-29 10:36 ` [PATCH v5 05/15] KVM: arm64: Harvest stage-2 dirty state into the host folio account Tian Zheng
2026-10-26 18:05 ` Leonardo Bras
2026-10-29 14:02 ` Tian Zheng
2026-09-29 10:36 ` [PATCH v5 06/15] KVM: arm64: Add support for FEAT_HDBSS Tian Zheng
2026-10-26 18:12 ` Leonardo Bras
2026-09-29 10:36 ` [PATCH v5 07/15] KVM: arm64: Add HDBSS per-vCPU buffer management Tian Zheng
2026-10-26 18:27 ` Leonardo Bras
2026-09-29 10:36 ` [PATCH v5 08/15] KVM: arm64: Flush the HDBSS buffer on VM exit Tian Zheng
2026-10-27 18:13 ` Leonardo Bras [this message]
2026-09-29 10:36 ` [PATCH v5 09/15] KVM: arm64: Handle HDBSS faults Tian Zheng
2026-09-29 10:53 ` sashiko-bot
2026-09-29 10:36 ` [PATCH v5 10/15] KVM: Add kvm_arch_dirty_ring_size_updated() hook Tian Zheng
2026-09-29 10:52 ` sashiko-bot
2026-09-29 10:36 ` [PATCH v5 11/15] KVM: arm64: Reserve dirty ring space for the HDBSS buffer Tian Zheng
2026-09-29 11:00 ` sashiko-bot
2026-09-29 10:36 ` [PATCH v5 12/15] KVM: arm64: Derive the VM hardware dirty mode from dirty logging Tian Zheng
2026-09-29 11:16 ` sashiko-bot
2026-09-30 8:27 ` Tian Zheng
2026-09-29 10:36 ` [PATCH v5 13/15] KVM: arm64: Add HDBSS buffer size ioctl for dirty-bitmap mode Tian Zheng
2026-09-29 10:36 ` [PATCH v5 14/15] KVM: arm64: Document HDBSS buffer size ioctl Tian Zheng
2026-09-29 11:06 ` sashiko-bot
2026-09-29 10:36 ` [PATCH v5 15/15] KVM: arm64: selftests: Add HDBSS buffer size ioctl interface test Tian Zheng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=auDpyRNpeDNzIk3W@LeoBrasDK \
--to=leo.bras@arm.com \
--cc=caijian11@h-partners.com \
--cc=catalin.marinas@arm.com \
--cc=corbet@lwn.net \
--cc=fuad.tabba@linux.dev \
--cc=joey.gouly@arm.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linuxarm@huawei.com \
--cc=liuyonglong@huawei.com \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=pbonzini@redhat.com \
--cc=rdunlap@infradead.org \
--cc=seanjc@google.com \
--cc=seiden@linux.ibm.com \
--cc=skhan@linuxfoundation.org \
--cc=suzuki.poulose@arm.com \
--cc=tangchengchang@huawei.com \
--cc=wangzhou1@hisilicon.com \
--cc=will@kernel.org \
--cc=yangjinqian1@huawei.com \
--cc=yezhenyu2@huawei.com \
--cc=yubihong@huawei.com \
--cc=yuzenghui@huawei.com \
--cc=zhengtian10@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.