mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
KVM: RISC-V: SBI FWFT: Add optional init() callback for hardware probing
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: 6f576fc0ae ("RISC-V: KVM: Add support for SBI_FWFT_POINTER_MASKING_PMLEN")
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260601-kvm-get_reg_list-v2-v5-2-415d08a2813b@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
parent
63224b0274
commit
86957e5b4b
|
|
@ -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)
|
||||
{
|
||||
return riscv_isa_extension_available(vcpu->arch.isa, SMNPM);
|
||||
}
|
||||
|
||||
static bool kvm_sbi_fwft_pointer_masking_pmlen_init(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_sbi_fwft *fwft = vcpu_to_fwft(vcpu);
|
||||
|
||||
if (!riscv_isa_extension_available(vcpu->arch.isa, SMNPM))
|
||||
return false;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user