Skip to content

Commit 0303ffd

Browse files
author
Marc Zyngier
committed
KVM: selftests: arm64: Check for supported page sizes
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 <[email protected]> Reviewed-by: Andrew Jones <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 357c628 commit 0303ffd

File tree

3 files changed

+50
-6
lines changed

3 files changed

+50
-6
lines changed

tools/testing/selftests/kvm/include/aarch64/processor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ enum {
113113
#define ESR_EC_WP_CURRENT 0x35
114114
#define ESR_EC_BRK_INS 0x3c
115115

116+
void aarch64_get_supported_page_sizes(uint32_t ipa,
117+
bool *ps4k, bool *ps16k, bool *ps64k);
118+
116119
void vm_init_descriptor_tables(struct kvm_vm *vm);
117120
void vcpu_init_descriptor_tables(struct kvm_vm *vm, uint32_t vcpuid);
118121

tools/testing/selftests/kvm/lib/aarch64/processor.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/compiler.h>
99
#include <assert.h>
1010

11+
#include "guest_modes.h"
1112
#include "kvm_util.h"
1213
#include "../kvm_util_internal.h"
1314
#include "processor.h"
@@ -433,6 +434,41 @@ uint32_t guest_get_vcpuid(void)
433434
return read_sysreg(tpidr_el1);
434435
}
435436

437+
void aarch64_get_supported_page_sizes(uint32_t ipa,
438+
bool *ps4k, bool *ps16k, bool *ps64k)
439+
{
440+
struct kvm_vcpu_init preferred_init;
441+
int kvm_fd, vm_fd, vcpu_fd, err;
442+
uint64_t val;
443+
struct kvm_one_reg reg = {
444+
.id = KVM_ARM64_SYS_REG(SYS_ID_AA64MMFR0_EL1),
445+
.addr = (uint64_t)&val,
446+
};
447+
448+
kvm_fd = open_kvm_dev_path_or_exit();
449+
vm_fd = ioctl(kvm_fd, KVM_CREATE_VM, ipa);
450+
TEST_ASSERT(vm_fd >= 0, "Can't create VM");
451+
452+
vcpu_fd = ioctl(vm_fd, KVM_CREATE_VCPU, 0);
453+
TEST_ASSERT(vcpu_fd >= 0, "Can't create vcpu");
454+
455+
err = ioctl(vm_fd, KVM_ARM_PREFERRED_TARGET, &preferred_init);
456+
TEST_ASSERT(err == 0, "Can't get target");
457+
err = ioctl(vcpu_fd, KVM_ARM_VCPU_INIT, &preferred_init);
458+
TEST_ASSERT(err == 0, "Can't get init vcpu");
459+
460+
err = ioctl(vcpu_fd, KVM_GET_ONE_REG, &reg);
461+
TEST_ASSERT(err == 0, "Can't get MMFR0");
462+
463+
*ps4k = ((val >> 28) & 0xf) != 0xf;
464+
*ps64k = ((val >> 24) & 0xf) == 0;
465+
*ps16k = ((val >> 20) & 0xf) != 0;
466+
467+
close(vcpu_fd);
468+
close(vm_fd);
469+
close(kvm_fd);
470+
}
471+
436472
/*
437473
* arm64 doesn't have a true default mode, so start by computing the
438474
* available IPA space and page sizes early.

tools/testing/selftests/kvm/lib/guest_modes.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "guest_modes.h"
66

77
#ifdef __aarch64__
8+
#include "processor.h"
89
enum vm_guest_mode vm_mode_default;
910
#endif
1011

@@ -17,20 +18,24 @@ void guest_modes_append_default(void)
1718
#else
1819
{
1920
unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE);
21+
bool ps4k, ps16k, ps64k;
2022
int i;
2123

24+
aarch64_get_supported_page_sizes(limit, &ps4k, &ps16k, &ps64k);
25+
2226
vm_mode_default = NUM_VM_MODES;
2327

2428
if (limit >= 52)
25-
guest_mode_append(VM_MODE_P52V48_64K, true, true);
29+
guest_mode_append(VM_MODE_P52V48_64K, ps64k, ps64k);
2630
if (limit >= 48) {
27-
guest_mode_append(VM_MODE_P48V48_4K, true, true);
28-
guest_mode_append(VM_MODE_P48V48_64K, true, true);
31+
guest_mode_append(VM_MODE_P48V48_4K, ps4k, ps4k);
32+
guest_mode_append(VM_MODE_P48V48_64K, ps64k, ps64k);
2933
}
3034
if (limit >= 40) {
31-
guest_mode_append(VM_MODE_P40V48_4K, true, true);
32-
guest_mode_append(VM_MODE_P40V48_64K, true, true);
33-
vm_mode_default = VM_MODE_P40V48_4K;
35+
guest_mode_append(VM_MODE_P40V48_4K, ps4k, ps4k);
36+
guest_mode_append(VM_MODE_P40V48_64K, ps64k, ps64k);
37+
if (ps4k)
38+
vm_mode_default = VM_MODE_P40V48_4K;
3439
}
3540

3641
/*

0 commit comments

Comments
 (0)