[PATCH v5 2/5] KVM: RISC-V: SBI FWFT: Add optional init() callback for hardware probing
Anup Patel
anup at brainfault.org
Fri Jun 5 09:11:43 PDT 2026
On Mon, Jun 1, 2026 at 3:56 PM Yong-Xuan Wang <yongxuan.wang at sifive.com> wrote:
>
> Add an optional init() callback to separate one-time hardware probing
> from runtime availability checks. For pointer masking, this allows
> probing supported PMM lengths during initialization while checking ISA
> extension availability at runtime.
>
> Fix try_to_set_pmm() to restore the previous HENVCFG.PMM value after
> probing, preventing side effects from hardware detection. Add preemption
> protection to ensure CSR probe sequences complete atomically on the same
> CPU.
>
> Fixes: 6f576fc0aeb9 ("RISC-V: KVM: Add support for SBI_FWFT_POINTER_MASKING_PMLEN")
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang at sifive.com>
LGTM.
Reviewed-by: Anup Patel <anup at brainfault.org>
Thanks,
Anup
> ---
> arch/riscv/kvm/vcpu_sbi_fwft.c | 33 +++++++++++++++++++++++++++++----
> 1 file changed, 29 insertions(+), 4 deletions(-)
>
> diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
> index 5e4aafb0cbf1..aee951f2b8e6 100644
> --- a/arch/riscv/kvm/vcpu_sbi_fwft.c
> +++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
> @@ -35,6 +35,16 @@ struct kvm_sbi_fwft_feature {
> */
> bool (*supported)(struct kvm_vcpu *vcpu);
>
> + /**
> + * @init: Probe and initialize the feature on the vcpu
> + *
> + * This callback is optional. If provided, it will be called during
> + * vcpu initialization to probe the feature availability and perform
> + * any necessary initialization. Returns true if the feature is supported
> + * and initialized successfully, false otherwise.
> + */
> + bool (*init)(struct kvm_vcpu *vcpu);
> +
> /**
> * @reset: Reset the feature value irrespective whether feature is supported or not
> *
> @@ -131,19 +141,30 @@ static long kvm_sbi_fwft_get_misaligned_delegation(struct kvm_vcpu *vcpu,
>
> static bool try_to_set_pmm(unsigned long value)
> {
> + unsigned long prev;
> + bool ret;
> +
> + prev = csr_read_clear(CSR_HENVCFG, ENVCFG_PMM);
> csr_set(CSR_HENVCFG, value);
> - return (csr_read_clear(CSR_HENVCFG, ENVCFG_PMM) & ENVCFG_PMM) == value;
> + ret = (csr_read_clear(CSR_HENVCFG, ENVCFG_PMM) & ENVCFG_PMM) == value;
> + csr_write(CSR_HENVCFG, prev);
> +
> + return ret;
> }
>
> static bool kvm_sbi_fwft_pointer_masking_pmlen_supported(struct kvm_vcpu *vcpu)
> {
> - struct kvm_sbi_fwft *fwft = vcpu_to_fwft(vcpu);
> + return riscv_isa_extension_available(vcpu->arch.isa, SMNPM);
> +}
>
> - if (!riscv_isa_extension_available(vcpu->arch.isa, SMNPM))
> - return false;
> +static bool kvm_sbi_fwft_pointer_masking_pmlen_init(struct kvm_vcpu *vcpu)
> +{
> + struct kvm_sbi_fwft *fwft = vcpu_to_fwft(vcpu);
>
> + preempt_disable();
> fwft->have_vs_pmlen_7 = try_to_set_pmm(ENVCFG_PMM_PMLEN_7);
> fwft->have_vs_pmlen_16 = try_to_set_pmm(ENVCFG_PMM_PMLEN_16);
> + preempt_enable();
>
> return fwft->have_vs_pmlen_7 || fwft->have_vs_pmlen_16;
> }
> @@ -231,6 +252,7 @@ static const struct kvm_sbi_fwft_feature features[] = {
> .first_reg_num = offsetof(struct kvm_riscv_sbi_fwft, pointer_masking.enable) /
> sizeof(unsigned long),
> .supported = kvm_sbi_fwft_pointer_masking_pmlen_supported,
> + .init = kvm_sbi_fwft_pointer_masking_pmlen_init,
> .reset = kvm_sbi_fwft_reset_pointer_masking_pmlen,
> .set = kvm_sbi_fwft_set_pointer_masking_pmlen,
> .get = kvm_sbi_fwft_get_pointer_masking_pmlen,
> @@ -365,6 +387,9 @@ static int kvm_sbi_ext_fwft_init(struct kvm_vcpu *vcpu)
> else
> conf->supported = true;
>
> + if (conf->supported && feature->init)
> + conf->supported = feature->init(vcpu);
> +
> conf->enabled = conf->supported;
> conf->feature = feature;
> }
>
> --
> 2.43.7
>
More information about the linux-riscv
mailing list