Skip to content

Commit f80e9cc

Browse files
atishp04avpatel
authored andcommitted
KVM: riscv: selftests: Add vector extension tests
Add vector related tests with the ISA extension standard template. However, the vector registers are bit tricky as the register length is variable based on vlenb value of the system. That's why the macros are defined with a default and overidden with actual value at runtime. Reviewed-by: Anup Patel <anup@brainfault.org> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Signed-off-by: Atish Patra <atishp@rivosinc.com> Link: https://lore.kernel.org/r/20250430-kvm_selftest_improve-v3-3-eea270ff080b@rivosinc.com Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent 3608b17 commit f80e9cc

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

tools/testing/selftests/kvm/riscv/get-reg-list.c

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ enum {
1717
VCPU_FEATURE_SBI_EXT,
1818
};
1919

20+
enum {
21+
KVM_RISC_V_REG_OFFSET_VSTART = 0,
22+
KVM_RISC_V_REG_OFFSET_VL,
23+
KVM_RISC_V_REG_OFFSET_VTYPE,
24+
KVM_RISC_V_REG_OFFSET_VCSR,
25+
KVM_RISC_V_REG_OFFSET_VLENB,
26+
KVM_RISC_V_REG_OFFSET_MAX,
27+
};
28+
2029
static bool isa_ext_cant_disable[KVM_RISCV_ISA_EXT_MAX];
2130

2231
bool filter_reg(__u64 reg)
@@ -143,6 +152,38 @@ bool check_reject_set(int err)
143152
return err == EINVAL;
144153
}
145154

155+
static int override_vector_reg_size(struct kvm_vcpu *vcpu, struct vcpu_reg_sublist *s,
156+
uint64_t feature)
157+
{
158+
unsigned long vlenb_reg = 0;
159+
int rc;
160+
u64 reg, size;
161+
162+
/* Enable V extension so that we can get the vlenb register */
163+
rc = __vcpu_set_reg(vcpu, feature, 1);
164+
if (rc)
165+
return rc;
166+
167+
vlenb_reg = vcpu_get_reg(vcpu, s->regs[KVM_RISC_V_REG_OFFSET_VLENB]);
168+
if (!vlenb_reg) {
169+
TEST_FAIL("Can't compute vector register size from zero vlenb\n");
170+
return -EPERM;
171+
}
172+
173+
size = __builtin_ctzl(vlenb_reg);
174+
size <<= KVM_REG_SIZE_SHIFT;
175+
176+
for (int i = 0; i < 32; i++) {
177+
reg = KVM_REG_RISCV | KVM_REG_RISCV_VECTOR | size | KVM_REG_RISCV_VECTOR_REG(i);
178+
s->regs[KVM_RISC_V_REG_OFFSET_MAX + i] = reg;
179+
}
180+
181+
/* We should assert if disabling failed here while enabling succeeded before */
182+
vcpu_set_reg(vcpu, feature, 0);
183+
184+
return 0;
185+
}
186+
146187
void finalize_vcpu(struct kvm_vcpu *vcpu, struct vcpu_reg_list *c)
147188
{
148189
unsigned long isa_ext_state[KVM_RISCV_ISA_EXT_MAX] = { 0 };
@@ -172,6 +213,13 @@ void finalize_vcpu(struct kvm_vcpu *vcpu, struct vcpu_reg_list *c)
172213
if (!s->feature)
173214
continue;
174215

216+
if (s->feature == KVM_RISCV_ISA_EXT_V) {
217+
feature = RISCV_ISA_EXT_REG(s->feature);
218+
rc = override_vector_reg_size(vcpu, s, feature);
219+
if (rc)
220+
goto skip;
221+
}
222+
175223
switch (s->feature_type) {
176224
case VCPU_FEATURE_ISA_EXT:
177225
feature = RISCV_ISA_EXT_REG(s->feature);
@@ -186,6 +234,7 @@ void finalize_vcpu(struct kvm_vcpu *vcpu, struct vcpu_reg_list *c)
186234
/* Try to enable the desired extension */
187235
__vcpu_set_reg(vcpu, feature, 1);
188236

237+
skip:
189238
/* Double check whether the desired extension was enabled */
190239
__TEST_REQUIRE(__vcpu_has_ext(vcpu, feature),
191240
"%s not available, skipping tests", s->name);
@@ -410,6 +459,35 @@ static const char *fp_d_id_to_str(const char *prefix, __u64 id)
410459
return strdup_printf("%lld /* UNKNOWN */", reg_off);
411460
}
412461

462+
static const char *vector_id_to_str(const char *prefix, __u64 id)
463+
{
464+
/* reg_off is the offset into struct __riscv_v_ext_state */
465+
__u64 reg_off = id & ~(REG_MASK | KVM_REG_RISCV_VECTOR);
466+
int reg_index = 0;
467+
468+
assert((id & KVM_REG_RISCV_TYPE_MASK) == KVM_REG_RISCV_VECTOR);
469+
470+
if (reg_off >= KVM_REG_RISCV_VECTOR_REG(0))
471+
reg_index = reg_off - KVM_REG_RISCV_VECTOR_REG(0);
472+
switch (reg_off) {
473+
case KVM_REG_RISCV_VECTOR_REG(0) ...
474+
KVM_REG_RISCV_VECTOR_REG(31):
475+
return strdup_printf("KVM_REG_RISCV_VECTOR_REG(%d)", reg_index);
476+
case KVM_REG_RISCV_VECTOR_CSR_REG(vstart):
477+
return "KVM_REG_RISCV_VECTOR_CSR_REG(vstart)";
478+
case KVM_REG_RISCV_VECTOR_CSR_REG(vl):
479+
return "KVM_REG_RISCV_VECTOR_CSR_REG(vl)";
480+
case KVM_REG_RISCV_VECTOR_CSR_REG(vtype):
481+
return "KVM_REG_RISCV_VECTOR_CSR_REG(vtype)";
482+
case KVM_REG_RISCV_VECTOR_CSR_REG(vcsr):
483+
return "KVM_REG_RISCV_VECTOR_CSR_REG(vcsr)";
484+
case KVM_REG_RISCV_VECTOR_CSR_REG(vlenb):
485+
return "KVM_REG_RISCV_VECTOR_CSR_REG(vlenb)";
486+
}
487+
488+
return strdup_printf("%lld /* UNKNOWN */", reg_off);
489+
}
490+
413491
#define KVM_ISA_EXT_ARR(ext) \
414492
[KVM_RISCV_ISA_EXT_##ext] = "KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_" #ext
415493

@@ -639,6 +717,9 @@ void print_reg(const char *prefix, __u64 id)
639717
case KVM_REG_SIZE_U128:
640718
reg_size = "KVM_REG_SIZE_U128";
641719
break;
720+
case KVM_REG_SIZE_U256:
721+
reg_size = "KVM_REG_SIZE_U256";
722+
break;
642723
default:
643724
printf("\tKVM_REG_RISCV | (%lld << KVM_REG_SIZE_SHIFT) | 0x%llx /* UNKNOWN */,\n",
644725
(id & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT, id & ~REG_MASK);
@@ -670,6 +751,10 @@ void print_reg(const char *prefix, __u64 id)
670751
printf("\tKVM_REG_RISCV | %s | KVM_REG_RISCV_FP_D | %s,\n",
671752
reg_size, fp_d_id_to_str(prefix, id));
672753
break;
754+
case KVM_REG_RISCV_VECTOR:
755+
printf("\tKVM_REG_RISCV | %s | KVM_REG_RISCV_VECTOR | %s,\n",
756+
reg_size, vector_id_to_str(prefix, id));
757+
break;
673758
case KVM_REG_RISCV_ISA_EXT:
674759
printf("\tKVM_REG_RISCV | %s | KVM_REG_RISCV_ISA_EXT | %s,\n",
675760
reg_size, isa_ext_id_to_str(prefix, id));
@@ -874,6 +959,48 @@ static __u64 fp_d_regs[] = {
874959
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_D,
875960
};
876961

962+
/* Define a default vector registers with length. This will be overwritten at runtime */
963+
static __u64 vector_regs[] = {
964+
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_CSR_REG(vstart),
965+
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_CSR_REG(vl),
966+
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_CSR_REG(vtype),
967+
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_CSR_REG(vcsr),
968+
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_CSR_REG(vlenb),
969+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(0),
970+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(1),
971+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(2),
972+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(3),
973+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(4),
974+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(5),
975+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(6),
976+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(7),
977+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(8),
978+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(9),
979+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(10),
980+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(11),
981+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(12),
982+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(13),
983+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(14),
984+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(15),
985+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(16),
986+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(17),
987+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(18),
988+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(19),
989+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(20),
990+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(21),
991+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(22),
992+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(23),
993+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(24),
994+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(25),
995+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(26),
996+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(27),
997+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(28),
998+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(29),
999+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(30),
1000+
KVM_REG_RISCV | KVM_REG_SIZE_U128 | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(31),
1001+
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_V,
1002+
};
1003+
8771004
#define SUBLIST_BASE \
8781005
{"base", .regs = base_regs, .regs_n = ARRAY_SIZE(base_regs), \
8791006
.skips_set = base_skips_set, .skips_set_n = ARRAY_SIZE(base_skips_set),}
@@ -898,6 +1025,9 @@ static __u64 fp_d_regs[] = {
8981025
{"fp_d", .feature = KVM_RISCV_ISA_EXT_D, .regs = fp_d_regs, \
8991026
.regs_n = ARRAY_SIZE(fp_d_regs),}
9001027

1028+
#define SUBLIST_V \
1029+
{"v", .feature = KVM_RISCV_ISA_EXT_V, .regs = vector_regs, .regs_n = ARRAY_SIZE(vector_regs),}
1030+
9011031
#define KVM_ISA_EXT_SIMPLE_CONFIG(ext, extu) \
9021032
static __u64 regs_##ext[] = { \
9031033
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | \
@@ -966,6 +1096,7 @@ KVM_SBI_EXT_SIMPLE_CONFIG(susp, SUSP);
9661096
KVM_ISA_EXT_SUBLIST_CONFIG(aia, AIA);
9671097
KVM_ISA_EXT_SUBLIST_CONFIG(fp_f, FP_F);
9681098
KVM_ISA_EXT_SUBLIST_CONFIG(fp_d, FP_D);
1099+
KVM_ISA_EXT_SUBLIST_CONFIG(v, V);
9691100
KVM_ISA_EXT_SIMPLE_CONFIG(h, H);
9701101
KVM_ISA_EXT_SIMPLE_CONFIG(smnpm, SMNPM);
9711102
KVM_ISA_EXT_SUBLIST_CONFIG(smstateen, SMSTATEEN);
@@ -1040,6 +1171,7 @@ struct vcpu_reg_list *vcpu_configs[] = {
10401171
&config_fp_f,
10411172
&config_fp_d,
10421173
&config_h,
1174+
&config_v,
10431175
&config_smnpm,
10441176
&config_smstateen,
10451177
&config_sscofpmf,

0 commit comments

Comments
 (0)