From: sashiko-bot@kernel.org
To: "David Woodhouse" <dwmw2@infradead.org>, kvm@vger.kernel.org
Cc: linux-rt-devel@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 14/20] KVM: selftests: Add nested VMX APIC cache invalidation test
Date: Thu, 05 Nov 2026 02:25:13 +0000 [thread overview]
Message-ID: <sashiko-outbox-198459@kernel.org> (raw)
In-Reply-To: <20261105020104.2507083-15-dwmw2@infradead.org>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] KVM: selftests: missing virtualize APIC accesses check in main()
- [Medium] KVM: selftests: memslot move races with vmlaunch() and vmresume() in run()
- [Medium] KVM: selftests: vmx_apic_update_test fails to verify APIC-access exits
--
commit c3febf61f5d64e784b8c55b816b4a00a658a0208
Author: Fred Griffoul <fgriffo@amazon.co.uk>
KVM: selftests: Add nested VMX APIC cache invalidation test
This commit adds a selftest for nested VMX APIC-access page cache
invalidation while an L2 guest writes to the APIC-access page concurrently
with either madvise(MADV_DONTNEED) or memslot moves.
> diff --git a/tools/testing/selftests/kvm/x86/vmx_apic_update_test.c b/tools/testing/selftests/kvm/x86/vmx_apic_update_test.c
> new file mode 100644
> index 0000000000000..357e10c88cd0a
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/x86/vmx_apic_update_test.c
[ ... ]
> +static void l1_guest_code(struct vmx_pages *vmx_pages)
> +{
> + uint32_t control, exit_reason;
> +
> + prepare_for_vmx_operation(vmx_pages);
> + load_vmcs(vmx_pages);
> + prepare_vmcs(vmx_pages, l2_guest_code);
> +
> + /* Enable APIC access */
> + control = vmread(CPU_BASED_VM_EXEC_CONTROL);
> + control |= CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
> + vmwrite(CPU_BASED_VM_EXEC_CONTROL, control);
> + control = vmread(SECONDARY_VM_EXEC_CONTROL);
> + control |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
> + vmwrite(SECONDARY_VM_EXEC_CONTROL, control);
> + vmwrite(APIC_ACCESS_ADDR, VAPIC_GPA);
> +
> + GUEST_SYNC1(0);
> + vmlaunch();
> +again:
> + exit_reason = vmread(VM_EXIT_REASON);
> + if (exit_reason == EXIT_REASON_APIC_ACCESS) {
> + uint64_t guest_rip = vmread(GUEST_RIP);
> + uint64_t instr_len = vmread(VM_EXIT_INSTRUCTION_LEN);
> +
> + vmwrite(GUEST_RIP, guest_rip + instr_len);
> + vmresume();
> + goto again;
> + }
> +
> + GUEST_SYNC1(exit_reason);
> + GUEST_ASSERT(exit_reason == EXIT_REASON_VMCALL);
> + GUEST_DONE();
> +}
[ ... ]
> +static void *update_move_memslot(void *arg)
> +{
> + struct update_control *ctrl = arg;
> + uint64_t gpa = VAPIC_GPA;
> +
> + wait_for_start_signal(ctrl);
> +
> + /*
> + * Alternate the slot between VAPIC_GPA and an alternate address,
> + * so that the GPA under test is repeatedly unbacked (L2's APIC
> + * access bounces to userspace as MMIO) and re-backed (KVM must
> + * re-latch the page). Moving strictly away would change
> + * vCPU-visible state only once.
> + */
> + while (is_running(ctrl)) {
> + usleep(update_period_ms * 1000);
> + gpa = (gpa == VAPIC_GPA) ? VAPIC_GPA + 0x10000 : VAPIC_GPA;
> + vm_mem_region_move(ctrl->vm, VAPIC_SLOT, gpa);
> + ctrl->updates++;
> + }
> +
> + return NULL;
> +}
> +
> +static void run(void * (*update)(void *), const char *name, bool mmio_ok)
> +{
[ ... ]
> + case KVM_EXIT_MMIO:
> + /*
> + * While the slot is moved away, the GPA under test
> + * is unbacked and the access legitimately bounces
> + * to userspace as MMIO (until the updater moves it
> + * back). madvise() never unbacks the GPA, so there
> + * an MMIO exit means KVM lost the mapping: fail.
> + */
> + TEST_ASSERT(mmio_ok,
> + "%s: unexpected APIC MMIO access at 0x%llx",
> + progname, vcpu->run->mmio.phys_addr);
> + printf
> + ("%s: APIC MMIO access at 0x%llx (memslot move effect)\n",
> + progname, vcpu->run->mmio.phys_addr);
> + break;
[Severity: Medium]
Does checking for the absence of KVM_EXIT_MMIO in run() actually verify that
APIC-access virtualization stayed active across invalidations?
In l2_guest_code(), L2 performs 8 writes to VAPIC_GPA + 0x80 followed by
vmcall(), while l1_guest_code() handles EXIT_REASON_APIC_ACCESS by advancing
GUEST_RIP and executing vmresume() without counting how many
EXIT_REASON_APIC_ACCESS exits occurred.
In the madvise(MADV_DONTNEED) test, VAPIC_SLOT remains registered at
VAPIC_GPA. After madvise() zaps the userspace PTE and EPT02 SPTE, L2's next
write faults in a new anonymous host page in EPT02 rather than triggering
KVM_EXIT_MMIO. If KVM fails to refresh vmcs02.APIC_ACCESS_ADDR to the new
HPA (or fails to re-enable SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES after
update_move_memslot() moves VAPIC_SLOT back to VAPIC_GPA), the EPT02 HPA
will not match vmcs02.APIC_ACCESS_ADDR and L2's writes will silently commit
to normal memory without triggering either EXIT_REASON_APIC_ACCESS or
KVM_EXIT_MMIO.
Should l1_guest_code() and run() count the EXIT_REASON_APIC_ACCESS exits and
assert that all 8 L2 writes are intercepted as EXIT_REASON_APIC_ACCESS in
the madvise case (and as either EXIT_REASON_APIC_ACCESS or KVM_EXIT_MMIO in
the memslot-move case)?
> + default:
> + TEST_FAIL("%s: Unexpected exit reason: %d (flags 0x%x)",
> + progname,
> + vcpu->run->exit_reason, vcpu->run->flags);
> + }
> + }
[Severity: Medium]
As reported by Sashiko on v1 [1], can update_move_memslot() race with
vmlaunch() and vmresume() in l1_guest_code() and cause run() to fail with
KVM_EXIT_INTERNAL_ERROR?
In l1_guest_code(), GUEST_SYNC1(0) starts the updater thread before
vmlaunch(), and each EXIT_REASON_APIC_ACCESS exit into L1 advances GUEST_RIP
and executes vmresume(). Concurrently, update_move_memslot() toggles
VAPIC_SLOT between VAPIC_GPA and VAPIC_GPA + 0x10000.
In KVM's nested VM-entry path:
nested_vmx_run()
nested_vmx_enter_non_root_mode()
nested_get_vmcs12_pages(vcpu, false)
nested_get_vmcs12_pages() is called with lazy == false on both vmlaunch and
vmresume. Unlike lazy revalidation while L2 is already in guest mode, if
VAPIC_GPA is unbacked when L1 executes vmlaunch() or vmresume(),
nested_get_vmcs12_pages() treats the missing gfn as an error and exits to
userspace with KVM_EXIT_INTERNAL_ERROR, hitting the default TEST_FAIL() case
in run().
[ ... ]
> +int main(int argc, char *argv[])
> +{
> + int opt_madvise = 0;
> + int opt_memslot_move = 0;
> +
> + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
> + TEST_REQUIRE(kvm_cpu_has_ept());
[Severity: Medium]
Should main() also check TEST_REQUIRE(kvm_cpu_has_vmx_virtualize_apic_accesses())
here, similar to vmx_apic_access_test.c?
In l1_guest_code(), the test unconditionally sets
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES in SECONDARY_VM_EXEC_CONTROL before
calling vmlaunch(). On hosts or nested environments where virtualize APIC
accesses is unsupported or disabled (for example when flexpriority is
disabled), vmlaunch() will fail with a guest assertion failure instead of
skipping the test.
[1] https://lore.kernel.org/r/20260920211920.928306-13-dwmw2@infradead.org
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105020104.2507083-1-dwmw2@infradead.org?part=14
next prev parent reply other threads:[~2026-11-05 2:25 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 2:00 [PATCH v2 00/20] KVM: Use atomic SRCU for gfn-to-pfn cache, reinstate guest mode for x86 nesting David Woodhouse
2026-11-05 2:00 ` [PATCH v2 01/20] KVM: x86/xen: Fill the hypercall page with a single guest write David Woodhouse
2026-11-05 2:00 ` [PATCH v2 02/20] KVM: x86/xen: Add KVM_XEN_VCPU_ATTR_TYPE_WRITE_HYPERCALL_PAGE David Woodhouse
2026-11-05 2:00 ` [PATCH v2 03/20] KVM: x86/xen: Extract delivery of event to vCPU into a separate helper David Woodhouse
2026-11-05 2:00 ` [PATCH v2 04/20] KVM: x86/xen: Explicitly tag "shared info" page as never being dirty tracked David Woodhouse
2026-11-05 2:00 ` [PATCH v2 05/20] KVM: x86/xen: Don't dirty track "vCPU info" page David Woodhouse
2026-11-05 2:00 ` [PATCH v2 06/20] KVM: x86: Request the guest TLB flush from record_steal_time() David Woodhouse
2026-11-05 2:00 ` [PATCH v2 07/20] KVM: selftests: Actually deactivate the HVA-based shared_info cache in xen_shinfo_test David Woodhouse
2026-11-05 2:00 ` [PATCH v2 08/20] KVM: pfncache: Use atomic SRCU for readers instead of a rwlock David Woodhouse
2026-11-05 2:00 ` [PATCH v2 09/20] KVM: x86: Use gfn_to_pfn_cache for steal time / preempted status David Woodhouse
2026-11-05 2:00 ` [PATCH v2 10/20] KVM: pfncache: Add guest-mode pinning (GUEST_USES_PFN successor) David Woodhouse
2026-11-05 2:29 ` sashiko-bot
2026-11-05 2:00 ` [PATCH v2 11/20] KVM: nVMX: Implement cache for L1 MSR bitmap David Woodhouse
2026-11-05 2:00 ` [PATCH v2 12/20] KVM: nVMX: Use pinned pfncache for L1 APIC virtualization pages David Woodhouse
2026-11-05 2:33 ` sashiko-bot
2026-11-05 2:00 ` [PATCH v2 13/20] KVM: x86: Post KVM_REQ_GET_NESTED_STATE_PAGES on memslot updates David Woodhouse
2026-11-05 2:00 ` [PATCH v2 14/20] KVM: selftests: Add nested VMX APIC cache invalidation test David Woodhouse
2026-11-05 2:25 ` sashiko-bot [this message]
2026-11-05 2:00 ` [PATCH v2 15/20] KVM: nSVM: Use a gfn_to_pfn_cache for the vmcb12 page David Woodhouse
2026-11-05 2:00 ` [PATCH v2 16/20] KVM: nSVM: Cache L1's MSR permissions map pages David Woodhouse
2026-11-05 2:00 ` [PATCH v2 17/20] KVM: nSVM: Cache L1's IO " David Woodhouse
2026-11-05 2:01 ` [PATCH v2 18/20] KVM: selftests: Add nested transition benchmark David Woodhouse
2026-11-05 2:01 ` [PATCH v2 19/20] KVM: selftests: Add Xen evtchn vs memslot-update race test David Woodhouse
2026-11-05 2:01 ` [PATCH v2 20/20] KVM: selftests: Add Xen evtchn vs mmu_notifier race test for HVA caches David Woodhouse
2026-11-05 2:28 ` sashiko-bot
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=sashiko-outbox-198459@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dwmw2@infradead.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--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
all inboxes | Powered by JetHome®