[PATCH v5 2/5] KVM: RISC-V: SBI FWFT: Add optional init() callback for hardware probing
Yong-Xuan Wang
yongxuan.wang at sifive.com
Mon Jun 1 03:26:23 PDT 2026
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>
---
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 kvm-riscv
mailing list