KVM: arm64: Selftest IPA fixes and 16kB support
Marc Zyngier
maintainerv2 cover KVM: arm64: Selftest IPA fixes and 16kB support
Now that the common variety of fruity arm64 systems makes a pretty remarkable KVM host, I have decided to run the collection of selftests on it.
Nothing works. Oh no!
As it turns out, the tests have a notion of "default mode" (40bit PA, 4kB), which cannot work in general on arm64 because there no such thing as an IPA size that would be valid everywhere (apart from the minimal 32bit), nor a guaranteed to be supported page size.
This small series is a first attempt at making these things computed at runtime by making the default something else on systems that do not support it. It also makes the supported page sizes dynamically discovered, which allows us to implement support for 16kB pages.
With that, the selftests do run on the M1, with the exception of the memslot tests that are freaked out by the use of 16kB pages on the host and 4kB in the guest (these tests are hardcoded to use 4kB pages even if the VM uses something else -- oh well...).
* From v1:
- Rebased on 5.16-rc7 and dropped the initial patch, now that non-x86 systems are up and running again
- Used Andrew's trick to initialise the default mode as a constructor instead of hacking every single test (I decided to make it an arm64-special instead of an all-arch thing though)
- Reworked the way TCR_EL1 gets configured for easier integration of new modes
- Added support for various 16kB modes
- Various cleanups as requested by Andrew
Marc Zyngier (6):
KVM: selftests: arm64: Initialise default guest mode at test startup
time
KVM: selftests: arm64: Introduce a variable default IPA size
KVM: selftests: arm64: Check for supported page sizes
KVM: selftests: arm64: Rework TCR_EL1 configuration
KVM: selftests: arm64: Add support for VM_MODE_P36V48_{4K,64K}
KVM: selftests: arm64: Add support for various modes with 16kB page
size
.../selftests/kvm/include/aarch64/processor.h | 3 + .../testing/selftests/kvm/include/kvm_util.h | 10 ++- .../selftests/kvm/lib/aarch64/processor.c | 82 +++++++++++++++++-- tools/testing/selftests/kvm/lib/guest_modes.c | 49 +++++++++-- tools/testing/selftests/kvm/lib/kvm_util.c | 22 +++++ 5 files changed, 152 insertions(+), 14 deletions(-)
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerPATCH v2 1/6 KVM: selftests: arm64: Initialise default guest mode at test startup time
As we are going to add support for a variable default mode on arm64, let's make sure it is setup first by using a constructor that gets called before the actual test runs.
--- tools/testing/selftests/kvm/lib/aarch64/processor.c | 9 +++++++++ 1 file changed, 9 insertions(+)
tools/testing/selftests/kvm/lib/aarch64/processor.c +9 -0
@@ -432,3 +432,12 @@ uint32_t guest_get_vcpuid(void) {return read_sysreg (tpidr_el1); } + +/* +* arm64 doesn't have a true default mode, so start by computing the +* available IPA space and page sizes early. +*/ +void __attribute__((constructor))init_guest_modes (void ) +{ +guest_modes_append_default (); +}
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [PATCH v2 1/6] KVM: selftests: arm64: Initialise default guest mode at test startup time
Quoted 30 lines · Marc Zyngier
As we are going to add support for a variable default mode on arm64, let's make sure it is setup first by using a constructor that gets called before the actual test runs.
Suggested-by Andrew Jones <[email protected]>Signed-off-by Marc Zyngier <[email protected]>--- tools/testing/selftests/kvm/lib/aarch64/processor.c | 9 +++++++++ 1 file changed, 9 insertions(+)tools/testing/selftests/kvm/lib/aarch64/processor.c +9
-0@@ -432,3 +432,12 @@ uint32_t guest_get_vcpuid(void) {return read_sysreg (tpidr_el1); } + +/* +* arm64 doesn't have a true default mode, so start by computing the +* available IPA space and page sizes early. +*/ +void __attribute__((constructor))init_guest_modes (void ) +{ +guest_modes_append_default (); +}Signature · 1 line
2.30.2
Marc Zyngier
maintainerPATCH v2 2/6 KVM: selftests: arm64: Introduce a variable default IPA size
In reply to Marc ZyngierContrary to popular belief, there is no such thing as a default IPA size on arm64. Anything goes, and implementations are the usual Wild West.
The selftest infrastructure default to 40bit IPA, which obviously doesn't work for some systems out there.
Turn VM_MODE_DEFAULT from a constant into a variable, and let guest_modes_append_default() populate it, depending on what the HW can do. In order to preserve the current behaviour, we still pick 40bits IPA as the default if it is available, and the largest supported IPA space otherwise.
--- .../testing/selftests/kvm/include/kvm_util.h | 4 ++- tools/testing/selftests/kvm/lib/guest_modes.c | 30 +++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-)
tools/testing/selftests/kvm/include/kvm_util.h +3 -1
@@ -53,7 +53,9 @@ enum vm_guest_mode {#if defined(__aarch64__) -#define VM_MODE_DEFAULT VM_MODE_P40V48_4K +extern enum vm_guest_mode vm_mode_default; + +#define VM_MODE_DEFAULT vm_mode_default#define MIN_PAGE_SHIFT 12U#define ptes_per_page (page_size) ((page_size) / 8)
tools/testing/selftests/kvm/lib/guest_modes.c +27 -3
@@ -4,22 +4,46 @@*/ #include "guest_modes.h" +#ifdef __aarch64__ +enum vm_guest_mode vm_mode_default; +#endif +struct guest_mode guest_modes[NUM_VM_MODES ];void guest_modes_append_default (void ) { +#ifndef __aarch64__guest_mode_append (VM_MODE_DEFAULT , true, true); - -#ifdef __aarch64__ -guest_mode_append (VM_MODE_P40V48_64K , true, true); +#else {unsigned int limit =kvm_check_cap (KVM_CAP_ARM_VM_IPA_SIZE ); +int i; + + vm_mode_default =NUM_VM_MODES ; +if (limit >=52 )guest_mode_append (VM_MODE_P52V48_64K , true, true);if (limit >=48 ) {guest_mode_append (VM_MODE_P48V48_4K , true, true);guest_mode_append (VM_MODE_P48V48_64K , true, true); } +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 ; + } + +/* +* Pick the first supported IPA size if the default +* isn't available. +*/ +for (i =0 ; vm_mode_default ==NUM_VM_MODES && i <NUM_VM_MODES ; i++) { +if (guest_modes[i].supported && guest_modes[i].enabled) + vm_mode_default = i; + } + +TEST_ASSERT (vm_mode_default !=NUM_VM_MODES , +"No supported mode!" ); }#endif #ifdef __s390x__
Signature · 1 line
2.30.2
Re: [PATCH v2 2/6] KVM: selftests: arm64: Introduce a variable default IPA size
Quoted 71 lines · Marc Zyngier
Contrary to popular belief, there is no such thing as a default IPA size on arm64. Anything goes, and implementations are the usual Wild West.
The selftest infrastructure default to 40bit IPA, which obviously doesn't work for some systems out there.
Turn
VM_MODE_DEFAULTfrom a constant into a variable, and letguest_modes_append_default()populate it, depending on what the HW can do. In order to preserve the current behaviour, we still pick 40bits IPA as the default if it is available, and the largest supported IPA space otherwise.Signed-off-by Marc Zyngier <[email protected]>--- .../testing/selftests/kvm/include/kvm_util.h | 4 ++- tools/testing/selftests/kvm/lib/guest_modes.c | 30 +++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-)tools/testing/selftests/kvm/include/kvm_util.h +3
-1@@ -53,7 +53,9 @@ enum vm_guest_mode {#if defined(__aarch64__) -#define VM_MODE_DEFAULT VM_MODE_P40V48_4K +extern enum vm_guest_mode vm_mode_default; + +#define VM_MODE_DEFAULT vm_mode_default#define MIN_PAGE_SHIFT 12U#define ptes_per_page (page_size) ((page_size) / 8)tools/testing/selftests/kvm/lib/guest_modes.c +13
-3@@ -4,22 +4,46 @@*/ #include "guest_modes.h" +#ifdef __aarch64__ +enum vm_guest_mode vm_mode_default; +#endif +struct guest_mode guest_modes[NUM_VM_MODES ];void guest_modes_append_default (void ) { +#ifndef __aarch64__guest_mode_append (VM_MODE_DEFAULT , true, true); - -#ifdef __aarch64__ -guest_mode_append (VM_MODE_P40V48_64K , true, true); +#else {unsigned int limit =kvm_check_cap (KVM_CAP_ARM_VM_IPA_SIZE ); +int i; + + vm_mode_default =NUM_VM_MODES ; +if (limit >=52 )guest_mode_append (VM_MODE_P52V48_64K , true, true);if (limit >=48 ) {guest_mode_append (VM_MODE_P48V48_4K , true, true);guest_mode_append (VM_MODE_P48V48_64K , true, true); } +if (limit >=40 ) { +guest_mode_append (VM_MODE_P40V48_4K , true, true); +guest_mode_append (VM_MODE_P40V48_64K , true, true);
tools/testing/selftests/kvm/lib/guest_modes.c line 42
Quoted 10 lines
tools/testing/selftests/kvm/lib/guest_modes.c +10
-0+ vm_mode_default =VM_MODE_P40V48_4K ; + } + +/* +* Pick the first supported IPA size if the default +* isn't available. +*/ +for (i =0 ; vm_mode_default ==NUM_VM_MODES && i <NUM_VM_MODES ; i++) { +if (guest_modes[i].supported && guest_modes[i].enabled) + vm_mode_default = i;
Since we don't have a 'break' here, this picks the last supported size (of the guest_modes list), not the first, as the comment implies it should do.
Thanks,
drew
Quoted 10 lines
tools/testing/selftests/kvm/lib/guest_modes.c +4
-0+ } + +TEST_ASSERT (vm_mode_default !=NUM_VM_MODES , +"No supported mode!" ); }#endif #ifdef __s390x__Signature · 1 line
2.30.2
Marc Zyngier
maintainerRe: [PATCH v2 2/6] KVM: selftests: arm64: Introduce a variable default IPA size
Quoted 79 lines · Andrew Jones
Quoted 77 lines · Marc Zyngier
Contrary to popular belief, there is no such thing as a default IPA size on arm64. Anything goes, and implementations are the usual Wild West.
The selftest infrastructure default to 40bit IPA, which obviously doesn't work for some systems out there.
Turn
VM_MODE_DEFAULTfrom a constant into a variable, and letguest_modes_append_default()populate it, depending on what the HW can do. In order to preserve the current behaviour, we still pick 40bits IPA as the default if it is available, and the largest supported IPA space otherwise.Signed-off-by Marc Zyngier <[email protected]>--- .../testing/selftests/kvm/include/kvm_util.h | 4 ++- tools/testing/selftests/kvm/lib/guest_modes.c | 30 +++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-)tools/testing/selftests/kvm/include/kvm_util.h +3
-1@@ -53,7 +53,9 @@ enum vm_guest_mode {#if defined(__aarch64__) -#define VM_MODE_DEFAULT VM_MODE_P40V48_4K +extern enum vm_guest_mode vm_mode_default; + +#define VM_MODE_DEFAULT vm_mode_default#define MIN_PAGE_SHIFT 12U#define ptes_per_page (page_size) ((page_size) / 8)tools/testing/selftests/kvm/lib/guest_modes.c +19
-3@@ -4,22 +4,46 @@*/ #include "guest_modes.h" +#ifdef __aarch64__ +enum vm_guest_mode vm_mode_default; +#endif +struct guest_mode guest_modes[NUM_VM_MODES ];void guest_modes_append_default (void ) { +#ifndef __aarch64__guest_mode_append (VM_MODE_DEFAULT , true, true); - -#ifdef __aarch64__ -guest_mode_append (VM_MODE_P40V48_64K , true, true); +#else {unsigned int limit =kvm_check_cap (KVM_CAP_ARM_VM_IPA_SIZE ); +int i; + + vm_mode_default =NUM_VM_MODES ; +if (limit >=52 )guest_mode_append (VM_MODE_P52V48_64K , true, true);if (limit >=48 ) {guest_mode_append (VM_MODE_P48V48_4K , true, true);guest_mode_append (VM_MODE_P48V48_64K , true, true); } +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 ; + } + +/* +* Pick the first supported IPA size if the default +* isn't available.
Quoted 8 lines
tools/testing/selftests/kvm/lib/guest_modes.c line 42
Quoted 4 lines
tools/testing/selftests/kvm/lib/guest_modes.c +4
-0+*/ +for (i =0 ; vm_mode_default ==NUM_VM_MODES && i <NUM_VM_MODES ; i++) { +if (guest_modes[i].supported && guest_modes[i].enabled) + vm_mode_default = i;Since we don't have a 'break' here, this picks the last supported size (of the
guest_modeslist), not the first, as the comment implies it should do.
This is checked in the for() loop condition, and the first matching mode will cause the loop to terminate. This is the same check that avoids scanning for a mode when VM_MODE_P40V48_4K is selected.
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Andrew Jones
Reviewed-byRe: [PATCH v2 2/6] KVM: selftests: arm64: Introduce a variable default IPA size
Quoted 8 lines · Marc Zyngier
Quoted 7 lines
tools/testing/selftests/kvm/lib/guest_modes.c line 42
Quoted 3 lines
tools/testing/selftests/kvm/lib/guest_modes.c +3
-0+for (i =0 ; vm_mode_default ==NUM_VM_MODES && i <NUM_VM_MODES ; i++) { +if (guest_modes[i].supported && guest_modes[i].enabled) + vm_mode_default = i;Since we don't have a 'break' here, this picks the last supported size (of the
guest_modeslist), not the first, as the comment implies it should do.
Quoted 4 lines
This is checked in the
for()loop condition, and the first matching mode will cause the loop to terminate. This is the same check that avoids scanning for a mode whenVM_MODE_P40V48_4Kis selected.
Ah, of course, sorry for the noise.
Marc Zyngier
maintainerPATCH v2 3/6 KVM: selftests: arm64: Check for supported page sizes
In reply to Marc ZyngierJust 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.
--- .../selftests/kvm/include/aarch64/processor.h | 3 ++ .../selftests/kvm/lib/aarch64/processor.c | 36 +++++++++++++++++++ tools/testing/selftests/kvm/lib/guest_modes.c | 17 +++++---- 3 files changed, 50 insertions(+), 6 deletions(-)
tools/testing/selftests/kvm/include/aarch64/processor.h +3 -0
@@ -113,6 +113,9 @@ enum {#define ESR_EC_WP_CURRENT 0x35#define ESR_EC_BRK_INS 0x3c +void aarch64_get_supported_page_sizes (uint32_t ipa, +bool *ps4k,bool *ps16k,bool *ps64k); +void vm_init_descriptor_tables (struct kvm_vm *vm);void vcpu_init_descriptor_tables (struct kvm_vm *vm,uint32_t vcpuid);
tools/testing/selftests/kvm/lib/aarch64/processor.c +36 -0
@@ -8,6 +8,7 @@#include <linux/compiler.h> #include <assert.h> +#include "guest_modes.h" #include "kvm_util.h" #include "../kvm_util_internal.h" #include "processor.h"
@@ -433,6 +434,41 @@ uint32_t guest_get_vcpuid(void)return read_sysreg (tpidr_el1); } +void aarch64_get_supported_page_sizes (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 , ®); +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); +} +/* * arm64 doesn't have a true default mode, so start by computing the * available IPA space and page sizes early.
tools/testing/selftests/kvm/lib/guest_modes.c +11 -6
@@ -5,6 +5,7 @@#include "guest_modes.h" #ifdef __aarch64__ +#include "processor.h" enum vm_guest_mode vm_mode_default;#endif
@@ -17,20 +18,24 @@ void guest_modes_append_default(void)#else {unsigned int limit =kvm_check_cap (KVM_CAP_ARM_VM_IPA_SIZE ); +bool ps4k, ps16k, ps64k;int i; +aarch64_get_supported_page_sizes (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 ; }/*
Signature · 1 line
2.30.2
Re: [PATCH v2 3/6] KVM: selftests: arm64: Check for supported page sizes
Quoted 6 lines · Marc Zyngier
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.
Quoted 7 lines
Signed-off-by Marc Zyngier <[email protected]>--- .../selftests/kvm/include/aarch64/processor.h | 3 ++ .../selftests/kvm/lib/aarch64/processor.c | 36 +++++++++++++++++++ tools/testing/selftests/kvm/lib/guest_modes.c | 17 +++++---- 3 files changed, 50 insertions(+), 6 deletions(-)
Marc Zyngier
maintainerPATCH v2 4/6 KVM: selftests: arm64: Rework TCR_EL1 configuration
In reply to Marc ZyngierThe current way we initialise TCR_EL1 is a bit cumbersome, as we mix setting TG0 and IPS in the same swtch statement.
Split it into two statements (one for the base granule size, and another for the IPA size), allowing new modes to be added in a more elegant way.
No functional change intended.
--- .../selftests/kvm/lib/aarch64/processor.c | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
tools/testing/selftests/kvm/lib/aarch64/processor.c +14 -7
@@ -238,6 +238,7 @@ void aarch64_vcpu_setup(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_vcpu_initget_reg (vm, vcpuid,KVM_ARM64_SYS_REG (SYS_SCTLR_EL1 ), &sctlr_el1);get_reg (vm, vcpuid,KVM_ARM64_SYS_REG (SYS_TCR_EL1 ), &tcr_el1); +/* Configure base granule size */ switch (vm->mode) {case VM_MODE_P52V48_4K : TEST_FAIL("AArch64 does not support 4K sized pages "
@@ -246,23 +247,29 @@ void aarch64_vcpu_setup(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_vcpu_initTEST_FAIL ("AArch64 does not support 4K sized pages " "with ANY-bit physical address ranges" );case VM_MODE_P52V48_64K : +case VM_MODE_P48V48_64K : +case VM_MODE_P40V48_64K : tcr_el1 |=1ul <<14 ;/* TG0 = 64KB */ - tcr_el1 |=6ul <<32 ;/* IPS = 52 bits */ break ;case VM_MODE_P48V48_4K : +case VM_MODE_P40V48_4K : tcr_el1 |=0ul <<14 ;/* TG0 = 4KB */ - tcr_el1 |=5ul <<32 ;/* IPS = 48 bits */ break ; +default : +TEST_FAIL ("Unknown guest mode, mode: 0x%x" , vm->mode); + } + +/* Configure output size */ +switch (vm->mode) { +case VM_MODE_P52V48_64K : + tcr_el1 |=6ul <<32 ;/* IPS = 52 bits */ +break ; +case VM_MODE_P48V48_4K :case VM_MODE_P48V48_64K : - tcr_el1 |=1ul <<14 ;/* TG0 = 64KB */ tcr_el1 |=5ul <<32 ;/* IPS = 48 bits */ break ;case VM_MODE_P40V48_4K : - tcr_el1 |=0ul <<14 ;/* TG0 = 4KB */ - tcr_el1 |=2ul <<32 ;/* IPS = 40 bits */ -break ;case VM_MODE_P40V48_64K : - tcr_el1 |=1ul <<14 ;/* TG0 = 64KB */ tcr_el1 |=2ul <<32 ;/* IPS = 40 bits */ break ;default :
Signature · 1 line
2.30.2
Re: [PATCH v2 4/6] KVM: selftests: arm64: Rework TCR_EL1 configuration
Quoted 7 lines · Marc Zyngier
The current way we initialise
TCR_EL1is a bit cumbersome, as we mix setting TG0 and IPS in the same swtch statement.Split it into two statements (one for the base granule size, and another for the IPA size), allowing new modes to be added in a more elegant way.
Quoted 7 lines
No functional change intended.
Signed-off-by Marc Zyngier <[email protected]>--- .../selftests/kvm/lib/aarch64/processor.c | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
Marc Zyngier
maintainerPATCH v2 5/6 KVM: selftests: arm64: Add support for VM_MODE_P36V48_{4K,64K}
In reply to Marc ZyngierSome of the arm64 systems out there have an IPA space that is positively tiny. Nonetheless, they make great KVM hosts.
Add support for 36bit IPA support with 4kB pages, which makes some of the fruity machines happy. Whilst we're at it, add support for 64kB pages as well, though these boxes have no support for it.
--- tools/testing/selftests/kvm/include/kvm_util.h | 2 ++ tools/testing/selftests/kvm/lib/aarch64/processor.c | 6 ++++++ tools/testing/selftests/kvm/lib/guest_modes.c | 4 ++++ tools/testing/selftests/kvm/lib/kvm_util.c | 6 ++++++ 4 files changed, 18 insertions(+)
tools/testing/selftests/kvm/include/kvm_util.h +2 -0
@@ -48,6 +48,8 @@ enum vm_guest_mode {VM_MODE_PXXV48_4K ,/* For 48bits VA but ANY bits PA */ VM_MODE_P47V64_4K ,VM_MODE_P44V64_4K , +VM_MODE_P36V48_4K , +VM_MODE_P36V48_64K , NUM_VM_MODES, };
tools/testing/selftests/kvm/lib/aarch64/processor.c +6 -0
@@ -249,10 +249,12 @@ void aarch64_vcpu_setup(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_vcpu_initcase VM_MODE_P52V48_64K :case VM_MODE_P48V48_64K :case VM_MODE_P40V48_64K : +case VM_MODE_P36V48_64K : tcr_el1 |=1ul <<14 ;/* TG0 = 64KB */ break ;case VM_MODE_P48V48_4K :case VM_MODE_P40V48_4K : +case VM_MODE_P36V48_4K : tcr_el1 |=0ul <<14 ;/* TG0 = 4KB */ break ;default :
@@ -272,6 +274,10 @@ void aarch64_vcpu_setup(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_vcpu_initcase VM_MODE_P40V48_64K : tcr_el1 |=2ul <<32 ;/* IPS = 40 bits */ break ; +case VM_MODE_P36V48_4K : +case VM_MODE_P36V48_64K : + tcr_el1 |=1ul <<32 ;/* IPS = 36 bits */ +break ;default :TEST_FAIL ("Unknown guest mode, mode: 0x%x" , vm->mode); }
tools/testing/selftests/kvm/lib/guest_modes.c +4 -0
@@ -37,6 +37,10 @@ void guest_modes_append_default(void)if (ps4k) vm_mode_default =VM_MODE_P40V48_4K ; } +if (limit >=36 ) { +guest_mode_append (VM_MODE_P36V48_4K , ps4k, ps4k); +guest_mode_append (VM_MODE_P36V48_64K , ps64k, ps64k); + }/* * Pick the first supported IPA size if the default
tools/testing/selftests/kvm/lib/kvm_util.c +6 -0
@@ -172,6 +172,8 @@ const char *vm_guest_mode_string(uint32_t i) [VM_MODE_PXXV48_4K] = "PA-bits:ANY, VA-bits:48, 4K pages", [VM_MODE_P47V64_4K] = "PA-bits:47, VA-bits:64, 4K pages", [VM_MODE_P44V64_4K] = "PA-bits:44, VA-bits:64, 4K pages", + [VM_MODE_P36V48_4K] = "PA-bits:36, VA-bits:48, 4K pages", + [VM_MODE_P36V48_64K ] ="PA-bits:36, VA-bits:48, 64K pages" , };_Static_assert (sizeof (strings)/sizeof (char *) ==NUM_VM_MODES ,"Missing new mode strings?" );
@@ -191,6 +193,8 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = { [VM_MODE_PXXV48_4K] = { 0, 0, 0x1000, 12 }, [VM_MODE_P47V64_4K] = { 47, 64, 0x1000, 12 }, [VM_MODE_P44V64_4K] = { 44, 64, 0x1000, 12 }, + [VM_MODE_P36V48_4K] = { 36, 48, 0x1000, 12 }, + [VM_MODE_P36V48_64K] = { 36, 48, 0x10000, 16 }, };_Static_assert (sizeof (vm_guest_mode_params)/sizeof (struct vm_guest_mode_params ) ==NUM_VM_MODES ,"Missing new mode params?" );
@@ -252,9 +256,11 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm) vm->pgtable_levels =3 ;break ;case VM_MODE_P40V48_4K : +case VM_MODE_P36V48_4K : vm->pgtable_levels =4 ;break ;case VM_MODE_P40V48_64K : +case VM_MODE_P36V48_64K : vm->pgtable_levels =3 ;break ;case VM_MODE_PXXV48_4K :
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerPATCH v2 6/6 KVM: selftests: arm64: Add support for various modes with 16kB page size
In reply to Marc ZyngierThe 16kB page size is not a popular choice, due to only a few CPUs actually implementing support for it. However, it can lead to some interesting performance improvements given the right uarch choices.
Add support for this page size for various PA/VA combinations.
--- tools/testing/selftests/kvm/include/kvm_util.h | 4 ++++ .../selftests/kvm/lib/aarch64/processor.c | 10 ++++++++++ tools/testing/selftests/kvm/lib/guest_modes.c | 4 ++++ tools/testing/selftests/kvm/lib/kvm_util.c | 16 ++++++++++++++++ 4 files changed, 34 insertions(+)
tools/testing/selftests/kvm/include/kvm_util.h +4 -0
@@ -42,14 +42,18 @@ enum vm_guest_mode {VM_MODE_P52V48_4K ,VM_MODE_P52V48_64K ,VM_MODE_P48V48_4K , +VM_MODE_P48V48_16K ,VM_MODE_P48V48_64K ,VM_MODE_P40V48_4K , +VM_MODE_P40V48_16K ,VM_MODE_P40V48_64K ,VM_MODE_PXXV48_4K ,/* For 48bits VA but ANY bits PA */ VM_MODE_P47V64_4K ,VM_MODE_P44V64_4K ,VM_MODE_P36V48_4K , +VM_MODE_P36V48_16K ,VM_MODE_P36V48_64K , +VM_MODE_P36V47_16K , NUM_VM_MODES, };
tools/testing/selftests/kvm/lib/aarch64/processor.c +10 -0
@@ -252,6 +252,12 @@ void aarch64_vcpu_setup(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_vcpu_initcase VM_MODE_P36V48_64K : tcr_el1 |=1ul <<14 ;/* TG0 = 64KB */ break ; +case VM_MODE_P48V48_16K : +case VM_MODE_P40V48_16K : +case VM_MODE_P36V48_16K : +case VM_MODE_P36V47_16K : + tcr_el1 |=2ul <<14 ;/* TG0 = 16KB */ +break ;case VM_MODE_P48V48_4K :case VM_MODE_P40V48_4K :case VM_MODE_P36V48_4K :
@@ -267,15 +273,19 @@ void aarch64_vcpu_setup(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_vcpu_init tcr_el1 |=6ul <<32 ;/* IPS = 52 bits */ break ;case VM_MODE_P48V48_4K : +case VM_MODE_P48V48_16K :case VM_MODE_P48V48_64K : tcr_el1 |=5ul <<32 ;/* IPS = 48 bits */ break ;case VM_MODE_P40V48_4K : +case VM_MODE_P40V48_16K :case VM_MODE_P40V48_64K : tcr_el1 |=2ul <<32 ;/* IPS = 40 bits */ break ;case VM_MODE_P36V48_4K : +case VM_MODE_P36V48_16K :case VM_MODE_P36V48_64K : +case VM_MODE_P36V47_16K : tcr_el1 |=1ul <<32 ;/* IPS = 36 bits */ break ;default :
tools/testing/selftests/kvm/lib/guest_modes.c +4 -0
@@ -29,17 +29,21 @@ void guest_modes_append_default(void)guest_mode_append (VM_MODE_P52V48_64K , ps64k, ps64k);if (limit >=48 ) {guest_mode_append (VM_MODE_P48V48_4K , ps4k, ps4k); +guest_mode_append (VM_MODE_P48V48_16K , ps16k, ps16k);guest_mode_append (VM_MODE_P48V48_64K , ps64k, ps64k); }if (limit >=40 ) {guest_mode_append (VM_MODE_P40V48_4K , ps4k, ps4k); +guest_mode_append (VM_MODE_P40V48_16K , ps16k, ps16k);guest_mode_append (VM_MODE_P40V48_64K , ps64k, ps64k);if (ps4k) vm_mode_default =VM_MODE_P40V48_4K ; }if (limit >=36 ) {guest_mode_append (VM_MODE_P36V48_4K , ps4k, ps4k); +guest_mode_append (VM_MODE_P36V48_16K , ps16k, ps16k);guest_mode_append (VM_MODE_P36V48_64K , ps64k, ps64k); +guest_mode_append (VM_MODE_P36V47_16K , ps16k, ps16k); }/*
tools/testing/selftests/kvm/lib/kvm_util.c +16 -0
@@ -166,14 +166,18 @@ const char *vm_guest_mode_string(uint32_t i) [VM_MODE_P52V48_4K] = "PA-bits:52, VA-bits:48, 4K pages", [VM_MODE_P52V48_64K] = "PA-bits:52, VA-bits:48, 64K pages", [VM_MODE_P48V48_4K] = "PA-bits:48, VA-bits:48, 4K pages", + [VM_MODE_P48V48_16K] = "PA-bits:48, VA-bits:48, 16K pages", [VM_MODE_P48V48_64K] = "PA-bits:48, VA-bits:48, 64K pages", [VM_MODE_P40V48_4K] = "PA-bits:40, VA-bits:48, 4K pages", + [VM_MODE_P40V48_16K] = "PA-bits:40, VA-bits:48, 16K pages", [VM_MODE_P40V48_64K] = "PA-bits:40, VA-bits:48, 64K pages", [VM_MODE_PXXV48_4K] = "PA-bits:ANY, VA-bits:48, 4K pages", [VM_MODE_P47V64_4K] = "PA-bits:47, VA-bits:64, 4K pages", [VM_MODE_P44V64_4K] = "PA-bits:44, VA-bits:64, 4K pages", [VM_MODE_P36V48_4K] = "PA-bits:36, VA-bits:48, 4K pages", + [VM_MODE_P36V48_16K] = "PA-bits:36, VA-bits:48, 16K pages", [VM_MODE_P36V48_64K] = "PA-bits:36, VA-bits:48, 64K pages", + [VM_MODE_P36V47_16K ] ="PA-bits:36, VA-bits:47, 16K pages" , };_Static_assert (sizeof (strings)/sizeof (char *) ==NUM_VM_MODES ,"Missing new mode strings?" );
@@ -187,14 +191,18 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = { [VM_MODE_P52V48_4K] = { 52, 48, 0x1000, 12 }, [VM_MODE_P52V48_64K] = { 52, 48, 0x10000, 16 }, [VM_MODE_P48V48_4K] = { 48, 48, 0x1000, 12 }, + [VM_MODE_P48V48_16K] = { 48, 48, 0x4000, 14 }, [VM_MODE_P48V48_64K] = { 48, 48, 0x10000, 16 }, [VM_MODE_P40V48_4K] = { 40, 48, 0x1000, 12 }, + [VM_MODE_P40V48_16K] = { 40, 48, 0x4000, 14 }, [VM_MODE_P40V48_64K] = { 40, 48, 0x10000, 16 }, [VM_MODE_PXXV48_4K] = { 0, 0, 0x1000, 12 }, [VM_MODE_P47V64_4K] = { 47, 64, 0x1000, 12 }, [VM_MODE_P44V64_4K] = { 44, 64, 0x1000, 12 }, [VM_MODE_P36V48_4K] = { 36, 48, 0x1000, 12 }, + [VM_MODE_P36V48_16K] = { 36, 48, 0x4000, 14 }, [VM_MODE_P36V48_64K] = { 36, 48, 0x10000, 16 }, + [VM_MODE_P36V47_16K] = { 36, 47, 0x4000, 14 }, };_Static_assert (sizeof (vm_guest_mode_params)/sizeof (struct vm_guest_mode_params ) ==NUM_VM_MODES ,"Missing new mode params?" );
@@ -263,6 +271,14 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)case VM_MODE_P36V48_64K : vm->pgtable_levels =3 ;break ; +case VM_MODE_P48V48_16K : +case VM_MODE_P40V48_16K : +case VM_MODE_P36V48_16K : + vm->pgtable_levels =4 ; +break ; +case VM_MODE_P36V47_16K : + vm->pgtable_levels =3 ; +break ;case VM_MODE_PXXV48_4K :#ifdef __x86_64__kvm_get_cpu_address_width (&vm->pa_bits, &vm->va_bits);
Signature · 1 line
2.30.2
Re: [PATCH v2 6/6] KVM: selftests: arm64: Add support for various modes with 16kB page size
Quoted 6 lines · Marc Zyngier
The 16kB page size is not a popular choice, due to only a few CPUs actually implementing support for it. However, it can lead to some interesting performance improvements given the right uarch choices.
Add support for this page size for various PA/VA combinations.
Quoted 8 lines
Signed-off-by Marc Zyngier <[email protected]>--- tools/testing/selftests/kvm/include/kvm_util.h | 4 ++++ .../selftests/kvm/lib/aarch64/processor.c | 10 ++++++++++ tools/testing/selftests/kvm/lib/guest_modes.c | 4 ++++ tools/testing/selftests/kvm/lib/kvm_util.c | 16 ++++++++++++++++ 4 files changed, 34 insertions(+)
Quoted 4 lines · Marc Zyngier
Now that the common variety of fruity arm64 systems makes a pretty remarkable KVM host, I have decided to run the collection of selftests on it.
Quoted 8 lines
Nothing works. Oh no!
As it turns out, the tests have a notion of "default mode" (40bit PA, 4kB), which cannot work in general on arm64 because there no such thing as an IPA size that would be valid everywhere (apart from the minimal 32bit), nor a guaranteed to be supported page size.
[...]
Applied to next, thanks!
[1/6] KVM: selftests: arm64: Initialise default guest mode at test startup time
commit: cb7c4f364abd09abd1865fa049ef492fb43e6bf3
[2/6] KVM: selftests: arm64: Introduce a variable default IPA size
commit: 357c628e1248dd53f5c43a768246a83478a7f489
[3/6] KVM: selftests: arm64: Check for supported page sizes
commit: 0303ffdb9ecffac4654b16bbf69ba84d131eb8b7
[4/6] KVM: selftests: arm64: Rework TCR_EL1 configuration
commit: 2f41a61c54fb6410202b2cc08be80ae9554d599d
[5/6] KVM: selftests: arm64: Add support for VM_MODE_P36V48_{4K,64K}
commit: e7f58a6bd28bfd2e4f60312abf48f07de2c4121c
[6/6] KVM: selftests: arm64: Add support for various modes with 16kB page size
commit: aa674de1dc3d2bdf2c67ad195dc81977972323c6Cheers,
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.