Skip to content

Commit 39ad809

Browse files
wufei-sanechipsavpatel
authored andcommitted
KVM: riscv: selftests: Add riscv vm satp modes
Current vm modes cannot represent riscv guest modes precisely, here add all 9 combinations of P(56,40,41) x V(57,48,39). Also the default vm mode is detected on runtime instead of hardcoded one, which might not be supported on specific machine. Signed-off-by: Wu Fei <wu.fei9@sanechips.com.cn> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20251105151442.28767-1-wu.fei9@sanechips.com.cn Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent ab2a7b7 commit 39ad809

5 files changed

Lines changed: 142 additions & 14 deletions

File tree

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,17 @@ enum vm_guest_mode {
186186
VM_MODE_P36V48_64K,
187187
VM_MODE_P47V47_16K,
188188
VM_MODE_P36V47_16K,
189+
190+
VM_MODE_P56V57_4K, /* For riscv64 */
191+
VM_MODE_P56V48_4K,
192+
VM_MODE_P56V39_4K,
193+
VM_MODE_P50V57_4K,
194+
VM_MODE_P50V48_4K,
195+
VM_MODE_P50V39_4K,
196+
VM_MODE_P41V57_4K,
197+
VM_MODE_P41V48_4K,
198+
VM_MODE_P41V39_4K,
199+
189200
NUM_VM_MODES,
190201
};
191202

@@ -210,10 +221,10 @@ kvm_static_assert(sizeof(struct vm_shape) == sizeof(uint64_t));
210221
shape; \
211222
})
212223

213-
#if defined(__aarch64__)
214-
215224
extern enum vm_guest_mode vm_mode_default;
216225

226+
#if defined(__aarch64__)
227+
217228
#define VM_MODE_DEFAULT vm_mode_default
218229
#define MIN_PAGE_SHIFT 12U
219230
#define ptes_per_page(page_size) ((page_size) / 8)
@@ -236,7 +247,7 @@ extern enum vm_guest_mode vm_mode_default;
236247
#error "RISC-V 32-bit kvm selftests not supported"
237248
#endif
238249

239-
#define VM_MODE_DEFAULT VM_MODE_P40V48_4K
250+
#define VM_MODE_DEFAULT vm_mode_default
240251
#define MIN_PAGE_SHIFT 12U
241252
#define ptes_per_page(page_size) ((page_size) / 8)
242253

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,6 @@ static inline void local_irq_disable(void)
192192
csr_clear(CSR_SSTATUS, SR_SIE);
193193
}
194194

195+
unsigned long riscv64_get_satp_mode(void);
196+
195197
#endif /* SELFTEST_KVM_PROCESSOR_H */

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

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
#include "guest_modes.h"
66

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

1414
void guest_modes_append_default(void)
1515
{
16-
#ifndef __aarch64__
16+
#if !defined(__aarch64__) && !defined(__riscv)
1717
guest_mode_append(VM_MODE_DEFAULT, true);
18-
#else
18+
#endif
19+
20+
#ifdef __aarch64__
1921
{
2022
unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE);
2123
uint32_t ipa4k, ipa16k, ipa64k;
@@ -74,11 +76,36 @@ void guest_modes_append_default(void)
7476
#ifdef __riscv
7577
{
7678
unsigned int sz = kvm_check_cap(KVM_CAP_VM_GPA_BITS);
79+
unsigned long satp_mode = riscv64_get_satp_mode() << SATP_MODE_SHIFT;
80+
int i;
7781

78-
if (sz >= 52)
79-
guest_mode_append(VM_MODE_P52V48_4K, true);
80-
if (sz >= 48)
81-
guest_mode_append(VM_MODE_P48V48_4K, true);
82+
switch (sz) {
83+
case 59:
84+
guest_mode_append(VM_MODE_P56V57_4K, satp_mode >= SATP_MODE_57);
85+
guest_mode_append(VM_MODE_P56V48_4K, satp_mode >= SATP_MODE_48);
86+
guest_mode_append(VM_MODE_P56V39_4K, satp_mode >= SATP_MODE_39);
87+
break;
88+
case 50:
89+
guest_mode_append(VM_MODE_P50V57_4K, satp_mode >= SATP_MODE_57);
90+
guest_mode_append(VM_MODE_P50V48_4K, satp_mode >= SATP_MODE_48);
91+
guest_mode_append(VM_MODE_P50V39_4K, satp_mode >= SATP_MODE_39);
92+
break;
93+
case 41:
94+
guest_mode_append(VM_MODE_P41V57_4K, satp_mode >= SATP_MODE_57);
95+
guest_mode_append(VM_MODE_P41V48_4K, satp_mode >= SATP_MODE_48);
96+
guest_mode_append(VM_MODE_P41V39_4K, satp_mode >= SATP_MODE_39);
97+
break;
98+
default:
99+
break;
100+
}
101+
102+
/* set the first supported mode as default */
103+
vm_mode_default = NUM_VM_MODES;
104+
for (i = 0; vm_mode_default == NUM_VM_MODES && i < NUM_VM_MODES; i++) {
105+
if (guest_modes[i].supported && guest_modes[i].enabled)
106+
vm_mode_default = i;
107+
}
108+
TEST_ASSERT(vm_mode_default != NUM_VM_MODES, "No supported mode!");
82109
}
83110
#endif
84111
}

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,15 @@ const char *vm_guest_mode_string(uint32_t i)
209209
[VM_MODE_P36V48_64K] = "PA-bits:36, VA-bits:48, 64K pages",
210210
[VM_MODE_P47V47_16K] = "PA-bits:47, VA-bits:47, 16K pages",
211211
[VM_MODE_P36V47_16K] = "PA-bits:36, VA-bits:47, 16K pages",
212+
[VM_MODE_P56V57_4K] = "PA-bits:56, VA-bits:57, 4K pages",
213+
[VM_MODE_P56V48_4K] = "PA-bits:56, VA-bits:48, 4K pages",
214+
[VM_MODE_P56V39_4K] = "PA-bits:56, VA-bits:39, 4K pages",
215+
[VM_MODE_P50V57_4K] = "PA-bits:50, VA-bits:57, 4K pages",
216+
[VM_MODE_P50V48_4K] = "PA-bits:50, VA-bits:48, 4K pages",
217+
[VM_MODE_P50V39_4K] = "PA-bits:50, VA-bits:39, 4K pages",
218+
[VM_MODE_P41V57_4K] = "PA-bits:41, VA-bits:57, 4K pages",
219+
[VM_MODE_P41V48_4K] = "PA-bits:41, VA-bits:48, 4K pages",
220+
[VM_MODE_P41V39_4K] = "PA-bits:41, VA-bits:39, 4K pages",
212221
};
213222
_Static_assert(sizeof(strings)/sizeof(char *) == NUM_VM_MODES,
214223
"Missing new mode strings?");
@@ -236,6 +245,15 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = {
236245
[VM_MODE_P36V48_64K] = { 36, 48, 0x10000, 16 },
237246
[VM_MODE_P47V47_16K] = { 47, 47, 0x4000, 14 },
238247
[VM_MODE_P36V47_16K] = { 36, 47, 0x4000, 14 },
248+
[VM_MODE_P56V57_4K] = { 56, 57, 0x1000, 12 },
249+
[VM_MODE_P56V48_4K] = { 56, 48, 0x1000, 12 },
250+
[VM_MODE_P56V39_4K] = { 56, 39, 0x1000, 12 },
251+
[VM_MODE_P50V57_4K] = { 50, 57, 0x1000, 12 },
252+
[VM_MODE_P50V48_4K] = { 50, 48, 0x1000, 12 },
253+
[VM_MODE_P50V39_4K] = { 50, 39, 0x1000, 12 },
254+
[VM_MODE_P41V57_4K] = { 41, 57, 0x1000, 12 },
255+
[VM_MODE_P41V48_4K] = { 41, 48, 0x1000, 12 },
256+
[VM_MODE_P41V39_4K] = { 41, 39, 0x1000, 12 },
239257
};
240258
_Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
241259
"Missing new mode params?");
@@ -338,6 +356,21 @@ struct kvm_vm *____vm_create(struct vm_shape shape)
338356
case VM_MODE_P44V64_4K:
339357
vm->pgtable_levels = 5;
340358
break;
359+
case VM_MODE_P56V57_4K:
360+
case VM_MODE_P50V57_4K:
361+
case VM_MODE_P41V57_4K:
362+
vm->pgtable_levels = 5;
363+
break;
364+
case VM_MODE_P56V48_4K:
365+
case VM_MODE_P50V48_4K:
366+
case VM_MODE_P41V48_4K:
367+
vm->pgtable_levels = 4;
368+
break;
369+
case VM_MODE_P56V39_4K:
370+
case VM_MODE_P50V39_4K:
371+
case VM_MODE_P41V39_4K:
372+
vm->pgtable_levels = 3;
373+
break;
341374
default:
342375
TEST_FAIL("Unknown guest mode: 0x%x", vm->mode);
343376
}

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

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/compiler.h>
99
#include <assert.h>
1010

11+
#include "guest_modes.h"
1112
#include "kvm_util.h"
1213
#include "processor.h"
1314
#include "ucall_common.h"
@@ -197,22 +198,41 @@ void riscv_vcpu_mmu_setup(struct kvm_vcpu *vcpu)
197198
{
198199
struct kvm_vm *vm = vcpu->vm;
199200
unsigned long satp;
201+
unsigned long satp_mode;
202+
unsigned long max_satp_mode;
200203

201204
/*
202205
* The RISC-V Sv48 MMU mode supports 56-bit physical address
203206
* for 48-bit virtual address with 4KB last level page size.
204207
*/
205208
switch (vm->mode) {
206-
case VM_MODE_P52V48_4K:
207-
case VM_MODE_P48V48_4K:
208-
case VM_MODE_P40V48_4K:
209+
case VM_MODE_P56V57_4K:
210+
case VM_MODE_P50V57_4K:
211+
case VM_MODE_P41V57_4K:
212+
satp_mode = SATP_MODE_57;
213+
break;
214+
case VM_MODE_P56V48_4K:
215+
case VM_MODE_P50V48_4K:
216+
case VM_MODE_P41V48_4K:
217+
satp_mode = SATP_MODE_48;
218+
break;
219+
case VM_MODE_P56V39_4K:
220+
case VM_MODE_P50V39_4K:
221+
case VM_MODE_P41V39_4K:
222+
satp_mode = SATP_MODE_39;
209223
break;
210224
default:
211225
TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
212226
}
213227

228+
max_satp_mode = vcpu_get_reg(vcpu, RISCV_CONFIG_REG(satp_mode));
229+
230+
if ((satp_mode >> SATP_MODE_SHIFT) > max_satp_mode)
231+
TEST_FAIL("Unable to set satp mode 0x%lx, max mode 0x%lx\n",
232+
satp_mode >> SATP_MODE_SHIFT, max_satp_mode);
233+
214234
satp = (vm->pgd >> PGTBL_PAGE_SIZE_SHIFT) & SATP_PPN;
215-
satp |= SATP_MODE_48;
235+
satp |= satp_mode;
216236

217237
vcpu_set_reg(vcpu, RISCV_GENERAL_CSR_REG(satp), satp);
218238
}
@@ -515,3 +535,38 @@ unsigned long get_host_sbi_spec_version(void)
515535

516536
return ret.value;
517537
}
538+
539+
void kvm_selftest_arch_init(void)
540+
{
541+
/*
542+
* riscv64 doesn't have a true default mode, so start by detecting the
543+
* supported vm mode.
544+
*/
545+
guest_modes_append_default();
546+
}
547+
548+
unsigned long riscv64_get_satp_mode(void)
549+
{
550+
int kvm_fd, vm_fd, vcpu_fd, err;
551+
uint64_t val;
552+
struct kvm_one_reg reg = {
553+
.id = RISCV_CONFIG_REG(satp_mode),
554+
.addr = (uint64_t)&val,
555+
};
556+
557+
kvm_fd = open_kvm_dev_path_or_exit();
558+
vm_fd = __kvm_ioctl(kvm_fd, KVM_CREATE_VM, NULL);
559+
TEST_ASSERT(vm_fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_VM, vm_fd));
560+
561+
vcpu_fd = ioctl(vm_fd, KVM_CREATE_VCPU, 0);
562+
TEST_ASSERT(vcpu_fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_VCPU, vcpu_fd));
563+
564+
err = ioctl(vcpu_fd, KVM_GET_ONE_REG, &reg);
565+
TEST_ASSERT(err == 0, KVM_IOCTL_ERROR(KVM_GET_ONE_REG, vcpu_fd));
566+
567+
close(vcpu_fd);
568+
close(vm_fd);
569+
close(kvm_fd);
570+
571+
return val;
572+
}

0 commit comments

Comments
 (0)