[PATCH v2 12/20] KVM: selftests: Add APIs to override memory region types with custom memslots

Claudio Imbrenda imbrenda at linux.ibm.com
Thu Sep 10 03:27:56 PDT 2026


On Wed,  2 Sep 2026 09:41:15 -0700
Sean Christopherson <seanjc at google.com> wrote:

> Add and use APIs to override memory region types instead of open coding the
> logic in tests, partly to dedup test code, but mostly to add some amount of
> protection against conflicting overrides.  This will allow converting more
> tests to override memory regions without taking on too much risk of bugs in
> the long term, e.g. due to silently overriding a region multiple times.
> 
> Deliberately "unroll" the loops in __vm_create() and the CMMA test's
> create_main_memslot() to avoid filling all memslots in anticipation of
> adding an "extra" memslot that is for test use and *only* test use, i.e.
> shouldn't be configured by core library code.
> 
> Converting tests to overriding memory regions will allow taking the region
> type instead of the raw memslot in the physical page allocator APIs.
> 
> Tested-by: Itaru Kitayama <itaru.kitayama at fujitsu.com>
> Signed-off-by: Sean Christopherson <seanjc at google.com>

Acked-by: Claudio Imbrenda <imbrenda at linux.ibm.com>

> ---
>  .../selftests/kvm/arm64/page_fault_test.c     | 18 +++++------
>  .../testing/selftests/kvm/include/kvm_util.h  | 30 +++++++++++++++++++
>  tools/testing/selftests/kvm/lib/kvm_util.c    |  8 +++--
>  tools/testing/selftests/kvm/s390/cmma_test.c  | 19 ++++--------
>  4 files changed, 49 insertions(+), 26 deletions(-)
> 
> diff --git a/tools/testing/selftests/kvm/arm64/page_fault_test.c b/tools/testing/selftests/kvm/arm64/page_fault_test.c
> index 6bb3d82906b2..b0e3fc8cd76a 100644
> --- a/tools/testing/selftests/kvm/arm64/page_fault_test.c
> +++ b/tools/testing/selftests/kvm/arm64/page_fault_test.c
> @@ -597,18 +597,16 @@ static void setup_memslots(struct kvm_vm *vm, struct test_params *p)
>  
>  	vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 0,
>  				    CODE_AND_DATA_MEMSLOT, code_npages, 0);
> -	vm->memslots[MEM_REGION_CODE] = CODE_AND_DATA_MEMSLOT;
> -	vm->memslots[MEM_REGION_DATA] = CODE_AND_DATA_MEMSLOT;
> +	____vm_override_mem_region(vm, MEM_REGION_CODE, CODE_AND_DATA_MEMSLOT);
> +	____vm_override_mem_region(vm, MEM_REGION_DATA, CODE_AND_DATA_MEMSLOT);
>  
> -	vm_userspace_mem_region_add(vm, p->src_type, data_gpa - pt_size,
> -				    PAGE_TABLE_MEMSLOT, pt_size / guest_page_size,
> -				    p->test_desc->pt_memslot_flags);
> -	vm->memslots[MEM_REGION_PT] = PAGE_TABLE_MEMSLOT;
> +	__vm_override_mem_region(vm, MEM_REGION_PT, p->src_type, data_gpa - pt_size,
> +				 PAGE_TABLE_MEMSLOT, pt_size / guest_page_size,
> +				 p->test_desc->pt_memslot_flags);
>  
> -	vm_userspace_mem_region_add(vm, p->src_type, data_gpa, TEST_DATA_MEMSLOT,
> -				    data_size / guest_page_size,
> -				    p->test_desc->data_memslot_flags);
> -	vm->memslots[MEM_REGION_TEST_DATA] = TEST_DATA_MEMSLOT;
> +	__vm_override_mem_region(vm, MEM_REGION_TEST_DATA, p->src_type, data_gpa,
> +				 TEST_DATA_MEMSLOT, data_size / guest_page_size,
> +				 p->test_desc->data_memslot_flags);
>  }
>  
>  static void setup_ucall(struct kvm_vm *vm)
> diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
> index 304ef6af3268..c8faa8a02b93 100644
> --- a/tools/testing/selftests/kvm/include/kvm_util.h
> +++ b/tools/testing/selftests/kvm/include/kvm_util.h
> @@ -704,6 +704,36 @@ void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,
>  		gpa_t gpa, u32 slot, u64 npages, u32 flags,
>  		int guest_memfd_fd, u64 guest_memfd_offset);
>  
> +
> +static inline void ____vm_override_mem_region(struct kvm_vm *vm,
> +					      enum kvm_mem_region_type type,
> +					      u32 slot)
> +{
> +	TEST_ASSERT(vm->memslots[type] == KVM_INVALID_MEMSLOT,
> +		    "Memory region type '%u' was already overridden with slot=%u",
> +		    type, vm->memslots[type]);
> +
> +	vm->memslots[type] = slot;
> +}
> +
> +static inline void __vm_override_mem_region(struct kvm_vm *vm,
> +					    enum kvm_mem_region_type type,
> +					    enum vm_mem_backing_src_type src_type,
> +					    gpa_t gpa, u32 slot, u64 npages,
> +					    u32 flags)
> +{
> +	____vm_override_mem_region(vm, type, slot);
> +	vm_userspace_mem_region_add(vm, src_type, gpa, slot, npages, flags);
> +}
> +
> +static inline void vm_override_mem_region(struct kvm_vm *vm,
> +					  enum kvm_mem_region_type type,
> +					  enum vm_mem_backing_src_type src_type,
> +					  gpa_t gpa, u32 slot, u64 npages)
> +{
> +	__vm_override_mem_region(vm, type, src_type, gpa, slot, npages, 0);
> +}
> +
>  #ifndef vm_arch_has_protected_memory
>  static inline bool vm_arch_has_protected_memory(struct kvm_vm *vm)
>  {
> diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
> index 56df5b1d9c79..781af2928d04 100644
> --- a/tools/testing/selftests/kvm/lib/kvm_util.c
> +++ b/tools/testing/selftests/kvm/lib/kvm_util.c
> @@ -495,7 +495,7 @@ struct kvm_vm *__vm_create(struct vm_shape shape, u32 nr_runnable_vcpus,
>  						 nr_extra_pages);
>  	struct userspace_mem_region *slot0;
>  	struct kvm_vm *vm;
> -	int i, flags;
> +	int flags;
>  
>  	kvm_set_files_rlimit(nr_runnable_vcpus);
>  
> @@ -513,8 +513,10 @@ struct kvm_vm *__vm_create(struct vm_shape shape, u32 nr_runnable_vcpus,
>  		flags |= KVM_MEM_GUEST_MEMFD;
>  
>  	vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 0, 0, nr_pages, flags);
> -	for (i = 0; i < NR_MEM_REGIONS; i++)
> -		vm->memslots[i] = 0;
> +	____vm_override_mem_region(vm, MEM_REGION_CODE, 0);
> +	____vm_override_mem_region(vm, MEM_REGION_PT, 0);
> +	____vm_override_mem_region(vm, MEM_REGION_DATA, 0);
> +	____vm_override_mem_region(vm, MEM_REGION_TEST_DATA, 0);
>  
>  	kvm_vm_elf_load(vm, program_invocation_name);
>  
> diff --git a/tools/testing/selftests/kvm/s390/cmma_test.c b/tools/testing/selftests/kvm/s390/cmma_test.c
> index 15d81b2ed7ad..73387cc3bca7 100644
> --- a/tools/testing/selftests/kvm/s390/cmma_test.c
> +++ b/tools/testing/selftests/kvm/s390/cmma_test.c
> @@ -102,24 +102,17 @@ static void guest_dirty_test_data(void)
>  
>  static void create_main_memslot(struct kvm_vm *vm)
>  {
> -	int i;
> -
>  	vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 0, 0, MAIN_PAGE_COUNT, 0);
> -	/* set the array of memslots to zero like __vm_create does */
> -	for (i = 0; i < NR_MEM_REGIONS; i++)
> -		vm->memslots[i] = 0;
> +	____vm_override_mem_region(vm, MEM_REGION_CODE, 0);
> +	____vm_override_mem_region(vm, MEM_REGION_PT, 0);
> +	____vm_override_mem_region(vm, MEM_REGION_DATA, 0);
>  }
>  
>  static void create_test_memslot(struct kvm_vm *vm)
>  {
> -	vm_userspace_mem_region_add(vm,
> -				    VM_MEM_SRC_ANONYMOUS,
> -				    TEST_DATA_START_GFN << vm->page_shift,
> -				    TEST_DATA_MEMSLOT,
> -				    TEST_DATA_PAGE_COUNT,
> -				    0
> -				   );
> -	vm->memslots[MEM_REGION_TEST_DATA] = TEST_DATA_MEMSLOT;
> +	vm_override_mem_region(vm, MEM_REGION_TEST_DATA, VM_MEM_SRC_ANONYMOUS,
> +			       TEST_DATA_START_GFN << vm->page_shift,
> +			       TEST_DATA_MEMSLOT, TEST_DATA_PAGE_COUNT);
>  }
>  
>  static void create_memslots(struct kvm_vm *vm)




More information about the linux-arm-kernel mailing list