Re: [PATCH 2/3] KVM: riscv: Check hugetlb block mappings against memslot bounds
Anup Patel <[email protected]>
| Newsgroups | org.infradead.lists.kvm-riscv,org.infradead.lists.linux-riscv,org.kernel.vger.kvm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAAhSdy2MhnN_6t2_Gpds-bVk+LzYCZsYTe+QXw-CMHdc58o2EA@mail.gmail.com> |
On Wed, May 20, 2026 at 8:52 PM Jinyu Tang <[email protected]> wrote: > > RISC-V KVM has used the hugetlb VMA size directly as the G-stage > mapping size since stage-2 page table support was added. That is safe > only if the block covered by the fault is fully contained in the > memslot and the userspace address has the same offset as the GPA > within that block. > > The THP path already checks those constraints before installing a PMD > block mapping. The hugetlb path did not, so an unaligned memslot could > make KVM install a PMD or PUD sized G-stage block that covers memory > outside the slot or maps the wrong host pages. > > Select hugetlb mapping sizes through the same memslot-boundary check, > falling back from PUD to PMD to PAGE_SIZE. When a smaller hugetlb > mapping size is selected, fault the GFN aligned to that selected size > instead of the original VMA size. > > Also keep hugetlb mappings out of transparent_hugepage_adjust(). Once > the hugetlb path has chosen PAGE_SIZE, promoting it again through the > THP helper would miss the hugetlb fallback decision. > > Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming") > Signed-off-by: Jinyu Tang <[email protected]> > --- > arch/riscv/kvm/mmu.c | 40 ++++++++++++++++++++++++++++++++++++---- > 1 file changed, 36 insertions(+), 4 deletions(-) > > diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c > index 10be8f683..d2378bb1f 100644 > --- a/arch/riscv/kvm/mmu.c > +++ b/arch/riscv/kvm/mmu.c > @@ -423,12 +423,33 @@ static unsigned long transparent_hugepage_adjust(struct kvm *kvm, > return PAGE_SIZE; > } > > +static unsigned long hugetlb_mapping_size(struct kvm_memory_slot *memslot, > + unsigned long hva, > + unsigned long map_size) > +{ > + switch (map_size) { > + case PUD_SIZE: > + if (fault_supports_gstage_huge_mapping(memslot, hva, PUD_SIZE)) This patch is marked with a Fixes tag but does not include the changes adding map_size parameter to fault_supports_gstage_huge_mapping(). I think it is better to sqash PATCH1 into this patch for completness of this patch as Fix. Regards, Anup > + return PUD_SIZE; > + fallthrough; > + case PMD_SIZE: > + if (fault_supports_gstage_huge_mapping(memslot, hva, PMD_SIZE)) > + return PMD_SIZE; > + fallthrough; > + case PAGE_SIZE: > + return PAGE_SIZE; > + default: > + return map_size; > + } > +} > + > int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, > gpa_t gpa, unsigned long hva, bool is_write, > struct kvm_gstage_mapping *out_map) > { > int ret; > kvm_pfn_t hfn; > + bool is_hugetlb; > bool writable; > short vma_pageshift; > gfn_t gfn = gpa >> PAGE_SHIFT; > @@ -462,16 +483,23 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, > return -EFAULT; > } > > - if (is_vm_hugetlb_page(vma)) > + is_hugetlb = is_vm_hugetlb_page(vma); > + if (is_hugetlb) > vma_pageshift = huge_page_shift(hstate_vma(vma)); > else > vma_pageshift = PAGE_SHIFT; > vma_pagesize = 1ULL << vma_pageshift; > if (logging || (vma->vm_flags & VM_PFNMAP)) > vma_pagesize = PAGE_SIZE; > + else if (is_hugetlb) > + vma_pagesize = hugetlb_mapping_size(memslot, hva, vma_pagesize); > > + /* > + * For hugetlb mappings, vma_pagesize might have been reduced from the > + * VMA size to a smaller safe mapping size. > + */ > if (vma_pagesize == PMD_SIZE || vma_pagesize == PUD_SIZE) > - gfn = (gpa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT; > + gfn = ALIGN_DOWN(gpa, vma_pagesize) >> PAGE_SHIFT; > > /* > * Read mmu_invalidate_seq so that KVM can detect if the results of > @@ -513,8 +541,12 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, > if (mmu_invalidate_retry(kvm, mmu_seq)) > goto out_unlock; > > - /* Check if we are backed by a THP and thus use block mapping if possible */ > - if (!logging && (vma_pagesize == PAGE_SIZE)) > + /* > + * Check if we are backed by a THP and thus use block mapping if > + * possible. Hugetlb mappings already selected their target size above, > + * so do not promote them through the THP helper. > + */ > + if (!logging && !is_hugetlb && vma_pagesize == PAGE_SIZE) > vma_pagesize = transparent_hugepage_adjust(kvm, memslot, hva, &hfn, &gpa); > > if (writable) { > -- > 2.43.0 > -- kvm-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kvm-riscv