Skip to content

Commit 72324ac

Browse files
ryanhrobMarc Zyngier
authored andcommitted
KVM: selftests: arm64: Determine max ipa size per-page size
We are about to add 52 bit PA guest modes for 4K and 16K pages when the system supports LPA2. In preparation beef up the logic that parses mmfr0 to also tell us what the maximum supported PA size is for each page size. Max PA size = 0 implies the page size is not supported at all. Reviewed-by: Oliver Upton <oliver.upton@linux.dev> Signed-off-by: Ryan Roberts <ryan.roberts@arm.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20231127111737.1897081-12-ryan.roberts@arm.com
1 parent d782ac5 commit 72324ac

4 files changed

Lines changed: 50 additions & 36 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ enum {
119119
/* Access flag update enable/disable */
120120
#define TCR_EL1_HA (1ULL << 39)
121121

122-
void aarch64_get_supported_page_sizes(uint32_t ipa,
123-
bool *ps4k, bool *ps16k, bool *ps64k);
122+
void aarch64_get_supported_page_sizes(uint32_t ipa, uint32_t *ipa4k,
123+
uint32_t *ipa16k, uint32_t *ipa64k);
124124

125125
void vm_init_descriptor_tables(struct kvm_vm *vm);
126126
void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu);

tools/testing/selftests/kvm/include/guest_modes.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ struct guest_mode {
1111

1212
extern struct guest_mode guest_modes[NUM_VM_MODES];
1313

14-
#define guest_mode_append(mode, supported, enabled) ({ \
15-
guest_modes[mode] = (struct guest_mode){ supported, enabled }; \
14+
#define guest_mode_append(mode, enabled) ({ \
15+
guest_modes[mode] = (struct guest_mode){ (enabled), (enabled) }; \
1616
})
1717

1818
void guest_modes_append_default(void);

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

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -492,12 +492,24 @@ uint32_t guest_get_vcpuid(void)
492492
return read_sysreg(tpidr_el1);
493493
}
494494

495-
void aarch64_get_supported_page_sizes(uint32_t ipa,
496-
bool *ps4k, bool *ps16k, bool *ps64k)
495+
static uint32_t max_ipa_for_page_size(uint32_t vm_ipa, uint32_t gran,
496+
uint32_t not_sup_val, uint32_t ipa52_min_val)
497+
{
498+
if (gran == not_sup_val)
499+
return 0;
500+
else if (gran >= ipa52_min_val && vm_ipa >= 52)
501+
return 52;
502+
else
503+
return min(vm_ipa, 48U);
504+
}
505+
506+
void aarch64_get_supported_page_sizes(uint32_t ipa, uint32_t *ipa4k,
507+
uint32_t *ipa16k, uint32_t *ipa64k)
497508
{
498509
struct kvm_vcpu_init preferred_init;
499510
int kvm_fd, vm_fd, vcpu_fd, err;
500511
uint64_t val;
512+
uint32_t gran;
501513
struct kvm_one_reg reg = {
502514
.id = KVM_ARM64_SYS_REG(SYS_ID_AA64MMFR0_EL1),
503515
.addr = (uint64_t)&val,
@@ -518,9 +530,17 @@ void aarch64_get_supported_page_sizes(uint32_t ipa,
518530
err = ioctl(vcpu_fd, KVM_GET_ONE_REG, &reg);
519531
TEST_ASSERT(err == 0, KVM_IOCTL_ERROR(KVM_GET_ONE_REG, vcpu_fd));
520532

521-
*ps4k = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64MMFR0_EL1_TGRAN4), val) != 0xf;
522-
*ps64k = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64MMFR0_EL1_TGRAN64), val) == 0;
523-
*ps16k = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64MMFR0_EL1_TGRAN16), val) != 0;
533+
gran = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64MMFR0_EL1_TGRAN4), val);
534+
*ipa4k = max_ipa_for_page_size(ipa, gran, ID_AA64MMFR0_EL1_TGRAN4_NI,
535+
ID_AA64MMFR0_EL1_TGRAN4_52_BIT);
536+
537+
gran = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64MMFR0_EL1_TGRAN64), val);
538+
*ipa64k = max_ipa_for_page_size(ipa, gran, ID_AA64MMFR0_EL1_TGRAN64_NI,
539+
ID_AA64MMFR0_EL1_TGRAN64_IMP);
540+
541+
gran = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64MMFR0_EL1_TGRAN16), val);
542+
*ipa16k = max_ipa_for_page_size(ipa, gran, ID_AA64MMFR0_EL1_TGRAN16_NI,
543+
ID_AA64MMFR0_EL1_TGRAN16_52_BIT);
524544

525545
close(vcpu_fd);
526546
close(vm_fd);

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

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,31 @@ struct guest_mode guest_modes[NUM_VM_MODES];
1414
void guest_modes_append_default(void)
1515
{
1616
#ifndef __aarch64__
17-
guest_mode_append(VM_MODE_DEFAULT, true, true);
17+
guest_mode_append(VM_MODE_DEFAULT, true);
1818
#else
1919
{
2020
unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE);
21-
bool ps4k, ps16k, ps64k;
21+
uint32_t ipa4k, ipa16k, ipa64k;
2222
int i;
2323

24-
aarch64_get_supported_page_sizes(limit, &ps4k, &ps16k, &ps64k);
24+
aarch64_get_supported_page_sizes(limit, &ipa4k, &ipa16k, &ipa64k);
2525

26-
vm_mode_default = NUM_VM_MODES;
26+
guest_mode_append(VM_MODE_P52V48_64K, ipa64k >= 52);
2727

28-
if (limit >= 52)
29-
guest_mode_append(VM_MODE_P52V48_64K, ps64k, ps64k);
30-
if (limit >= 48) {
31-
guest_mode_append(VM_MODE_P48V48_4K, ps4k, ps4k);
32-
guest_mode_append(VM_MODE_P48V48_16K, ps16k, ps16k);
33-
guest_mode_append(VM_MODE_P48V48_64K, ps64k, ps64k);
34-
}
35-
if (limit >= 40) {
36-
guest_mode_append(VM_MODE_P40V48_4K, ps4k, ps4k);
37-
guest_mode_append(VM_MODE_P40V48_16K, ps16k, ps16k);
38-
guest_mode_append(VM_MODE_P40V48_64K, ps64k, ps64k);
39-
if (ps4k)
40-
vm_mode_default = VM_MODE_P40V48_4K;
41-
}
42-
if (limit >= 36) {
43-
guest_mode_append(VM_MODE_P36V48_4K, ps4k, ps4k);
44-
guest_mode_append(VM_MODE_P36V48_16K, ps16k, ps16k);
45-
guest_mode_append(VM_MODE_P36V48_64K, ps64k, ps64k);
46-
guest_mode_append(VM_MODE_P36V47_16K, ps16k, ps16k);
47-
}
28+
guest_mode_append(VM_MODE_P48V48_4K, ipa4k >= 48);
29+
guest_mode_append(VM_MODE_P48V48_16K, ipa16k >= 48);
30+
guest_mode_append(VM_MODE_P48V48_64K, ipa64k >= 48);
31+
32+
guest_mode_append(VM_MODE_P40V48_4K, ipa4k >= 40);
33+
guest_mode_append(VM_MODE_P40V48_16K, ipa16k >= 40);
34+
guest_mode_append(VM_MODE_P40V48_64K, ipa64k >= 40);
35+
36+
guest_mode_append(VM_MODE_P36V48_4K, ipa4k >= 36);
37+
guest_mode_append(VM_MODE_P36V48_16K, ipa16k >= 36);
38+
guest_mode_append(VM_MODE_P36V48_64K, ipa64k >= 36);
39+
guest_mode_append(VM_MODE_P36V47_16K, ipa16k >= 36);
40+
41+
vm_mode_default = ipa4k >= 40 ? VM_MODE_P40V48_4K : NUM_VM_MODES;
4842

4943
/*
5044
* Pick the first supported IPA size if the default
@@ -72,17 +66,17 @@ void guest_modes_append_default(void)
7266
close(kvm_fd);
7367
/* Starting with z13 we have 47bits of physical address */
7468
if (info.ibc >= 0x30)
75-
guest_mode_append(VM_MODE_P47V64_4K, true, true);
69+
guest_mode_append(VM_MODE_P47V64_4K, true);
7670
}
7771
#endif
7872
#ifdef __riscv
7973
{
8074
unsigned int sz = kvm_check_cap(KVM_CAP_VM_GPA_BITS);
8175

8276
if (sz >= 52)
83-
guest_mode_append(VM_MODE_P52V48_4K, true, true);
77+
guest_mode_append(VM_MODE_P52V48_4K, true);
8478
if (sz >= 48)
85-
guest_mode_append(VM_MODE_P48V48_4K, true, true);
79+
guest_mode_append(VM_MODE_P48V48_4K, true);
8680
}
8781
#endif
8882
}

0 commit comments

Comments
 (0)