On Mon, Jun 1, 2026 at 3:56 PM Yong-Xuan Wang <[email protected]> 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 <[email protected]>

LGTM.

Reviewed-by: Anup Patel <[email protected]>

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
>

Reply via email to