From: sashiko-bot@kernel.org
To: "Leonardo Bras" <leo.bras@arm.com>
Cc: kvm@vger.kernel.org
Subject: Re: [RFC PATCH v3 3/3] KVM: selftests: dirty_log_perf_test: Add dirty-ring support
Date: Wed, 08 Jul 2026 15:36:13 +0000 [thread overview]
Message-ID: <20260708153613.8F7AF1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260708152232.2568907-4-leo.bras@arm.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] The 'dirty memory time' metric incorrectly includes the time vCPU threads spend waiting for the global `collect` mutex, misattributing it to guest execution time and underreporting dirty ring management overhead.
- [Medium] Lockless synchronization between the vCPU threads and the main thread lacks memory barriers, creating a data race on the `vcpu_dirty_ring_collect` timespec payload.
--
--- Patch [3]: [RFC PATCH v3 3/3] KVM: selftests: dirty_log_perf_test: Add dirty-ring support ---
commit d30bfe94110209591fe009dbe43668ba5266de12
Author: Leonardo Bras <leo.bras@arm.com>
KVM: selftests: dirty_log_perf_test: Add dirty-ring support
dirty_log_test supports both dirty-bitmap and dirty-ring as dirty-page
tracking mechanisms, while dirty_log_perf_test only supports dirty-bitmap.
Add support to dirty-ring on dirty_log_perf_test so it can be used to
compare performance between changes in the mechanism.
> diff --git a/tools/testing/selftests/kvm/dirty_log_perf_test.c b/tools/testing/selftests/kvm/dirty_log_perf_test.c
> index 69b38791440e7..181f521c9be96 100644
> --- a/tools/testing/selftests/kvm/dirty_log_perf_test.c
> +++ b/tools/testing/selftests/kvm/dirty_log_perf_test.c
> @@ -29,9 +30,53 @@ static bool run_vcpus_while_disabling_dirty_logging;
>
> /* Host variables */
> static u64 dirty_log_manual_caps;
> +static u32 dirty_ring_size;
> static bool host_quit;
> static int iteration;
> static int vcpu_last_completed_iteration[KVM_MAX_VCPUS];
> +static struct timespec vcpu_dirty_ring_collect[KVM_MAX_VCPUS];
> +
> +static void dirty_ring_collect(struct kvm_vcpu *vcpu, u32 *ring_idx,
> + struct timespec *ts)
> +{
> + static pthread_mutex_t collect = PTHREAD_MUTEX_INITIALIZER;
> + struct timespec start;
> + struct kvm_dirty_gfn *dirty_gfns = vcpu_map_dirty_ring(vcpu);
> + u32 idx = *ring_idx;
> + u32 ring_size = vcpu->vm->dirty_ring_size / sizeof(struct kvm_dirty_gfn);
> + int cleared, count;
> +
> + pthread_mutex_lock(&collect);
> +
> + clock_gettime(CLOCK_MONOTONIC, &start);
[Severity: Medium]
Will this timer placement incorrectly measure performance metrics?
Because clock_gettime() is called after acquiring the collect mutex, the
returned ts will not include any time the vCPU thread spends waiting for the
lock.
Later in vcpu_worker():
ts_diff = timespec_elapsed(start);
if (use_dirty_ring) {
ts_diff = timespec_sub(ts_diff, collect);
}
Since collect excludes lock contention time, subtracting it leaves that
contention overhead in ts_diff. Does this result in misattributing lock
contention to guest execution time?
> +
> + while (true) {
> + struct kvm_dirty_gfn *cur;
[ ... ]
> @@ -43,17 +88,33 @@ static void vcpu_worker(struct memstress_vcpu_args *vcpu_args)
> struct timespec ts_diff;
> struct timespec total = (struct timespec){0};
> struct timespec avg;
> + bool use_dirty_ring = !!vcpu->vm->dirty_ring_size;
> + u32 ring_idx = 0;
> int ret;
>
> run = vcpu->run;
>
> while (!READ_ONCE(host_quit)) {
> int current_iteration = READ_ONCE(iteration);
> + struct timespec collect = (struct timespec){0};
>
> clock_gettime(CLOCK_MONOTONIC, &start);
> - ret = _vcpu_run(vcpu);
> +
> + do {
> + ret = _vcpu_run(vcpu);
> + if (!use_dirty_ring)
> + break;
> +
> + dirty_ring_collect(vcpu, &ring_idx, &collect);
> + } while (run->exit_reason == KVM_EXIT_DIRTY_RING_FULL);
> +
> ts_diff = timespec_elapsed(start);
>
> + if (use_dirty_ring) {
> + ts_diff = timespec_sub(ts_diff, collect);
> + vcpu_dirty_ring_collect[vcpu_idx] = collect;
> + }
> +
> TEST_ASSERT(ret == 0, "vcpu_run failed: %d", ret);
> TEST_ASSERT(get_ucall(vcpu, NULL) == UCALL_SYNC,
> "Invalid guest sync status: exit_reason=%s",
> exit_reason_str(run->exit_reason));
>
> pr_debug("Got sync event from vCPU %d\n", vcpu_idx);
> vcpu_last_completed_iteration[vcpu_idx] = current_iteration;
[Severity: Medium]
Are memory barriers needed for this lockless synchronization?
The worker thread updates vcpu_dirty_ring_collect and then sets
vcpu_last_completed_iteration to signal completion. However, this is done
without store-release semantics.
Meanwhile, the main thread in run_test() spins on the completion flag and
then reads the array:
for (i = 0; i < nr_vcpus; i++) {
while (READ_ONCE(vcpu_last_completed_iteration[i]) != iteration)
;
}
/* ... */
if (dirty_ring_size) {
for (i = 0; i < nr_vcpus; i++)
iteration_sum = timespec_add(iteration_sum,
vcpu_dirty_ring_collect[i]);
}
Could weakly-ordered architectures like ARM64 reorder the worker thread's
stores (or the main thread's loads), causing the main thread to read torn or
stale struct timespec data?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260708152232.2568907-1-leo.bras@arm.com?part=3
next prev parent reply other threads:[~2026-07-08 15:36 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-08 15:22 [RFC PATCH v3 0/3] KVM: selftests: Improvements on dirty-ring Leonardo Bras
2026-07-08 15:22 ` [RFC PATCH v3 1/3] KVM: selftests: memstress: Add option to enable dirty-ring on VM creation Leonardo Bras
2026-07-08 15:22 ` [RFC PATCH v3 2/3] KVM: selftests: Check dirty-ring size before enabling Leonardo Bras
2026-07-08 15:22 ` [RFC PATCH v3 3/3] KVM: selftests: dirty_log_perf_test: Add dirty-ring support Leonardo Bras
2026-07-08 15:36 ` sashiko-bot [this message]
2026-07-08 16:57 ` Leonardo Bras
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=20260708153613.8F7AF1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=leo.bras@arm.com \
--cc=sashiko-reviews@lists.linux.dev \
/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