From: sashiko-bot@kernel.org
To: "Tian Zheng" <zhengtian10@huawei.com>
Cc: kvmarm@lists.linux.dev, kvm@vger.kernel.org,
"Marc Zyngier" <maz@kernel.org>,
"Oliver Upton" <oupton@kernel.org>
Subject: Re: [PATCH v5 14/15] KVM: arm64: Document HDBSS buffer size ioctl
Date: Tue, 29 Sep 2026 11:06:38 +0000 [thread overview]
Message-ID: <20260929110638.D19171F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260929103655.85107-15-zhengtian10@huawei.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] kvm: arm64: missing vCPU kick in kvm_arch_update_hw_dirty_mode causes data corruption
- [High] kvm: arm64: stage2_wrprotect_walker clobbers concurrent hardware PTE updates
- [Medium] kvm: uapi: enabling dirty ring silently resets HDBSS buffer size
- [Low] kvm: uapi: KVM_CHECK_EXTENSION misused to return mutable VM state
--
commit ad3d8df658768bdca959742e1b61e3dd3914fdd8
Author: Tian Zheng <zhengtian10@huawei.com>
KVM: arm64: Document HDBSS buffer size ioctl
Document KVM_CAP_ARM_HDBSS_BUFFER_SIZE, which lets userspace configure the
per-vCPU HDBSS buffer size for hardware-assisted dirty tracking during live
migration.
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -9056,6 +9056,34 @@ enabled, cmma can't be enabled anymore and pfmfi and the storage key
> interpretation are disabled. If cmma has already been enabled or the
> hpage_2g module parameter is not set to 1, -EINVAL is returned.
>
> +7.48 KVM_CAP_ARM_HDBSS_BUFFER_SIZE
> +-----------------------------------
> +
> +:Architectures: arm64
> +:Target: VM
> +:Parameters: args[0] is the per-vCPU HDBSS buffer size in bytes
> +:Returns: 0 on success; -EINVAL if the size is invalid or vCPUs have already
> + been created; -EBUSY if the buffer size was already configured.
> +
> +This capability configures the per-vCPU HDBSS buffer size used for
> +hardware-assisted dirty tracking during live migration.
> +
> +Userspace sets the size in bytes via KVM_ENABLE_CAP. KVM allocates
> +per-vCPU HDBSS buffers of the requested size.
> +
> +KVM_CHECK_EXTENSION returns the maximum supported size (``SZ_2M``)
> +when queried without a VM, or the configured per-VM size (default
> +``PAGE_SIZE``) when queried with a VM.
[Severity: Low]
KVM_CHECK_EXTENSION is designed to advertise static feature support and
limits, not to serve as a GET interface for mutable, dynamically configured
VM attributes.
Would it be better to use a dedicated interface to read back this dynamic
state instead of KVM_CHECK_EXTENSION?
> +
> +Constraints:
> +
> +- The size must be a power of two in [``PAGE_SIZE``, ``SZ_2M``].
> +- Dirty-bitmap mode only: rejected with -EINVAL once the dirty ring
> + (``KVM_CAP_DIRTY_LOG_RING``) is enabled, and enabling the ring after
> + a size was set resets it to the default.
[Severity: Medium]
The KVM guidelines mandate that new memslot and vCPU flags default to
immutable.
Instead of silently mutating previously configured state (which can lead to
unpredictable state-machine transitions that userspace is not prepared
for), should this incompatible capability configuration fail explicitly by
returning an error like -EINVAL?
> +- Must be set before any vCPU is created; a second setting is rejected
> + with -EBUSY.
>
> diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
> --- a/arch/arm64/kvm/hyp/pgtable.c
> +++ b/arch/arm64/kvm/hyp/pgtable.c
[ ... ]
> @@ -1285,12 +1298,47 @@ static int stage2_update_leaf_attrs(struct kvm_pgtable *pgt, u64 addr,
> return 0;
> }
>
> +static int stage2_wrprotect_walker(const struct kvm_pgtable_visit_ctx *ctx,
> + enum kvm_pgtable_walk_flags visit)
> +{
> + kvm_pte_t new = ctx->old & ~KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
> +
> + /* We remove DBM on blocks so they can fault and get split */
> + if (ctx->level < KVM_PGTABLE_LAST_LEVEL)
> + new &= ~KVM_PTE_LEAF_ATTR_HI_S2_DBM;
> +
> + if (kvm_pte_valid(ctx->old) && ctx->old != new &&
> + (ctx->old & KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W) &&
> + ctx->mm_ops->mark_page_dirty)
> + ctx->mm_ops->mark_page_dirty(kvm_pte_to_phys(ctx->old));
> +
> + /*
> + * The plain WRITE_ONCE races with hardware updates; both are
> + * benign.
> + *
> + * AF: the update may be lost, and is set on the next access.
> + *
> + * Dirty state: we only rewrite entries whose old value had S2AP[1]
> + * set, while hardware only promotes entries with S2AP[1] clear, so
> + * the two never touch the same entry. The one overlap is DBM removal
> + * on writable-clean blocks: a racing promotion is demoted back to
> + * read-only, but the write is still recorded in the HDBSS buffer and
> + * the folio was marked dirty at fault-in, so nothing is lost.
> + */
> + if (kvm_pte_valid(ctx->old) && ctx->old != new)
> + WRITE_ONCE(*ctx->ptep, new);
[Severity: High]
The global review guidelines strictly mandate: When KVM updates SPTE bits that
the hardware page-table walker also writes (Dirty/Access on leaf entries), the
update must not clobber a concurrent hardware update.
Since WRITE_ONCE unconditionally overwrites the PTE with the old masked
value, could this non-atomic write in stage2_wrprotect_walker() clobber
concurrent hardware updates to the Access Flag (AF) or Dirty Bit on leaf
PTEs?
> +
> + return 0;
> +}
> +
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
[ ... ]
> @@ -2581,6 +2629,45 @@ int __init kvm_mmu_init(u32 hyp_va_bits)
> return err;
> }
>
> +/*
> + * The VM's hardware dirty-management mode is a derived value, a pure
> + * function of the static capabilities and the number of logging
> + * memslots, so recomputing it on every event cannot lose an update
> + * and needs no locking against racing writers:
> + *
> + * logging && HDBSS-capable -> HD|HA|HDBSS (hardware tracking)
> + * logging, no HDBSS -> off (write-protect faults)
> + * !logging && HAFDBS-cap. -> HD|HA (only written pages go dirty)
> + */
> +void kvm_arch_update_hw_dirty_mode(struct kvm *kvm)
> +{
> + unsigned long cur, target;
> + bool logging = atomic_read(&kvm->nr_memslots_dirty_logging) != 0;
> +
> + if (logging && kvm_supports_hdbss(kvm))
> + target = VTCR_EL2_HD | VTCR_EL2_HA | VTCR_EL2_HDBSS;
> + else if (logging || !kvm_supports_hafdbs())
> + target = 0;
> + else
> + target = VTCR_EL2_HD | VTCR_EL2_HA;
> +
> + cur = kvm->arch.mmu.vtcr & (VTCR_EL2_HD | VTCR_EL2_HA | VTCR_EL2_HDBSS);
> + if (cur == target)
> + return;
> +
> + kvm->arch.mmu.vtcr = (kvm->arch.mmu.vtcr &
> + ~(VTCR_EL2_HD | VTCR_EL2_HA | VTCR_EL2_HDBSS)) |
> + target;
> +
> + kvm_make_all_cpus_request(kvm, KVM_REQ_RELOAD_STAGE2);
> +
> + /*
> + * The request only reloads VTCR_EL2; cached translations keep
> + * the old permissions until invalidated.
> + */
> + kvm_flush_remote_tlbs(kvm);
[Severity: Critical]
Inside kvm_arch_update_hw_dirty_mode(), kvm_make_all_cpus_request() is issued
with KVM_REQ_RELOAD_STAGE2, which is defined as:
#define KVM_REQ_RELOAD_STAGE2 \
KVM_ARCH_REQ_FLAGS(12, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
The KVM_REQUEST_NO_WAKEUP flag prevents the request from interrupting running
vCPUs. The subsequent kvm_flush_remote_tlbs() executes a hardware broadcast TLBI
and also does not send IPIs.
Because running vCPUs are never kicked out of guest mode, won't they
continue executing with their physical VTCR_EL2 register holding the
stale state (HD=1)?
If software dirty logging is active but HDBSS is not correctly synchronized
on the CPU, the hardware page table walker could silently promote
writable-clean PTEs to writable-dirty without trapping. Since KVM never
sees the write, could this cause silent data loss during live migration?
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260929103655.85107-1-zhengtian10@huawei.com?part=14
next prev parent reply other threads:[~2026-09-29 11:06 UTC|newest]
Thread overview: 28+ 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-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-09-29 10:36 ` [PATCH v5 06/15] KVM: arm64: Add support for FEAT_HDBSS Tian Zheng
2026-09-29 10:36 ` [PATCH v5 07/15] KVM: arm64: Add HDBSS per-vCPU buffer management Tian Zheng
2026-09-29 10:36 ` [PATCH v5 08/15] KVM: arm64: Flush the HDBSS buffer on VM exit Tian Zheng
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 [this message]
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=20260929110638.D19171F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox