From: sashiko-bot@kernel.org
To: "Jinyu Tang" <jinyu.tang@linux.dev>
Cc: kvm@vger.kernel.org
Subject: Re: [PATCH v3 1/3] KVM: riscv: Implement KVM_PRE_FAULT_MEMORY
Date: Fri, 14 Aug 2026 12:04:44 +0000 [thread overview]
Message-ID: <20260814120445.3324C1F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260814114507.583424-2-jinyu.tang@linux.dev>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] The KVM_PRE_FAULT_MEMORY ioctl handler loops infinitely in the kernel if it encounters a HWPOISON page and the userspace thread has blocked SIGBUS.
- [Medium] kvm_arch_vcpu_pre_fault_memory() can silently skip requested pages and report false progress when mapping a split THP page.
Pre-existing issues:
- [High] Infinite VMExit page fault loop when a guest accesses an unaligned THP address on a split page table.
- [High] Physical page table leak when overwriting a lower-level page table directory with a huge page leaf PTE.
--
--- Patch [1]: [PATCH v3 1/3] KVM: riscv: Implement KVM_PRE_FAULT_MEMORY ---
commit ac8ca417e02ba68eb7b7c58fbc637ee417dc2c72
Author: Jinyu Tang <jinyu.tang@linux.dev>
KVM: riscv: Implement KVM_PRE_FAULT_MEMORY
This commit introduces the KVM_PRE_FAULT_MEMORY ioctl handler for RISC-V.
It reuses the existing G-stage fault mapping path with a read access to
populate KVM page tables before running a vCPU, looping until a mapping
is installed or an exit condition is met.
> diff --git a/arch/riscv/kvm/gstage.c b/arch/riscv/kvm/gstage.c
> index b0474fcf065aa..ebd1e8a4b9e38 100644
> --- a/arch/riscv/kvm/gstage.c
> +++ b/arch/riscv/kvm/gstage.c
> @@ -280,6 +280,9 @@ int kvm_riscv_gstage_map_page(...)
> } else if (ALIGN_DOWN(PFN_PHYS(pte_pfn(ptep_get(ptep))), page_size) == hpa) {
> kvm_riscv_gstage_update_pte_prot(gstage, ptep_level, gpa, ptep, prot);
> + out_map->addr = ALIGN_DOWN(gpa, page_size);
> + out_map->level = ptep_level;
> + out_map->pte = ptep_get(ptep);
> return 0;
> }
> }
[Severity: High]
This isn't a bug introduced by this patch, but does this lead to an
infinite VMExit loop when a guest accesses an unaligned THP address on
a split page table?
During fault handling, transparent_hugepage_adjust() in kvm_riscv_mmu_map()
can silently overwrite the original faulting gpa with the 2MB-aligned
base address.
If the G-stage page table is currently split into 4KB PTEs, this block in
kvm_riscv_gstage_map_page() intentionally updates only the 4KB PTE at the
newly aligned gpa. The originally faulting 4KB page remains unmapped,
causing the guest to immediately fault again upon resumption.
[ ... ]
> out_map->pte = pfn_pte(PFN_DOWN(hpa), prot);
> out_map->pte = pte_mkdirty(out_map->pte);
>
> return kvm_riscv_gstage_set_pte(gstage, pcache, out_map);
> }
[Severity: High]
This is a pre-existing issue, but does this leak physical page tables when
overwriting a lower-level page table directory with a huge page leaf PTE?
If 4KB leaf PTEs inside a THP-backed region are zapped (for example, via
MADV_DONTNEED) but the page directory remains, a subsequent fault triggers
a THP mapping. kvm_riscv_gstage_get_leaf() fails to find a leaf.
The code then falls through here to kvm_riscv_gstage_set_pte(), which blindly
overwrites the existing directory entry with a huge page leaf PTE. Because
freeing page tables is not yet supported, the orphaned child page tables
appear to be leaked.
> diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
> index 8a0aa5e0e216e..c71c1ebb07857 100644
> --- a/arch/riscv/kvm/mmu.c
> +++ b/arch/riscv/kvm/mmu.c
[ ... ]
> + for (;;) {
> + if (signal_pending(current))
> + return -EINTR;
> +
> + if (kvm_check_request(KVM_REQ_VM_DEAD, vcpu))
> + return -EIO;
> +
> + cond_resched();
> + ret = kvm_riscv_mmu_map(vcpu, memslot, range->gpa, hva, false, &out_map);
> + if (ret)
> + return ret;
> +
> + if (pte_val(out_map.pte))
> + break;
> + }
[Severity: High]
Can this loop spin infinitely if the userspace thread blocks SIGBUS and
KVM encounters a hardware-poisoned page?
Looking at kvm_riscv_mmu_map(), it handles HWPOISON by calling
send_sig_mceerr() and returning 0 without populating out_map.
If the userspace thread has SIGBUS blocked, send_sig_mceerr() queues the
signal but might not set TIF_SIGPENDING. In that scenario, signal_pending()
won't catch the pending signal, out_map.pte remains empty, and the loop
will retry infinitely without yielding back to userspace.
> +
> + map_size = PAGE_SIZE << (out_map.level * kvm_riscv_gstage_index_bits);
> + end = ALIGN_DOWN(range->gpa, map_size) + map_size;
> +
> + return min_t(u64, range->size, end - range->gpa);
> +}
[Severity: Medium]
Does this miscalculate the mapped progress when handling a split THP page?
If transparent_hugepage_adjust() aligns the gpa down to the 2MB base and
kvm_riscv_gstage_map_page() falls back to a 4KB mapping, the 4KB PTE is
populated at the base address. out_map.addr is correctly set to this base.
However, the progress here is calculated using the original unaligned
range->gpa instead of out_map.addr. If the requested GPA was at an offset,
KVM might falsely report progress for the unmapped requested page while
actually mapping the unrequested base page.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260814114507.583424-1-jinyu.tang@linux.dev?part=1
next prev parent reply other threads:[~2026-08-14 12:04 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-14 11:45 [PATCH v3 0/3] KVM: riscv: Add KVM_PRE_FAULT_MEMORY support Jinyu Tang
2026-08-14 11:45 ` Jinyu Tang
2026-08-14 11:45 ` Jinyu Tang
2026-08-14 11:45 ` [PATCH v3 1/3] KVM: riscv: Implement KVM_PRE_FAULT_MEMORY Jinyu Tang
2026-08-14 11:45 ` Jinyu Tang
2026-08-14 11:45 ` Jinyu Tang
2026-08-14 12:04 ` sashiko-bot [this message]
2026-08-14 11:45 ` [PATCH v3 2/3] KVM: selftests: Add RISC-V Sv57 page table indexing Jinyu Tang
2026-08-14 11:45 ` Jinyu Tang
2026-08-14 11:45 ` Jinyu Tang
2026-08-14 11:45 ` [PATCH v3 3/3] KVM: selftests: Enable pre_fault_memory_test for RISC-V Jinyu Tang
2026-08-14 11:45 ` Jinyu Tang
2026-08-14 11:45 ` Jinyu Tang
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=20260814120445.3324C1F00A3A@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=jinyu.tang@linux.dev \
--cc=kvm@vger.kernel.org \
--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 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.