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 >

