[PATCH 1/2] KVM: riscv: selftests: Add riscv vm satp modes
Andrew Jones
ajones at ventanamicro.com
Fri Oct 17 08:38:24 PDT 2025
On Fri, Oct 17, 2025 at 11:13:33AM +0800, wu.fei9 at sanechips.com.cn wrote:
> Current vm modes cannot represent riscv guest modes precisely, here add
> P41V39, P50V48 and P56V57.
>
> Signed-off-by: Wu Fei <wu.fei9 at sanechips.com.cn>
> ---
> .../testing/selftests/kvm/include/kvm_util.h | 7 ++++++-
> tools/testing/selftests/kvm/lib/guest_modes.c | 7 +++----
> tools/testing/selftests/kvm/lib/kvm_util.c | 15 +++++++++++++
> .../selftests/kvm/lib/riscv/processor.c | 21 +++++++++++++++----
> 4 files changed, 41 insertions(+), 9 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
> index bee65ca08721..02224bc514d4 100644
> --- a/tools/testing/selftests/kvm/include/kvm_util.h
> +++ b/tools/testing/selftests/kvm/include/kvm_util.h
> @@ -179,6 +179,11 @@ enum vm_guest_mode {
> VM_MODE_P36V48_64K,
> VM_MODE_P47V47_16K,
> VM_MODE_P36V47_16K,
> +
> + VM_MODE_P56V57_4K, /* For riscv64 */
This should be P59
> + VM_MODE_P50V48_4K,
> + VM_MODE_P41V39_4K,
> +
> NUM_VM_MODES,
> };
>
> @@ -229,7 +234,7 @@ extern enum vm_guest_mode vm_mode_default;
> #error "RISC-V 32-bit kvm selftests not supported"
> #endif
>
> -#define VM_MODE_DEFAULT VM_MODE_P40V48_4K
> +#define VM_MODE_DEFAULT VM_MODE_P50V48_4K
> #define MIN_PAGE_SHIFT 12U
> #define ptes_per_page(page_size) ((page_size) / 8)
>
> diff --git a/tools/testing/selftests/kvm/lib/guest_modes.c b/tools/testing/selftests/kvm/lib/guest_modes.c
> index b04901e55138..63d0d5479188 100644
> --- a/tools/testing/selftests/kvm/lib/guest_modes.c
> +++ b/tools/testing/selftests/kvm/lib/guest_modes.c
> @@ -75,10 +75,9 @@ void guest_modes_append_default(void)
> {
> unsigned int sz = kvm_check_cap(KVM_CAP_VM_GPA_BITS);
>
> - if (sz >= 52)
> - guest_mode_append(VM_MODE_P52V48_4K, true);
> - if (sz >= 48)
> - guest_mode_append(VM_MODE_P48V48_4K, true);
> + 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);
Even when the host doesn't support P59 a guest may still use V57 (and when
a host doesn't support P50 a guest may still use V57 or V48). The host
simply doesn't describe physical memory with address bit widths greater
than its limits to the guest. Then the guest is free to use whatever
virtual address width is supported by the MMU. IOW, we need all
combinations of P and V widths for modes and then select similarly to how
Arm has multiple modes to manage all the different page sizes. Also in
order to know the maximum supported virtual bit width we need to
get-one-reg satp_mode. We should do that here instead of in
riscv_vcpu_mmu_setup() in order to filter out invalid modes when
appending them.
Thanks,
drew
> }
> #endif
> }
> diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
> index a055343a7bf7..4cd69fffa06d 100644
> --- a/tools/testing/selftests/kvm/lib/kvm_util.c
> +++ b/tools/testing/selftests/kvm/lib/kvm_util.c
> @@ -224,6 +224,9 @@ const char *vm_guest_mode_string(uint32_t i)
> [VM_MODE_P36V48_64K] = "PA-bits:36, VA-bits:48, 64K pages",
> [VM_MODE_P47V47_16K] = "PA-bits:47, VA-bits:47, 16K pages",
> [VM_MODE_P36V47_16K] = "PA-bits:36, VA-bits:47, 16K pages",
> + [VM_MODE_P56V57_4K] = "PA-bits:56, VA-bits:57, 4K pages",
> + [VM_MODE_P50V48_4K] = "PA-bits:50, VA-bits:48, 4K pages",
> + [VM_MODE_P41V39_4K] = "PA-bits:41, VA-bits:39, 4K pages",
> };
> _Static_assert(sizeof(strings)/sizeof(char *) == NUM_VM_MODES,
> "Missing new mode strings?");
> @@ -251,6 +254,9 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = {
> [VM_MODE_P36V48_64K] = { 36, 48, 0x10000, 16 },
> [VM_MODE_P47V47_16K] = { 47, 47, 0x4000, 14 },
> [VM_MODE_P36V47_16K] = { 36, 47, 0x4000, 14 },
> + [VM_MODE_P56V57_4K] = { 56, 57, 0x1000, 12 },
> + [VM_MODE_P50V48_4K] = { 50, 48, 0x1000, 12 },
> + [VM_MODE_P41V39_4K] = { 41, 39, 0x1000, 12 },
> };
> _Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
> "Missing new mode params?");
> @@ -351,6 +357,15 @@ struct kvm_vm *____vm_create(struct vm_shape shape)
> case VM_MODE_P44V64_4K:
> vm->pgtable_levels = 5;
> break;
> + case VM_MODE_P56V57_4K:
> + vm->pgtable_levels = 5;
> + break;
> + case VM_MODE_P50V48_4K:
> + vm->pgtable_levels = 4;
> + break;
> + case VM_MODE_P41V39_4K:
> + vm->pgtable_levels = 3;
> + break;
> default:
> TEST_FAIL("Unknown guest mode: 0x%x", vm->mode);
> }
> diff --git a/tools/testing/selftests/kvm/lib/riscv/processor.c b/tools/testing/selftests/kvm/lib/riscv/processor.c
> index 2eac7d4b59e9..de84c092f982 100644
> --- a/tools/testing/selftests/kvm/lib/riscv/processor.c
> +++ b/tools/testing/selftests/kvm/lib/riscv/processor.c
> @@ -197,22 +197,35 @@ void riscv_vcpu_mmu_setup(struct kvm_vcpu *vcpu)
> {
> struct kvm_vm *vm = vcpu->vm;
> unsigned long satp;
> + unsigned long satp_mode;
> + unsigned long max_satp_mode;
>
> /*
> * The RISC-V Sv48 MMU mode supports 56-bit physical address
> * for 48-bit virtual address with 4KB last level page size.
> */
> switch (vm->mode) {
> - case VM_MODE_P52V48_4K:
> - case VM_MODE_P48V48_4K:
> - case VM_MODE_P40V48_4K:
> + case VM_MODE_P56V57_4K:
> + satp_mode = SATP_MODE_57;
> + break;
> + case VM_MODE_P50V48_4K:
> + satp_mode = SATP_MODE_48;
> + break;
> + case VM_MODE_P41V39_4K:
> + satp_mode = SATP_MODE_39;
> break;
> default:
> TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
> }
>
> + max_satp_mode = vcpu_get_reg(vcpu, RISCV_CONFIG_REG(satp_mode));
> +
> + if ((satp_mode >> SATP_MODE_SHIFT) > max_satp_mode)
> + TEST_FAIL("Unable to set satp mode 0x%lx, max mode 0x%lx\n",
> + satp_mode >> SATP_MODE_SHIFT, max_satp_mode);
> +
> satp = (vm->pgd >> PGTBL_PAGE_SIZE_SHIFT) & SATP_PPN;
> - satp |= SATP_MODE_48;
> + satp |= satp_mode;
>
> vcpu_set_reg(vcpu, RISCV_GENERAL_CSR_REG(satp), satp);
> }
> --
> 2.43.0
More information about the kvm-riscv
mailing list