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
Remove the redundant static 'supported' field from kvm_sbi_fwft_config
and replace all conf->supported checks with feature->supported(vcpu)
calls that check the current vCPU ISA extension state. This can ensure
the feature availability is always determined at runtime based on the
current configuration, not initialization-time snapshots.
Fixes: 6b72fd170592 ("RISC-V: KVM: add support for FWFT SBI extension")
Signed-off-by: Yong-Xuan Wang <[email protected]>
---
arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h | 1 -
arch/riscv/kvm/vcpu_sbi_fwft.c | 17 ++++++++---------
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
index 5604cec79902..837431867c6f 100644
--- a/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
+++ b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
@@ -15,7 +15,6 @@ struct kvm_sbi_fwft_feature;
struct kvm_sbi_fwft_config {
const struct kvm_sbi_fwft_feature *feature;
- bool supported;
bool enabled;
unsigned long flags;
};
diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
index 2eab15339694..d3be059c3822 100644
--- a/arch/riscv/kvm/vcpu_sbi_fwft.c
+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
@@ -279,8 +279,8 @@ static int kvm_fwft_get_feature(struct kvm_vcpu *vcpu, u32
feature,
return SBI_ERR_DENIED;
}
- if (!tconf->supported || !tconf->enabled)
- return SBI_ERR_NOT_SUPPORTED;
+ if (!tconf->feature->supported(vcpu))
+ return SBI_ERR_NOT_SUPPORTED;
*conf = tconf;
@@ -361,11 +361,10 @@ static int kvm_sbi_ext_fwft_init(struct kvm_vcpu *vcpu)
feature = &features[i];
conf = &fwft->configs[i];
if (feature->supported)
- conf->supported = feature->supported(vcpu);
+ conf->enabled = feature->supported(vcpu);
else
- conf->supported = true;
+ conf->enabled = true;
- conf->enabled = conf->supported;
conf->feature = feature;
}
@@ -406,7 +405,7 @@ static unsigned long kvm_sbi_ext_fwft_get_reg_count(struct
kvm_vcpu *vcpu)
continue;
conf = kvm_sbi_fwft_get_config(vcpu, feature->id);
- if (!conf || !conf->supported)
+ if (!conf || !feature->supported(vcpu))
continue;
ret++;
@@ -428,7 +427,7 @@ static int kvm_sbi_ext_fwft_get_reg_id(struct kvm_vcpu
*vcpu, int index, u64 *re
continue;
conf = kvm_sbi_fwft_get_config(vcpu, feature->id);
- if (!conf || !conf->supported)
+ if (!conf || !feature->supported(vcpu))
continue;
if (index == idx) {
@@ -463,7 +462,7 @@ static int kvm_sbi_ext_fwft_get_reg(struct kvm_vcpu *vcpu,
unsigned long reg_num
return -ENOENT;
conf = kvm_sbi_fwft_get_config(vcpu, feature->id);
- if (!conf || !conf->supported)
+ if (!conf || !feature->supported(vcpu))
return -ENOENT;
switch (reg_num - feature->first_reg_num) {
@@ -500,7 +499,7 @@ static int kvm_sbi_ext_fwft_set_reg(struct kvm_vcpu *vcpu,
unsigned long reg_num
return -ENOENT;
conf = kvm_sbi_fwft_get_config(vcpu, feature->id);
- if (!conf || !conf->supported)
+ if (!conf || !feature->supported(vcpu))
return -ENOENT;
switch (reg_num - feature->first_reg_num) {
--
2.43.7