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

Wu Fei atwufei at 163.com
Mon Oct 20 06:26:18 PDT 2025


On 10/18/25 00:04, Andrew Jones wrote:
> On Fri, Oct 17, 2025 at 11:15:57AM +0800, wu.fei9 at sanechips.com.cn wrote:
>> 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;
> 
> We can just move this declaration out of the #ifdef __aarch64__ region.
> It shouldn't harm other architectures.

OK.

> 
>> +
>> +#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);
> 
> Something along these lines was what I was suggesting in the last patch,
> but where we select from many more combinations of P and V for modes.
> 
> VM_MODE_P41V39_4K
> VM_MODE_P41V48_4K
> VM_MODE_P41V57_4K
> VM_MODE_P50V48_4K
> VM_MODE_P50V57_4K
> VM_MODE_P59V57_4K

Do we need more? e.g. for sv39, there could be P50V39 and P56V39.

> 
>> +
>> +               // set the first (maximum) supported mode as default
> 
> Please, no C++ comments, and don't we want a V39 mode to be the default?
> In fact, VM_MODE_P41V39_4K should always be supported, so we can just set
> VM_MODE_DEFAULT to that.

It's likely the maximum supported mode is the most common configuration 
on production?

Thanks,
Fei.

> 
> Thanks,
> drew
> 
>> +               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