Divide the monolithic SBI FWFT (Firmware Features) register list into separate sublists, each testing a specific FWFT feature independently with proper dependency checking.
Previously, all FWFT features were tested together in a single sublist. This caused issues because: 1. Not all FWFT features are available on all platforms 2. Some features depend on specific ISA extensions (e.g., pointer_masking requires Smnpm) 3. Tests would fail if any single feature was unavailable Add the feature-specific SBI FWFT sublists with the following improvements: - Add check_fwft_feature() helper to verify FWFT feature availability at runtime - Update filter_reg() to handle per-feature FWFT register filtering Signed-off-by: Yong-Xuan Wang <[email protected]> --- tools/testing/selftests/kvm/riscv/get-reg-list.c | 60 ++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/riscv/get-reg-list.c b/tools/testing/selftests/kvm/riscv/get-reg-list.c index 5033c09201ef..cb86cb6b3635 100644 --- a/tools/testing/selftests/kvm/riscv/get-reg-list.c +++ b/tools/testing/selftests/kvm/riscv/get-reg-list.c @@ -27,6 +27,7 @@ enum { }; static bool isa_ext_cant_disable[KVM_RISCV_ISA_EXT_MAX]; +static bool sbi_ext_enabled[KVM_RISCV_SBI_EXT_MAX]; bool filter_reg(__u64 reg) { @@ -149,6 +150,14 @@ bool filter_reg(__u64 reg) case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio1h): case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio2h): return isa_ext_cant_disable[KVM_RISCV_ISA_EXT_SSAIA]; + /* + * FWFT misaligned delegation registers are always visible when the SBI FWFT + * extension is enable and the host supports the misaligned delegation. + */ + case KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(misaligned_deleg.enable): + case KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(misaligned_deleg.flags): + case KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(misaligned_deleg.value): + return sbi_ext_enabled[KVM_RISCV_SBI_EXT_FWFT]; default: break; } @@ -193,6 +202,27 @@ static int override_vector_reg_size(struct kvm_vcpu *vcpu, struct vcpu_reg_subli return 0; } +void check_fwft_feature(struct kvm_vcpu *vcpu, struct vcpu_reg_sublist *s, u64 feature) +{ + unsigned long value; + int rc; + + /* Enable SBI FWFT extension so that we can check the supported register */ + rc = __vcpu_set_reg(vcpu, feature, 1); + if (rc) + return; + + for (int i = 0; i < s->regs_n; i++) { + if ((s->regs[i] & KVM_REG_RISCV_TYPE_MASK) == KVM_REG_RISCV_SBI_STATE) { + rc = __vcpu_get_reg(vcpu, s->regs[i], &value); + __TEST_REQUIRE(!rc, "%s not available, skipping tests", s->name); + } + } + + /* We should assert if disabling failed here while enabling succeeded before */ + vcpu_set_reg(vcpu, feature, 0); +} + void finalize_vcpu(struct kvm_vcpu *vcpu, struct vcpu_reg_list *c) { unsigned long isa_ext_state[KVM_RISCV_ISA_EXT_MAX] = { 0 }; @@ -235,6 +265,9 @@ void finalize_vcpu(struct kvm_vcpu *vcpu, struct vcpu_reg_list *c) break; case VCPU_FEATURE_SBI_EXT: feature = RISCV_SBI_EXT_REG(s->feature); + if (s->feature == KVM_RISCV_SBI_EXT_FWFT) + check_fwft_feature(vcpu, s, feature); + sbi_ext_enabled[s->feature] = true; break; default: TEST_FAIL("Unknown feature type"); @@ -897,11 +930,15 @@ static __u64 sbi_sta_regs[] = { KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_STA | KVM_REG_RISCV_SBI_STA_REG(shmem_hi), }; -static __u64 sbi_fwft_regs[] = { +static __u64 sbi_fwft_misaligned_deleg_regs[] = { KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_FWFT, KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(misaligned_deleg.enable), KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(misaligned_deleg.flags), KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(misaligned_deleg.value), +}; + +static __u64 sbi_fwft_pointer_masking_regs[] = { + KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_FWFT, KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pointer_masking.enable), KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pointer_masking.flags), KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pointer_masking.value), @@ -1129,7 +1166,6 @@ KVM_SBI_EXT_SIMPLE_CONFIG(pmu, PMU); KVM_SBI_EXT_SIMPLE_CONFIG(dbcn, DBCN); KVM_SBI_EXT_SIMPLE_CONFIG(susp, SUSP); KVM_SBI_EXT_SIMPLE_CONFIG(mpxy, MPXY); -KVM_SBI_EXT_SUBLIST_CONFIG(fwft, FWFT); KVM_ISA_EXT_SUBLIST_CONFIG(aia, SSAIA); KVM_ISA_EXT_SUBLIST_CONFIG(fp_f, F); @@ -1206,6 +1242,23 @@ KVM_ISA_EXT_SIMPLE_CONFIG(zvksed, ZVKSED); KVM_ISA_EXT_SIMPLE_CONFIG(zvksh, ZVKSH); KVM_ISA_EXT_SIMPLE_CONFIG(zvkt, ZVKT); +static struct vcpu_reg_list config_sbi_fwft_misaligned_deleg = { + .sublists = { + SUBLIST_BASE, + SUBLIST_SBI(fwft_misaligned_deleg, FWFT), + {0}, + }, +}; + +static struct vcpu_reg_list config_sbi_fwft_pointer_masking = { + .sublists = { + SUBLIST_BASE, + SUBLIST_ISA(smnpm, SMNPM), + SUBLIST_SBI(fwft_pointer_masking, FWFT), + {0}, + }, +}; + struct vcpu_reg_list *vcpu_configs[] = { &config_sbi_base, &config_sbi_sta, @@ -1213,7 +1266,8 @@ struct vcpu_reg_list *vcpu_configs[] = { &config_sbi_dbcn, &config_sbi_susp, &config_sbi_mpxy, - &config_sbi_fwft, + &config_sbi_fwft_misaligned_deleg, + &config_sbi_fwft_pointer_masking, &config_aia, &config_fp_f, &config_fp_d, -- 2.43.7

