Hardware updating of PTE A/D bits is controlled through ADUE bit in
henvcfg Expose the feature only if the Svadu is supported for VS-mode.
Allow the VMM to block access to the feature by disabling the ISA
extension in the guest.

Assisted-by: YuanSheng:claude-4.7-opus
Co-developed-by: Quan Zhou <[email protected]>
Signed-off-by: Quan Zhou <[email protected]>
Signed-off-by: Inochi Amaoto <[email protected]>
---
 arch/riscv/include/uapi/asm/kvm.h |  3 ++
 arch/riscv/kvm/vcpu_sbi_fwft.c    | 72 +++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+)

diff --git a/arch/riscv/include/uapi/asm/kvm.h 
b/arch/riscv/include/uapi/asm/kvm.h
index 504e73305343..501e4fc60dd2 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -240,6 +240,9 @@ struct kvm_riscv_sbi_fwft_feature {
 struct kvm_riscv_sbi_fwft {
        struct kvm_riscv_sbi_fwft_feature misaligned_deleg;
        struct kvm_riscv_sbi_fwft_feature pointer_masking;
+       struct kvm_riscv_sbi_fwft_feature pte_ad_hw_updating;
+       struct kvm_riscv_sbi_fwft_feature landing_pad;
+       struct kvm_riscv_sbi_fwft_feature shadow_stack;
 };
 
 /* If you need to interpret the index values, here is the key: */
diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
index 2eab15339694..375269e43c13 100644
--- a/arch/riscv/kvm/vcpu_sbi_fwft.c
+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
@@ -84,6 +84,42 @@ static bool kvm_fwft_is_defined_feature(enum 
sbi_fwft_feature_t feature)
        return false;
 }
 
+static void kvm_sbi_fwft_env_flag_reset_helper(struct kvm_vcpu *vcpu,
+                                              unsigned long flag)
+{
+       vcpu->arch.cfg.henvcfg &= ~flag;
+}
+
+static long kvm_sbi_fwft_env_flag_set_helper(struct kvm_vcpu *vcpu,
+                                            struct kvm_sbi_fwft_config *conf,
+                                            bool one_reg_access,
+                                            unsigned long value, unsigned long 
flag)
+{
+       struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
+
+       if (value == 0)
+               cfg->henvcfg &= ~flag;
+       else if (value == 1)
+               cfg->henvcfg |= flag;
+       else
+               return SBI_ERR_INVALID_PARAM;
+
+       if (!one_reg_access)
+               csr_write(CSR_HENVCFG, vcpu->arch.cfg.henvcfg);
+
+       return SBI_SUCCESS;
+}
+
+static long kvm_sbi_fwft_env_flag_get_helper(struct kvm_vcpu *vcpu,
+                                            struct kvm_sbi_fwft_config *conf,
+                                            bool one_reg_access,
+                                            unsigned long *value, unsigned 
long flag)
+{
+       *value = (vcpu->arch.cfg.henvcfg & flag) == flag;
+
+       return SBI_SUCCESS;
+}
+
 static bool kvm_sbi_fwft_misaligned_delegation_supported(struct kvm_vcpu *vcpu)
 {
        return misaligned_traps_can_delegate();
@@ -127,6 +163,33 @@ static long kvm_sbi_fwft_get_misaligned_delegation(struct 
kvm_vcpu *vcpu,
        return SBI_SUCCESS;
 }
 
+static bool kvm_sbi_fwft_pte_ad_hw_updating_supported(struct kvm_vcpu *vcpu)
+{
+       return riscv_isa_extension_available(vcpu->arch.isa, SVADU) &&
+               !riscv_isa_extension_available(vcpu->arch.isa, SVADE);
+}
+
+static void kvm_sbi_fwft_reset_pte_ad_hw_updating(struct kvm_vcpu *vcpu)
+{
+       kvm_sbi_fwft_env_flag_reset_helper(vcpu, ENVCFG_ADUE);
+}
+
+static long kvm_sbi_fwft_set_pte_ad_hw_updating(struct kvm_vcpu *vcpu,
+                                               struct kvm_sbi_fwft_config 
*conf,
+                                               bool one_reg_access, unsigned 
long value)
+{
+       return kvm_sbi_fwft_env_flag_set_helper(vcpu, conf, one_reg_access,
+                                               value, ENVCFG_ADUE);
+}
+
+static long kvm_sbi_fwft_get_pte_ad_hw_updating(struct kvm_vcpu *vcpu,
+                                               struct kvm_sbi_fwft_config 
*conf,
+                                               bool one_reg_access, unsigned 
long *value)
+{
+       return kvm_sbi_fwft_env_flag_get_helper(vcpu, conf, one_reg_access,
+                                               value, ENVCFG_ADUE);
+}
+
 #ifndef CONFIG_32BIT
 
 static bool try_to_set_pmm(unsigned long value)
@@ -225,6 +288,15 @@ static const struct kvm_sbi_fwft_feature features[] = {
                .set = kvm_sbi_fwft_set_misaligned_delegation,
                .get = kvm_sbi_fwft_get_misaligned_delegation,
        },
+       {
+               .id = SBI_FWFT_PTE_AD_HW_UPDATING,
+               .first_reg_num = offsetof(struct kvm_riscv_sbi_fwft, 
pte_ad_hw_updating.enable) /
+                                sizeof(unsigned long),
+               .supported = kvm_sbi_fwft_pte_ad_hw_updating_supported,
+               .reset = kvm_sbi_fwft_reset_pte_ad_hw_updating,
+               .set = kvm_sbi_fwft_set_pte_ad_hw_updating,
+               .get = kvm_sbi_fwft_get_pte_ad_hw_updating,
+       },
 #ifndef CONFIG_32BIT
        {
                .id = SBI_FWFT_POINTER_MASKING_PMLEN,
-- 
2.54.0


Reply via email to