[PATCH 2/2] KVM: riscv: selftests: Detect supported vm modes

wu.fei9 at sanechips.com.cn wu.fei9 at sanechips.com.cn
Thu Oct 16 20:15:57 PDT 2025


The default vm mode on riscv is hardcoded to sv48, which causes tests to
fail on platform supporting sv39 only, such as '-cpu rva23s64' on qemu.
This patch detects the support vm modes and sets default to the maximum
supported one.

Signed-off-by: Wu Fei <wu.fei9 at sanechips.com.cn>
---
 .../testing/selftests/kvm/include/kvm_util.h  |  4 ++-
 .../selftests/kvm/include/riscv/processor.h   |  2 ++
 tools/testing/selftests/kvm/lib/guest_modes.c | 24 +++++++++----
 .../selftests/kvm/lib/riscv/processor.c       | 36 +++++++++++++++++++
 4 files changed, 59 insertions(+), 7 deletions(-)

diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 02224bc514d4..7bc2ee9f0cad 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -234,7 +234,9 @@ extern enum vm_guest_mode vm_mode_default;
 #error "RISC-V 32-bit kvm selftests not supported"
 #endif

-#define VM_MODE_DEFAULT                        VM_MODE_P50V48_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)

diff --git a/tools/testing/selftests/kvm/include/riscv/processor.h b/tools/testing/selftests/kvm/include/riscv/processor.h
index 162f303d9daa..2d5a5548e698 100644
--- a/tools/testing/selftests/kvm/include/riscv/processor.h
+++ b/tools/testing/selftests/kvm/include/riscv/processor.h
@@ -191,4 +191,6 @@ static inline void local_irq_disable(void)
        csr_clear(CSR_SSTATUS, SR_SIE);
 }

+unsigned long riscv64_get_satp_mode(void);
+
 #endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/lib/guest_modes.c b/tools/testing/selftests/kvm/lib/guest_modes.c
index 63d0d5479188..9c4a9e86223e 100644
--- a/tools/testing/selftests/kvm/lib/guest_modes.c
+++ b/tools/testing/selftests/kvm/lib/guest_modes.c
@@ -4,7 +4,7 @@
  */
 #include "guest_modes.h"

-#ifdef __aarch64__
+#if defined(__aarch64__) || defined(__riscv)
 #include "processor.h"
 enum vm_guest_mode vm_mode_default;
 #endif
@@ -13,9 +13,11 @@ struct guest_mode guest_modes[NUM_VM_MODES];

 void guest_modes_append_default(void)
 {
-#ifndef __aarch64__
+#if !defined(__aarch64__) && !defined(__riscv)
        guest_mode_append(VM_MODE_DEFAULT, true);
-#else
+#endif
+
+#ifdef __aarch64__
        {
                unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE);
                uint32_t ipa4k, ipa16k, ipa64k;
@@ -74,10 +76,20 @@ void guest_modes_append_default(void)
 #ifdef __riscv
        {
                unsigned int sz = kvm_check_cap(KVM_CAP_VM_GPA_BITS);
+               unsigned long satp_mode = riscv64_get_satp_mode() << SATP_MODE_SHIFT;
+               int i;

-               guest_mode_append(VM_MODE_P56V57_4K, sz >= 59);
-               guest_mode_append(VM_MODE_P50V48_4K, sz >= 50);
-               guest_mode_append(VM_MODE_P41V39_4K, sz >= 41);
+               guest_mode_append(VM_MODE_P56V57_4K, satp_mode >= SATP_MODE_57 && sz >= 59);
+               guest_mode_append(VM_MODE_P50V48_4K, satp_mode >= SATP_MODE_48 && sz >= 50);
+               guest_mode_append(VM_MODE_P41V39_4K, satp_mode >= SATP_MODE_39 && sz >= 41);
+
+               // set the first (maximum) supported mode as default
+               vm_mode_default = NUM_VM_MODES;
+               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
 }
diff --git a/tools/testing/selftests/kvm/lib/riscv/processor.c b/tools/testing/selftests/kvm/lib/riscv/processor.c
index de84c092f982..eac67cb21f50 100644
--- a/tools/testing/selftests/kvm/lib/riscv/processor.c
+++ b/tools/testing/selftests/kvm/lib/riscv/processor.c
@@ -8,6 +8,7 @@
 #include <linux/compiler.h>
 #include <assert.h>

+#include "guest_modes.h"
 #include "kvm_util.h"
 #include "processor.h"
 #include "ucall_common.h"
@@ -528,3 +529,38 @@ unsigned long get_host_sbi_spec_version(void)

        return ret.value;
 }
+
+void kvm_selftest_arch_init(void)
+{
+       /*
+        * riscv64 doesn't have a true default mode, so start by detecting the
+        * supported vm mode.
+        */
+       guest_modes_append_default();
+}
+
+unsigned long riscv64_get_satp_mode(void)
+{
+       int kvm_fd, vm_fd, vcpu_fd, err;
+       uint64_t val;
+       struct kvm_one_reg reg = {
+               .id     = RISCV_CONFIG_REG(satp_mode),
+               .addr   = (uint64_t)&val,
+       };
+
+       kvm_fd = open_kvm_dev_path_or_exit();
+       vm_fd = __kvm_ioctl(kvm_fd, KVM_CREATE_VM, NULL);
+       TEST_ASSERT(vm_fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_VM, vm_fd));
+
+       vcpu_fd = ioctl(vm_fd, KVM_CREATE_VCPU, 0);
+       TEST_ASSERT(vcpu_fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_VCPU, vcpu_fd));
+
+       err = ioctl(vcpu_fd, KVM_GET_ONE_REG, &reg);
+       TEST_ASSERT(err == 0, KVM_IOCTL_ERROR(KVM_GET_ONE_REG, vcpu_fd));
+
+       close(vcpu_fd);
+       close(vm_fd);
+       close(kvm_fd);
+
+       return val;
+}
--
2.43.0



More information about the kvm-riscv mailing list