[PATCH 1/3] KVM: riscv: Pass the target size to huge G-stage checks

Anup Patel anup at brainfault.org
Wed Jun 3 22:29:12 PDT 2026


On Wed, May 20, 2026 at 8:52 PM Jinyu Tang <tjytimi at 163.com> wrote:
>
> fault_supports_gstage_huge_mapping() already contains the two checks
> needed before installing a G-stage block mapping: the userspace address
> and GPA must have matching offsets within the block, and the whole block
> must be contained within the memslot.
>
> The helper currently hard-codes PMD_SIZE because its only caller is the
> transparent hugepage path. The hugetlb path needs the same checks, but
> the target block size can be either PMD_SIZE or PUD_SIZE depending on the
> hugetlb VMA.
>
> So pass the target mapping size into the helper and use it for the
> alignment and bounds checks. This keeps the existing THP PMD behavior
> unchanged and prepares the helper to be reused for the following hugetlb
> fix.
>
> Signed-off-by: Jinyu Tang <tjytimi at 163.com>
> ---
>  arch/riscv/kvm/mmu.c | 14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
> index 2d3def024..10be8f683 100644
> --- a/arch/riscv/kvm/mmu.c
> +++ b/arch/riscv/kvm/mmu.c
> @@ -286,7 +286,8 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
>  }
>
>  static bool fault_supports_gstage_huge_mapping(struct kvm_memory_slot *memslot,
> -                                              unsigned long hva)
> +                                              unsigned long hva,
> +                                              unsigned long map_size)
>  {
>         hva_t uaddr_start, uaddr_end;
>         gpa_t gpa_start;
> @@ -300,8 +301,8 @@ static bool fault_supports_gstage_huge_mapping(struct kvm_memory_slot *memslot,
>
>         /*
>          * Pages belonging to memslots that don't have the same alignment
> -        * within a PMD for userspace and GPA cannot be mapped with g-stage
> -        * PMD entries, because we'll end up mapping the wrong pages.
> +        * within a huge page for userspace and GPA cannot be mapped with
> +        * g-stage block entries, because we'll end up mapping the wrong pages.
>          *
>          * Consider a layout like the following:
>          *
> @@ -321,7 +322,7 @@ static bool fault_supports_gstage_huge_mapping(struct kvm_memory_slot *memslot,
>          *   e -> g
>          *   f -> h
>          */
> -       if ((gpa_start & (PMD_SIZE - 1)) != (uaddr_start & (PMD_SIZE - 1)))
> +       if ((gpa_start & (map_size - 1)) != (uaddr_start & (map_size - 1)))
>                 return false;
>
>         /*
> @@ -336,7 +337,8 @@ static bool fault_supports_gstage_huge_mapping(struct kvm_memory_slot *memslot,
>          * userspace_addr or the base_gfn, as both are equally aligned (per
>          * the check above) and equally sized.
>          */
> -       return (hva >= ALIGN(uaddr_start, PMD_SIZE)) && (hva < ALIGN_DOWN(uaddr_end, PMD_SIZE));
> +       return (hva & ~(map_size - 1)) >= uaddr_start &&
> +              (hva & ~(map_size - 1)) + map_size <= uaddr_end;

This looks counter intuitive.
Why not have "(hva >= ALIGN(uaddr_start, map_size)) && (hva <
ALIGN_DOWN(uaddr_end, map_size))" ?

>  }
>
>  static int get_hva_mapping_size(struct kvm *kvm,
> @@ -404,7 +406,7 @@ static unsigned long transparent_hugepage_adjust(struct kvm *kvm,
>          * sure that the HVA and GPA are sufficiently aligned and that the
>          * block map is contained within the memslot.
>          */
> -       if (fault_supports_gstage_huge_mapping(memslot, hva)) {
> +       if (fault_supports_gstage_huge_mapping(memslot, hva, PMD_SIZE)) {
>                 int sz;
>
>                 sz = get_hva_mapping_size(kvm, hva);
> --
> 2.43.0
>

Regards,
Anup



More information about the kvm-riscv mailing list