On Thu, Jun 4, 2026 at 7:58 PM Jinyu Tang <[email protected]> wrote: > > kvm_page_table_test can already exercise hugetlb-backed guest memory, > but it always creates the test memslot with GPA alignment matching the > hugetlb backing size. That misses the case where a valid hugetlb > memslot is later moved so that the memslot GPA and HVA no longer have > the same offset within the backing huge page. > > Add a -u option that moves the test memslot GPA by one guest page after > creating the hugetlb memslot. The memslot is created through the normal > helper first, so the backing allocation remains valid and hugetlb aligned. > Moving the memslot then creates a deliberate HVA/GPA offset mismatch > before the guest mapping is installed. > > This mode is useful for checking that architecture MMUs do not install > a block mapping when the block would map the wrong host pages or cover > memory outside the memslot. The option is restricted to hugetlb-backed > test memory because it's specifically about hugetlb block mapping > eligibility. > > Signed-off-by: Jinyu Tang <[email protected]>
LGTM. Reviewed-by: Anup Patel <[email protected]> I did not observe any impact on the default usage without "-u" option hence queueing it for Linux-7.2 Thanks Anup > --- > v1 -> v2: > - Keep the selftest change unchanged from v1 > > .../selftests/kvm/kvm_page_table_test.c | 28 +++++++++++++++---- > 1 file changed, 22 insertions(+), 6 deletions(-) > > diff --git a/tools/testing/selftests/kvm/kvm_page_table_test.c > b/tools/testing/selftests/kvm/kvm_page_table_test.c > index fc5242fb9..a910e3abb 100644 > --- a/tools/testing/selftests/kvm/kvm_page_table_test.c > +++ b/tools/testing/selftests/kvm/kvm_page_table_test.c > @@ -230,6 +230,7 @@ struct test_params { > u64 phys_offset; > u64 test_mem_size; > enum vm_mem_backing_src_type src_type; > + bool misalign_slot_gpa; > }; > > static struct kvm_vm *pre_init_before_test(enum vm_guest_mode mode, void > *arg) > @@ -244,6 +245,7 @@ static struct kvm_vm *pre_init_before_test(enum > vm_guest_mode mode, void *arg) > u64 guest_num_pages; > u64 alignment; > void *host_test_mem; > + struct userspace_mem_region *region; > struct kvm_vm *vm; > > /* Align up the test memory size */ > @@ -276,13 +278,22 @@ static struct kvm_vm *pre_init_before_test(enum > vm_guest_mode mode, void *arg) > /* Add an extra memory slot with specified backing src type */ > vm_userspace_mem_region_add(vm, src_type, guest_test_phys_mem, > TEST_MEM_SLOT_INDEX, guest_num_pages, 0); > + region = memslot2region(vm, TEST_MEM_SLOT_INDEX); > + host_test_mem = region->host_mem; > + > + if (p->misalign_slot_gpa) { > + TEST_ASSERT(is_backing_src_hugetlb(src_type), > + "Memslot GPA misalignment requires hugetlb > backing"); > + TEST_ASSERT(guest_num_pages > 1, > + "Need at least two guest pages to misalign > memslot GPA"); > + > + guest_test_phys_mem += guest_page_size; > + vm_mem_region_move(vm, TEST_MEM_SLOT_INDEX, > guest_test_phys_mem); > + } > > /* Do mapping(GVA->GPA) for the testing memory slot */ > virt_map(vm, guest_test_virt_mem, guest_test_phys_mem, > guest_num_pages); > > - /* Cache the HVA pointer of the region */ > - host_test_mem = addr_gpa2hva(vm, (gpa_t)guest_test_phys_mem); > - > /* Export shared structure test_args to guest */ > sync_global_to_guest(vm, test_args); > > @@ -417,8 +428,8 @@ static void run_test(enum vm_guest_mode mode, void *arg) > static void help(char *name) > { > puts(""); > - printf("usage: %s [-h] [-p offset] [-m mode] " > - "[-b mem-size] [-v vcpus] [-s mem-type]\n", name); > + printf("usage: %s [-h] [-p offset] [-m mode] [-b mem-size]\n", name); > + printf(" [-v vcpus] [-s mem-type] [-u]\n"); > puts(""); > printf(" -p: specify guest physical test memory offset\n" > " Warning: a low offset can conflict with the loaded test > code.\n"); > @@ -428,6 +439,8 @@ static void help(char *name) > printf(" -v: specify the number of vCPUs to run\n" > " (default: 1)\n"); > backing_src_help("-s"); > + printf(" -u: move the test memslot GPA by one guest page after > creating\n" > + " the memslot, forcing a hugetlb HVA/GPA offset > mismatch\n"); > puts(""); > } > > @@ -442,7 +455,7 @@ int main(int argc, char *argv[]) > > guest_modes_append_default(); > > - while ((opt = getopt(argc, argv, "hp:m:b:v:s:")) != -1) { > + while ((opt = getopt(argc, argv, "hp:m:b:v:s:u")) != -1) { > switch (opt) { > case 'p': > p.phys_offset = strtoull(optarg, NULL, 0); > @@ -461,6 +474,9 @@ int main(int argc, char *argv[]) > case 's': > p.src_type = parse_backing_src_type(optarg); > break; > + case 'u': > + p.misalign_slot_gpa = true; > + break; > case 'h': > default: > help(argv[0]); > -- > 2.43.0 >

