On Mon, Jun 1, 2026 at 3:56 PM Yong-Xuan Wang <[email protected]> wrote:
>
> Fix a bug where FWFT features could be incorrectly exposed to guests
> after userspace disables their dependent ISA extensions at runtime.
>
> The 'supported' field in kvm_sbi_fwft_config was set once during vCPU
> initialization based on the initial hardware/extension availability.
> However, when userspace subsequently disables ISA extensions via the KVM
> ONE_REG interface, the 'supported' field was not updated. This caused
> the following issues:
> 1. FWFT features would remain visible and accessible to guests even
>    after their prerequisite ISA extensions were disabled
> 2. Guests could configure FWFT features that depend on disabled
>    extensions, leading to undefined behavior
> 3. The static 'supported' flag and the dynamic supported() callback
>    could disagree about feature availability
>
> The fix introduces a two-layer checking mechanism:
> 1. Add an optional init() callback to the kvm_sbi_fwft_feature structure
>    for features that require hardware probing during initialization. This
>    separates the one-time hardware detection logic from the runtime
>    availability check.
> 2. Add runtime checks in all FWFT-related functions that call
>    feature->supported(vcpu) if the callback exists. This ensures feature
>    availability is re-evaluated based on the current ISA extension state.
>
> This approach maintains the cached 'supported' field for initialization-
> time decisions while ensuring runtime availability is always determined
> by the current vCPU configuration, not initialization-time snapshots.
>
> Fixes: 6b72fd170592 ("RISC-V: KVM: add support for FWFT SBI extension")
>
> Signed-off-by: Yong-Xuan Wang <[email protected]>

LGTM.

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

Thanks,
Anup

> ---
>  arch/riscv/kvm/vcpu_sbi_fwft.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
> index aee951f2b8e6..ab39ac464ffd 100644
> --- a/arch/riscv/kvm/vcpu_sbi_fwft.c
> +++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
> @@ -303,6 +303,8 @@ static int kvm_fwft_get_feature(struct kvm_vcpu *vcpu, 
> u32 feature,
>
>         if (!tconf->supported || !tconf->enabled)
>                 return SBI_ERR_NOT_SUPPORTED;
> +       else if (tconf->feature->supported && 
> !tconf->feature->supported(vcpu))
> +               return SBI_ERR_NOT_SUPPORTED;
>
>         *conf = tconf;
>
> @@ -433,6 +435,8 @@ static unsigned long 
> kvm_sbi_ext_fwft_get_reg_count(struct kvm_vcpu *vcpu)
>                 conf = kvm_sbi_fwft_get_config(vcpu, feature->id);
>                 if (!conf || !conf->supported)
>                         continue;
> +               else if (conf->feature->supported && 
> !conf->feature->supported(vcpu))
> +                       continue;
>
>                 ret++;
>         }
> @@ -455,6 +459,8 @@ static int kvm_sbi_ext_fwft_get_reg_id(struct kvm_vcpu 
> *vcpu, int index, u64 *re
>                 conf = kvm_sbi_fwft_get_config(vcpu, feature->id);
>                 if (!conf || !conf->supported)
>                         continue;
> +               else if (conf->feature->supported && 
> !conf->feature->supported(vcpu))
> +                       continue;
>
>                 if (index == idx) {
>                         *reg_id = KVM_REG_RISCV |
> @@ -490,6 +496,8 @@ static int kvm_sbi_ext_fwft_get_reg(struct kvm_vcpu 
> *vcpu, unsigned long reg_num
>         conf = kvm_sbi_fwft_get_config(vcpu, feature->id);
>         if (!conf || !conf->supported)
>                 return -ENOENT;
> +       else if (conf->feature->supported && !conf->feature->supported(vcpu))
> +               return -ENOENT;
>
>         switch (reg_num - feature->first_reg_num) {
>         case 0:
> @@ -527,6 +535,8 @@ static int kvm_sbi_ext_fwft_set_reg(struct kvm_vcpu 
> *vcpu, unsigned long reg_num
>         conf = kvm_sbi_fwft_get_config(vcpu, feature->id);
>         if (!conf || !conf->supported)
>                 return -ENOENT;
> +       else if (conf->feature->supported && !conf->feature->supported(vcpu))
> +               return -ENOENT;
>
>         switch (reg_num - feature->first_reg_num) {
>         case 0:
>
> --
> 2.43.7
>

Reply via email to