[PATCH 4/5] KVM: selftests: arm64: Check for supported page sizes

Andrew Jones drjones at redhat.com
Thu Dec 23 08:26:29 PST 2021


On Thu, Dec 16, 2021 at 12:31:34PM +0000, Marc Zyngier wrote:
> Just as arm64 implemenations don't necessary support all IPA
> ranges, they don't  all support the same page sizes either. Fun.
> 
> Create a dummy VM to snapshot the page sizes supported by the
> host, and filter the supported modes.
> 
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> ---
>  tools/testing/selftests/kvm/lib/guest_modes.c | 51 ++++++++++++++++---
>  1 file changed, 45 insertions(+), 6 deletions(-)
> 
> diff --git a/tools/testing/selftests/kvm/lib/guest_modes.c b/tools/testing/selftests/kvm/lib/guest_modes.c
> index fadc99bac69c..8db9ea2c4032 100644
> --- a/tools/testing/selftests/kvm/lib/guest_modes.c
> +++ b/tools/testing/selftests/kvm/lib/guest_modes.c
> @@ -5,7 +5,42 @@
>  #include "guest_modes.h"
>  
>  #ifdef __aarch64__
> +#include "processor.h"
>  enum vm_guest_mode vm_mode_default;
> +static void get_supported_psz(uint32_t ipa,
> +			      bool *ps4k, bool *ps16k, bool *ps64k)
> +{
> +	struct kvm_vcpu_init preferred_init;
> +	int kvm_fd, vm_fd, vcpu_fd, err;
> +	uint64_t val;
> +	struct kvm_one_reg reg = {
> +		.id	= KVM_ARM64_SYS_REG(SYS_ID_AA64MMFR0_EL1),
> +		.addr	= (uint64_t)&val,
> +	};
> +
> +	kvm_fd = open_kvm_dev_path_or_exit();
> +	vm_fd = ioctl(kvm_fd, KVM_CREATE_VM, ipa);
> +	TEST_ASSERT(vm_fd >= 0, "Can't create VM");
> +
> +	vcpu_fd = ioctl(vm_fd, KVM_CREATE_VCPU, 0);
> +	TEST_ASSERT(vcpu_fd >= 0, "Can't create vcpu");
> +
> +	err = ioctl(vm_fd, KVM_ARM_PREFERRED_TARGET, &preferred_init);
> +	TEST_ASSERT(err == 0, "Can't get target");
> +	err = ioctl(vcpu_fd, KVM_ARM_VCPU_INIT, &preferred_init);
> +	TEST_ASSERT(err == 0, "Can't get init vcpu");
> +
> +	err = ioctl(vcpu_fd, KVM_GET_ONE_REG, &reg);
> +	TEST_ASSERT(err == 0, "Can't get MMFR0");
> +
> +	*ps4k = ((val >> 28) & 0xf) != 0xf;
> +	*ps64k = ((val >> 24) & 0xf) == 0;
> +	*ps16k = ((val >> 20) & 0xf) != 0;
> +
> +	close(vcpu_fd);
> +	close(vm_fd);
> +	close(kvm_fd);
> +}

I think I'd prefer stashing this function in lib/aarch64/processor.c and
naming it aarch64_get_supported_page_sizes.

>  #endif
>  
>  struct guest_mode guest_modes[NUM_VM_MODES];
> @@ -18,20 +53,24 @@ void guest_modes_append_default(void)
>  #ifdef __aarch64__
>  	{
>  		unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE);
> +		bool ps4k, ps16k, ps64k;
>  		int i;
>  
> +		get_supported_psz(limit, &ps4k, &ps16k, &ps64k);
> +
>  		vm_mode_default = NUM_VM_MODES;
>  
>  		if (limit >= 52)
> -			guest_mode_append(VM_MODE_P52V48_64K, true, true);
> +			guest_mode_append(VM_MODE_P52V48_64K, ps64k, ps64k);
>  		if (limit >= 48) {
> -			guest_mode_append(VM_MODE_P48V48_4K, true, true);
> -			guest_mode_append(VM_MODE_P48V48_64K, true, true);
> +			guest_mode_append(VM_MODE_P48V48_4K, ps4k, ps4k);
> +			guest_mode_append(VM_MODE_P48V48_64K, ps64k, ps64k);
>  		}
>  		if (limit >= 40) {
> -			guest_mode_append(VM_MODE_P40V48_4K, true, true);
> -			guest_mode_append(VM_MODE_P40V48_64K, true, true);
> -			vm_mode_default = VM_MODE_P40V48_4K;
> +			guest_mode_append(VM_MODE_P40V48_4K, ps4k, ps4k);
> +			guest_mode_append(VM_MODE_P40V48_64K, ps64k, ps64k);
> +			if (ps4k)
> +				vm_mode_default = VM_MODE_P40V48_4K;
>  		}
>  
>  		/* Pick the largest supported IPA size */
> -- 
> 2.30.2
>

Thanks,
drew 




More information about the linux-arm-kernel mailing list