* [PATCH v5 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support
@ 2026-07-06 2:20 Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 1/8] RISC-V: KVM: Add support for Svadu FWFT features Inochi Amaoto
` (7 more replies)
0 siblings, 8 replies; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-06 2:20 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan,
Charlie Jenkins, Sergey Matyukevich, Thomas Huth, Inochi Amaoto,
Deepak Gupta
Cc: linux-riscv, linux-kernel, kvm, kvm-riscv, linux-kselftest,
Yixun Lan, Longbin Li
This patchset based on the patchset "RISC-V: KVM: Add Zicfiss/Zicfilp
support".
The patch includes all the function of original patchset from Quan:
adding the Svadu/Zicfiss/Zicfilp FWFT for the RISC-V KVM. And this
patchset already passes the KVM unit test.
Test with the patch applied
https://lore.kernel.org/all/20260618064406.14508-1-cuiyunhui@bytedance.com/
Changed from v4:
patch 1:
1. Use NACL for csr update
2. Check ISA mapping before cleaning the ADUE bit
patch 4:
1. Clear the zicfiss csr during a VCPU reset
2. Add zicfiss csr to num_csr_regs()
patch 6:
1. Cleanup SPELP after redirecting the trap
patch 7:
1. Use interrupt bit instead of number for masking/unmasking
patch 8:
1. Add missing entry for the test
2. Fix the wrong comment.
Changed from v3:
- https://lore.kernel.org/kvm/20260607081105.993908-1-inochiama@gmail.com/
1. rebase to the v7.2-rc1
2. Tested with the updated Svadu patch
3. Remove the dependency as it is already merged.
Changed from v2:
- https://lore.kernel.org/kvm/20260601084336.2601675-1-inochiama@gmail.com/
1. rebase with Yong-Xuan's patch set
2. Add SSP CSR context switch/set/get
3. Move the software-check exception set/unset into FWFT
4. Only delegate software-check exception when Zicfiss/Zicfilp is enabled.
5. Make KVM SBI_FWFT_PTE_AD_HW_UPDATING depends on both Svadu and Svade
enabled.
Changed from Quan's v1:
- https://lore.kernel.org/kvm/cover.1764509485.git.zhouquan@iscas.ac.cn/
1. rebase to the latest master.
2. Split Svadu change as separate patch
3. Fix all build error from the original series
4. Remove the Svadu check in kvm_riscv_vcpu_config_ran_once() and in
favor of the FWFT.
5. Remove the LPE/SSE setting bit in kvm_riscv_vcpu_config_ran_once()
(kvm_riscv_vcpu_setup_config() in original patchset)
Inochi Amaoto (8):
RISC-V: KVM: Add support for Svadu FWFT features
KVM: riscv: selftests: add Svadu FWFT extension to get-reg-list test
RISC-V: KVM: Allow Zicfiss/Zicfilp extensions for Guest/VM
RISC-V: KVM: Add ssp context save/restore
RISC-V: KVM: Handle software-check exits for VCPU
RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is
enabled.
RISC-V: KVM: Add support for control-flow integrity FWFT features
KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list
test
arch/riscv/include/asm/csr.h | 1 +
arch/riscv/include/asm/kvm_host.h | 7 +
arch/riscv/include/uapi/asm/kvm.h | 13 ++
arch/riscv/kvm/isa.c | 2 +
arch/riscv/kvm/vcpu.c | 7 +
arch/riscv/kvm/vcpu_exit.c | 11 ++
arch/riscv/kvm/vcpu_onereg.c | 68 ++++++-
arch/riscv/kvm/vcpu_sbi_fwft.c | 184 ++++++++++++++++++
.../selftests/kvm/riscv/get-reg-list.c | 90 +++++++++
9 files changed, 381 insertions(+), 2 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v5 1/8] RISC-V: KVM: Add support for Svadu FWFT features
2026-07-06 2:20 [PATCH v5 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
@ 2026-07-06 2:20 ` Inochi Amaoto
2026-07-07 2:46 ` Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 2/8] KVM: riscv: selftests: add Svadu FWFT extension to get-reg-list test Inochi Amaoto
` (6 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-06 2:20 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan,
Charlie Jenkins, Sergey Matyukevich, Thomas Huth, Inochi Amaoto,
Deepak Gupta
Cc: linux-riscv, linux-kernel, kvm, kvm-riscv, linux-kselftest,
Yixun Lan, Longbin Li, Quan Zhou
Hardware updating of PTE A/D bits is controlled through ADUE bit in
henvcfg Expose the feature only if both Svadu and Svade are supported
for VS-mode.
Allow the VMM to enable/disable this feature by change the ISA
extension state in the guest.
Assisted-by: YuanSheng:claude-4.7-opus
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
arch/riscv/include/uapi/asm/kvm.h | 1 +
arch/riscv/kvm/vcpu_sbi_fwft.c | 77 +++++++++++++++++++++++++++++++
2 files changed, 78 insertions(+)
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index 504e73305343..7bbea8812d92 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -240,6 +240,7 @@ 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;
};
/* 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 ab39ac464ffd..01db40b53295 100644
--- a/arch/riscv/kvm/vcpu_sbi_fwft.c
+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
@@ -11,6 +11,7 @@
#include <linux/kvm_host.h>
#include <asm/cpufeature.h>
#include <asm/sbi.h>
+#include <asm/kvm_nacl.h>
#include <asm/kvm_vcpu_sbi.h>
#include <asm/kvm_vcpu_sbi_fwft.h>
@@ -94,6 +95,45 @@ 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,
+ u64 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, u64 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) {
+ ncsr_write(CSR_HENVCFG, vcpu->arch.cfg.henvcfg);
+ if (IS_ENABLED(CONFIG_32BIT))
+ ncsr_write(CSR_HENVCFGH, vcpu->arch.cfg.henvcfg >> 32);
+ }
+
+ 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, u64 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();
@@ -137,6 +177,34 @@ 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)
+{
+ if (kvm_sbi_fwft_pte_ad_hw_updating_supported(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)
@@ -246,6 +314,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.55.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v5 2/8] KVM: riscv: selftests: add Svadu FWFT extension to get-reg-list test
2026-07-06 2:20 [PATCH v5 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 1/8] RISC-V: KVM: Add support for Svadu FWFT features Inochi Amaoto
@ 2026-07-06 2:20 ` Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 3/8] RISC-V: KVM: Allow Zicfiss/Zicfilp extensions for Guest/VM Inochi Amaoto
` (5 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-06 2:20 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan,
Charlie Jenkins, Sergey Matyukevich, Thomas Huth, Inochi Amaoto,
Deepak Gupta
Cc: linux-riscv, linux-kernel, kvm, kvm-riscv, linux-kselftest,
Yixun Lan, Longbin Li, Quan Zhou
The KVM RISC-V allows Svadu FWFT for Guest/VM so add this extension
to get-reg-list test.
Assisted-by: YuanSheng:claude-4.7-opus
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
.../selftests/kvm/riscv/get-reg-list.c | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/tools/testing/selftests/kvm/riscv/get-reg-list.c b/tools/testing/selftests/kvm/riscv/get-reg-list.c
index cb86cb6b3635..94e33b2ee796 100644
--- a/tools/testing/selftests/kvm/riscv/get-reg-list.c
+++ b/tools/testing/selftests/kvm/riscv/get-reg-list.c
@@ -745,6 +745,9 @@ static const char *sbi_fwft_id_to_str(__u64 reg_off)
case 3: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pointer_masking.enable)";
case 4: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pointer_masking.flags)";
case 5: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pointer_masking.value)";
+ case 6: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pte_ad_hw_updating.enable)";
+ case 7: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pte_ad_hw_updating.flags)";
+ case 8: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pte_ad_hw_updating.value)";
}
return strdup_printf("KVM_REG_RISCV_SBI_FWFT | %lld /* UNKNOWN */", reg_off);
}
@@ -944,6 +947,13 @@ static __u64 sbi_fwft_pointer_masking_regs[] = {
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pointer_masking.value),
};
+static __u64 sbi_fwft_pte_ad_hw_updating_regs[] = {
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_FWFT,
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pte_ad_hw_updating.enable),
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pte_ad_hw_updating.flags),
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pte_ad_hw_updating.value),
+};
+
static __u64 zicbom_regs[] = {
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_CONFIG | KVM_REG_RISCV_CONFIG_REG(zicbom_block_size),
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICBOM,
@@ -1259,6 +1269,16 @@ static struct vcpu_reg_list config_sbi_fwft_pointer_masking = {
},
};
+static struct vcpu_reg_list config_sbi_fwft_pte_ad_hw_updating = {
+ .sublists = {
+ SUBLIST_BASE,
+ SUBLIST_ISA(svade, SVADE),
+ SUBLIST_ISA(svadu, SVADU),
+ SUBLIST_SBI(fwft_pte_ad_hw_updating, FWFT),
+ {0},
+ },
+};
+
struct vcpu_reg_list *vcpu_configs[] = {
&config_sbi_base,
&config_sbi_sta,
@@ -1268,6 +1288,7 @@ struct vcpu_reg_list *vcpu_configs[] = {
&config_sbi_mpxy,
&config_sbi_fwft_misaligned_deleg,
&config_sbi_fwft_pointer_masking,
+ &config_sbi_fwft_pte_ad_hw_updating,
&config_aia,
&config_fp_f,
&config_fp_d,
--
2.55.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v5 3/8] RISC-V: KVM: Allow Zicfiss/Zicfilp extensions for Guest/VM
2026-07-06 2:20 [PATCH v5 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 1/8] RISC-V: KVM: Add support for Svadu FWFT features Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 2/8] KVM: riscv: selftests: add Svadu FWFT extension to get-reg-list test Inochi Amaoto
@ 2026-07-06 2:20 ` Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 4/8] RISC-V: KVM: Add ssp context save/restore Inochi Amaoto
` (4 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-06 2:20 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan,
Charlie Jenkins, Sergey Matyukevich, Thomas Huth, Inochi Amaoto,
Deepak Gupta
Cc: linux-riscv, linux-kernel, kvm, kvm-riscv, linux-kselftest,
Yixun Lan, Longbin Li, Quan Zhou
Extend the KVM ISA extension array to allow KVM userspace to
detect and enable Zicfiss/Zicfilp extensions for Guest/VM.
Assisted-by: YuanSheng:claude-4.7-opus
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
arch/riscv/include/uapi/asm/kvm.h | 2 ++
arch/riscv/kvm/isa.c | 2 ++
2 files changed, 4 insertions(+)
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index 7bbea8812d92..a27de850fa4c 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -199,6 +199,8 @@ enum KVM_RISCV_ISA_EXT_ID {
KVM_RISCV_ISA_EXT_ZCLSD,
KVM_RISCV_ISA_EXT_ZILSD,
KVM_RISCV_ISA_EXT_ZALASR,
+ KVM_RISCV_ISA_EXT_ZICFILP,
+ KVM_RISCV_ISA_EXT_ZICFISS,
KVM_RISCV_ISA_EXT_MAX,
};
diff --git a/arch/riscv/kvm/isa.c b/arch/riscv/kvm/isa.c
index 1132d909cc25..9852a91fdecc 100644
--- a/arch/riscv/kvm/isa.c
+++ b/arch/riscv/kvm/isa.c
@@ -65,6 +65,8 @@ static const unsigned long kvm_isa_ext_arr[] = {
KVM_ISA_EXT_ARR(ZICBOP),
KVM_ISA_EXT_ARR(ZICBOZ),
KVM_ISA_EXT_ARR(ZICCRSE),
+ KVM_ISA_EXT_ARR(ZICFILP),
+ KVM_ISA_EXT_ARR(ZICFISS),
KVM_ISA_EXT_ARR(ZICNTR),
KVM_ISA_EXT_ARR(ZICOND),
KVM_ISA_EXT_ARR(ZICSR),
--
2.55.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v5 4/8] RISC-V: KVM: Add ssp context save/restore
2026-07-06 2:20 [PATCH v5 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
` (2 preceding siblings ...)
2026-07-06 2:20 ` [PATCH v5 3/8] RISC-V: KVM: Allow Zicfiss/Zicfilp extensions for Guest/VM Inochi Amaoto
@ 2026-07-06 2:20 ` Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 5/8] RISC-V: KVM: Handle software-check exits for VCPU Inochi Amaoto
` (3 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-06 2:20 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan,
Charlie Jenkins, Sergey Matyukevich, Thomas Huth, Inochi Amaoto,
Deepak Gupta
Cc: linux-riscv, linux-kernel, kvm, kvm-riscv, linux-kselftest,
Yixun Lan, Longbin Li
Add ssp context save/restore for guest VCPUs and also add it to the
ONE_REG interface to allow its access from user space.
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
arch/riscv/include/asm/kvm_host.h | 7 ++++
arch/riscv/include/uapi/asm/kvm.h | 8 ++++
arch/riscv/kvm/vcpu.c | 7 ++++
arch/riscv/kvm/vcpu_onereg.c | 68 ++++++++++++++++++++++++++++++-
4 files changed, 88 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
index 60017ceec9d2..e5ed3b0e5a55 100644
--- a/arch/riscv/include/asm/kvm_host.h
+++ b/arch/riscv/include/asm/kvm_host.h
@@ -163,6 +163,10 @@ struct kvm_vcpu_smstateen_csr {
unsigned long sstateen0;
};
+struct kvm_vcpu_zicfiss_csr {
+ unsigned long ssp;
+};
+
struct kvm_vcpu_reset_state {
spinlock_t lock;
unsigned long pc;
@@ -203,6 +207,9 @@ struct kvm_vcpu_arch {
/* CPU Smstateen CSR context of Guest VCPU */
struct kvm_vcpu_smstateen_csr smstateen_csr;
+ /* CPU Zicfiss CSR context of Guest VCPU */
+ struct kvm_vcpu_zicfiss_csr zicfiss_csr;
+
/* CPU reset state of Guest VCPU */
struct kvm_vcpu_reset_state reset_state;
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index a27de850fa4c..fd4c81697617 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -102,6 +102,11 @@ struct kvm_riscv_smstateen_csr {
unsigned long sstateen0;
};
+/* Zicfiss CSR for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
+struct kvm_riscv_zicfiss_csr {
+ unsigned long ssp;
+};
+
/* TIMER registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
struct kvm_riscv_timer {
__u64 frequency;
@@ -266,12 +271,15 @@ struct kvm_riscv_sbi_fwft {
#define KVM_REG_RISCV_CSR_GENERAL (0x0 << KVM_REG_RISCV_SUBTYPE_SHIFT)
#define KVM_REG_RISCV_CSR_AIA (0x1 << KVM_REG_RISCV_SUBTYPE_SHIFT)
#define KVM_REG_RISCV_CSR_SMSTATEEN (0x2 << KVM_REG_RISCV_SUBTYPE_SHIFT)
+#define KVM_REG_RISCV_CSR_ZICFISS (0x3 << KVM_REG_RISCV_SUBTYPE_SHIFT)
#define KVM_REG_RISCV_CSR_REG(name) \
(offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long))
#define KVM_REG_RISCV_CSR_AIA_REG(name) \
(offsetof(struct kvm_riscv_aia_csr, name) / sizeof(unsigned long))
#define KVM_REG_RISCV_CSR_SMSTATEEN_REG(name) \
(offsetof(struct kvm_riscv_smstateen_csr, name) / sizeof(unsigned long))
+#define KVM_REG_RISCV_CSR_ZICFISS_REG(name) \
+ (offsetof(struct kvm_riscv_zicfiss_csr, name) / sizeof(unsigned long))
/* Timer registers are mapped as type 4 */
#define KVM_REG_RISCV_TIMER (0x04 << KVM_REG_RISCV_TYPE_SHIFT)
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index cf6e231e76e2..acdb12fcdb69 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -63,6 +63,7 @@ static void kvm_riscv_vcpu_context_reset(struct kvm_vcpu *vcpu,
memset(cntx, 0, sizeof(*cntx));
memset(csr, 0, sizeof(*csr));
memset(&vcpu->arch.smstateen_csr, 0, sizeof(vcpu->arch.smstateen_csr));
+ memset(&vcpu->arch.zicfiss_csr, 0, sizeof(vcpu->arch.zicfiss_csr));
/* Restore datap as it's not a part of the guest context. */
cntx->vector.datap = vector_datap;
@@ -720,6 +721,7 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu)
static __always_inline void kvm_riscv_vcpu_swap_in_guest_state(struct kvm_vcpu *vcpu)
{
+ struct kvm_vcpu_zicfiss_csr *zicficsr = &vcpu->arch.zicfiss_csr;
struct kvm_vcpu_smstateen_csr *smcsr = &vcpu->arch.smstateen_csr;
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
@@ -727,10 +729,13 @@ static __always_inline void kvm_riscv_vcpu_swap_in_guest_state(struct kvm_vcpu *
vcpu->arch.host_senvcfg = csr_swap(CSR_SENVCFG, csr->senvcfg);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN))
vcpu->arch.host_sstateen0 = csr_swap(CSR_SSTATEEN0, smcsr->sstateen0);
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICFISS))
+ csr_write(CSR_SSP, zicficsr->ssp);
}
static __always_inline void kvm_riscv_vcpu_swap_in_host_state(struct kvm_vcpu *vcpu)
{
+ struct kvm_vcpu_zicfiss_csr *zicficsr = &vcpu->arch.zicfiss_csr;
struct kvm_vcpu_smstateen_csr *smcsr = &vcpu->arch.smstateen_csr;
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
@@ -738,6 +743,8 @@ static __always_inline void kvm_riscv_vcpu_swap_in_host_state(struct kvm_vcpu *v
csr->senvcfg = csr_swap(CSR_SENVCFG, vcpu->arch.host_senvcfg);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN))
smcsr->sstateen0 = csr_swap(CSR_SSTATEEN0, vcpu->arch.host_sstateen0);
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICFISS))
+ zicficsr->ssp = csr_swap(CSR_SSP, 0);
}
/*
diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index bb920e8923c9..dd9519438546 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -355,6 +355,44 @@ static int kvm_riscv_vcpu_smstateen_get_csr(struct kvm_vcpu *vcpu,
return 0;
}
+static inline int kvm_riscv_vcpu_zicfiss_set_csr(struct kvm_vcpu *vcpu,
+ unsigned long reg_num,
+ unsigned long reg_val)
+{
+ struct kvm_vcpu_zicfiss_csr *csr = &vcpu->arch.zicfiss_csr;
+ unsigned long regs_max = sizeof(struct kvm_vcpu_zicfiss_csr) /
+ sizeof(unsigned long);
+
+ if (!riscv_isa_extension_available(vcpu->arch.isa, ZICFISS))
+ return -ENOENT;
+ if (reg_num >= regs_max)
+ return -ENOENT;
+
+ reg_num = array_index_nospec(reg_num, regs_max);
+
+ ((unsigned long *)csr)[reg_num] = reg_val;
+ return 0;
+}
+
+static int kvm_riscv_vcpu_zicfiss_get_csr(struct kvm_vcpu *vcpu,
+ unsigned long reg_num,
+ unsigned long *out_val)
+{
+ struct kvm_vcpu_zicfiss_csr *csr = &vcpu->arch.zicfiss_csr;
+ unsigned long regs_max = sizeof(struct kvm_vcpu_zicfiss_csr) /
+ sizeof(unsigned long);
+
+ if (!riscv_isa_extension_available(vcpu->arch.isa, ZICFISS))
+ return -ENOENT;
+ if (reg_num >= regs_max)
+ return -ENOENT;
+
+ reg_num = array_index_nospec(reg_num, regs_max);
+
+ *out_val = ((unsigned long *)csr)[reg_num];
+ return 0;
+}
+
static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg)
{
@@ -381,6 +419,9 @@ static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
case KVM_REG_RISCV_CSR_SMSTATEEN:
rc = kvm_riscv_vcpu_smstateen_get_csr(vcpu, reg_num, ®_val);
break;
+ case KVM_REG_RISCV_CSR_ZICFISS:
+ rc = kvm_riscv_vcpu_zicfiss_get_csr(vcpu, reg_num, ®_val);
+ break;
default:
rc = -ENOENT;
break;
@@ -423,6 +464,9 @@ static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu,
case KVM_REG_RISCV_CSR_SMSTATEEN:
rc = kvm_riscv_vcpu_smstateen_set_csr(vcpu, reg_num, reg_val);
break;
+ case KVM_REG_RISCV_CSR_ZICFISS:
+ rc = kvm_riscv_vcpu_zicfiss_set_csr(vcpu, reg_num, reg_val);
+ break;
default:
rc = -ENOENT;
break;
@@ -680,6 +724,8 @@ static inline unsigned long num_csr_regs(const struct kvm_vcpu *vcpu)
n += sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long);
if (riscv_isa_extension_available(vcpu->arch.isa, SMSTATEEN))
n += sizeof(struct kvm_riscv_smstateen_csr) / sizeof(unsigned long);
+ if (riscv_isa_extension_available(vcpu->arch.isa, ZICFISS))
+ n += sizeof(struct kvm_riscv_zicfiss_csr) / sizeof(unsigned long);
return n;
}
@@ -688,7 +734,7 @@ static int copy_csr_reg_indices(const struct kvm_vcpu *vcpu,
u64 __user *uindices)
{
int n1 = sizeof(struct kvm_riscv_csr) / sizeof(unsigned long);
- int n2 = 0, n3 = 0;
+ int n2 = 0, n3 = 0, n4 = 0;
/* copy general csr regs */
for (int i = 0; i < n1; i++) {
@@ -740,7 +786,25 @@ static int copy_csr_reg_indices(const struct kvm_vcpu *vcpu,
}
}
- return n1 + n2 + n3;
+ /* copy Zicfiss csr regs */
+ if (riscv_isa_extension_available(vcpu->arch.isa, ZICFISS)) {
+ n4 = sizeof(struct kvm_riscv_zicfiss_csr) / sizeof(unsigned long);
+
+ for (int i = 0; i < n4; i++) {
+ u64 size = IS_ENABLED(CONFIG_32BIT) ?
+ KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64;
+ u64 reg = KVM_REG_RISCV | size | KVM_REG_RISCV_CSR |
+ KVM_REG_RISCV_CSR_ZICFISS | i;
+
+ if (uindices) {
+ if (put_user(reg, uindices))
+ return -EFAULT;
+ uindices++;
+ }
+ }
+ }
+
+ return n1 + n2 + n3 + n4;
}
static inline unsigned long num_timer_regs(void)
--
2.55.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v5 5/8] RISC-V: KVM: Handle software-check exits for VCPU
2026-07-06 2:20 [PATCH v5 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
` (3 preceding siblings ...)
2026-07-06 2:20 ` [PATCH v5 4/8] RISC-V: KVM: Add ssp context save/restore Inochi Amaoto
@ 2026-07-06 2:20 ` Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 6/8] RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled Inochi Amaoto
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-06 2:20 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan,
Charlie Jenkins, Sergey Matyukevich, Thomas Huth, Inochi Amaoto,
Deepak Gupta
Cc: linux-riscv, linux-kernel, kvm, kvm-riscv, linux-kselftest,
Yixun Lan, Longbin Li, Quan Zhou
The extension Zicfiss/Zicfilp introduces a software-check exception
to the privilege architecture. Delegate this exception to VS mode
when vCPU enable Zicfiss/Zicfilp so the CFI violations in VU/VS could
be reported.
Assisted-by: YuanSheng:claude-4.7-opus
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
arch/riscv/include/asm/csr.h | 1 +
arch/riscv/kvm/vcpu_exit.c | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 31b8988f4488..224af9facf1f 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -117,6 +117,7 @@
#define EXC_INST_PAGE_FAULT 12
#define EXC_LOAD_PAGE_FAULT 13
#define EXC_STORE_PAGE_FAULT 15
+#define EXC_SOFTWARE_CHECK 18
#define EXC_INST_GUEST_PAGE_FAULT 20
#define EXC_LOAD_GUEST_PAGE_FAULT 21
#define EXC_VIRTUAL_INST_FAULT 22
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 0bb0c51e3c89..12eebeabdf14 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -243,6 +243,10 @@ int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
run->exit_reason = KVM_EXIT_DEBUG;
ret = 0;
break;
+ case EXC_SOFTWARE_CHECK:
+ if (vcpu->arch.cfg.henvcfg & (ENVCFG_LPE | ENVCFG_SSE))
+ ret = vcpu_redirect(vcpu, trap);
+ break;
default:
break;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v5 6/8] RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled.
2026-07-06 2:20 [PATCH v5 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
` (4 preceding siblings ...)
2026-07-06 2:20 ` [PATCH v5 5/8] RISC-V: KVM: Handle software-check exits for VCPU Inochi Amaoto
@ 2026-07-06 2:20 ` Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 7/8] RISC-V: KVM: Add support for control-flow integrity FWFT features Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 8/8] KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test Inochi Amaoto
7 siblings, 0 replies; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-06 2:20 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan,
Charlie Jenkins, Sergey Matyukevich, Thomas Huth, Inochi Amaoto,
Deepak Gupta
Cc: linux-riscv, linux-kernel, kvm, kvm-riscv, linux-kselftest,
Yixun Lan, Longbin Li
Delegate the newly added SPELP bit from Zicfilp extension to VS/VU mode
if it enables landing pad support.
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
arch/riscv/kvm/vcpu_exit.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 12eebeabdf14..92a3ea7c7ffb 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -154,6 +154,13 @@ void kvm_riscv_vcpu_trap_redirect(struct kvm_vcpu *vcpu,
/* Clear Guest SSTATUS.SIE bit */
vsstatus &= ~SR_SIE;
+ /* Change Guest SSTATUS.SPELP bit */
+ if (vcpu->arch.cfg.henvcfg & ENVCFG_LPE) {
+ vsstatus &= ~SR_SPELP;
+ vsstatus |= vcpu->arch.guest_context.sstatus & SR_SPELP;
+ vcpu->arch.guest_context.sstatus &= ~SR_SPELP;
+ }
+
/* Update Guest SSTATUS */
ncsr_write(CSR_VSSTATUS, vsstatus);
--
2.55.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v5 7/8] RISC-V: KVM: Add support for control-flow integrity FWFT features
2026-07-06 2:20 [PATCH v5 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
` (5 preceding siblings ...)
2026-07-06 2:20 ` [PATCH v5 6/8] RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled Inochi Amaoto
@ 2026-07-06 2:20 ` Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 8/8] KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test Inochi Amaoto
7 siblings, 0 replies; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-06 2:20 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan,
Charlie Jenkins, Sergey Matyukevich, Thomas Huth, Inochi Amaoto,
Deepak Gupta
Cc: linux-riscv, linux-kernel, kvm, kvm-riscv, linux-kselftest,
Yixun Lan, Longbin Li, Quan Zhou
Control-flow integrity is controlled through a WARL field in henvcfg.
Expose the feature only if the Zicfilp/Zicfiss 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 <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
arch/riscv/include/uapi/asm/kvm.h | 2 +
arch/riscv/kvm/vcpu_sbi_fwft.c | 107 ++++++++++++++++++++++++++++++
2 files changed, 109 insertions(+)
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index fd4c81697617..20d9959ca44f 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -248,6 +248,8 @@ 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 01db40b53295..bc514ae6521d 100644
--- a/arch/riscv/kvm/vcpu_sbi_fwft.c
+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
@@ -177,6 +177,95 @@ static long kvm_sbi_fwft_get_misaligned_delegation(struct kvm_vcpu *vcpu,
return SBI_SUCCESS;
}
+static long kvm_sbi_fwft_set_cfi(struct kvm_vcpu *vcpu,
+ struct kvm_sbi_fwft_config *conf,
+ bool one_reg_access, unsigned long value,
+ u64 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 (cfg->henvcfg & (ENVCFG_LPE | ENVCFG_SSE))
+ cfg->hedeleg |= BIT(EXC_SOFTWARE_CHECK);
+ else
+ cfg->hedeleg &= ~BIT(EXC_SOFTWARE_CHECK);
+
+ if (!one_reg_access) {
+ ncsr_write(CSR_HEDELEG, cfg->hedeleg);
+ /*
+ * Both Bit LPE and SSE are in the lower part, so it is safe
+ * to only write the henvcfg
+ */
+ ncsr_write(CSR_HENVCFG, vcpu->arch.cfg.henvcfg);
+ }
+
+ return SBI_SUCCESS;
+}
+
+static bool kvm_sbi_fwft_landing_pad_supported(struct kvm_vcpu *vcpu)
+{
+ return riscv_isa_extension_available(vcpu->arch.isa, ZICFILP);
+}
+
+static void kvm_sbi_fwft_reset_landing_pad(struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
+
+ kvm_sbi_fwft_env_flag_reset_helper(vcpu, ENVCFG_LPE);
+ if ((cfg->henvcfg & (ENVCFG_LPE | ENVCFG_SSE)) == 0)
+ cfg->hedeleg &= ~BIT(EXC_SOFTWARE_CHECK);
+}
+
+static long kvm_sbi_fwft_set_landing_pad(struct kvm_vcpu *vcpu,
+ struct kvm_sbi_fwft_config *conf,
+ bool one_reg_access, unsigned long value)
+{
+ return kvm_sbi_fwft_set_cfi(vcpu, conf, one_reg_access, value, ENVCFG_LPE);
+}
+
+static long kvm_sbi_fwft_get_landing_pad(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_LPE);
+}
+
+static bool kvm_sbi_fwft_shadow_stack_supported(struct kvm_vcpu *vcpu)
+{
+ return riscv_isa_extension_available(vcpu->arch.isa, ZICFISS);
+}
+
+static void kvm_sbi_fwft_reset_shadow_stack(struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
+
+ kvm_sbi_fwft_env_flag_reset_helper(vcpu, ENVCFG_SSE);
+ if ((cfg->henvcfg & (ENVCFG_LPE | ENVCFG_SSE)) == 0)
+ cfg->hedeleg &= ~BIT(EXC_SOFTWARE_CHECK);
+}
+
+static long kvm_sbi_fwft_set_shadow_stack(struct kvm_vcpu *vcpu,
+ struct kvm_sbi_fwft_config *conf,
+ bool one_reg_access, unsigned long value)
+{
+ return kvm_sbi_fwft_set_cfi(vcpu, conf, one_reg_access, value, ENVCFG_SSE);
+}
+
+static long kvm_sbi_fwft_get_shadow_stack(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_SSE);
+}
+
static bool kvm_sbi_fwft_pte_ad_hw_updating_supported(struct kvm_vcpu *vcpu)
{
return riscv_isa_extension_available(vcpu->arch.isa, SVADU) &&
@@ -314,6 +403,24 @@ 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_LANDING_PAD,
+ .first_reg_num = offsetof(struct kvm_riscv_sbi_fwft, landing_pad.enable) /
+ sizeof(unsigned long),
+ .supported = kvm_sbi_fwft_landing_pad_supported,
+ .reset = kvm_sbi_fwft_reset_landing_pad,
+ .set = kvm_sbi_fwft_set_landing_pad,
+ .get = kvm_sbi_fwft_get_landing_pad,
+ },
+ {
+ .id = SBI_FWFT_SHADOW_STACK,
+ .first_reg_num = offsetof(struct kvm_riscv_sbi_fwft, shadow_stack.enable) /
+ sizeof(unsigned long),
+ .supported = kvm_sbi_fwft_shadow_stack_supported,
+ .reset = kvm_sbi_fwft_reset_shadow_stack,
+ .set = kvm_sbi_fwft_set_shadow_stack,
+ .get = kvm_sbi_fwft_get_shadow_stack,
+ },
{
.id = SBI_FWFT_PTE_AD_HW_UPDATING,
.first_reg_num = offsetof(struct kvm_riscv_sbi_fwft, pte_ad_hw_updating.enable) /
--
2.55.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v5 8/8] KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test
2026-07-06 2:20 [PATCH v5 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
` (6 preceding siblings ...)
2026-07-06 2:20 ` [PATCH v5 7/8] RISC-V: KVM: Add support for control-flow integrity FWFT features Inochi Amaoto
@ 2026-07-06 2:20 ` Inochi Amaoto
7 siblings, 0 replies; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-06 2:20 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan,
Charlie Jenkins, Sergey Matyukevich, Thomas Huth, Inochi Amaoto,
Deepak Gupta
Cc: linux-riscv, linux-kernel, kvm, kvm-riscv, linux-kselftest,
Yixun Lan, Longbin Li, Quan Zhou
The KVM RISC-V allows Zicfiss/Zicfilp extensions for Guest/VM so
add these extensions to get-reg-list test.
Assisted-by: YuanSheng:claude-4.7-opus
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
.../selftests/kvm/riscv/get-reg-list.c | 69 +++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/tools/testing/selftests/kvm/riscv/get-reg-list.c b/tools/testing/selftests/kvm/riscv/get-reg-list.c
index 94e33b2ee796..49a4be825031 100644
--- a/tools/testing/selftests/kvm/riscv/get-reg-list.c
+++ b/tools/testing/selftests/kvm/riscv/get-reg-list.c
@@ -90,6 +90,8 @@ bool filter_reg(__u64 reg)
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICBOP:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICBOZ:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICCRSE:
+ case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICFILP:
+ case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICFISS:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICNTR:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICOND:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICSR:
@@ -358,6 +360,8 @@ static const char *core_id_to_str(const char *prefix, __u64 id)
"KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_REG(" #csr ")"
#define RISCV_CSR_SMSTATEEN(csr) \
"KVM_REG_RISCV_CSR_SMSTATEEN | KVM_REG_RISCV_CSR_REG(" #csr ")"
+#define RISCV_CSR_ZICFISS(csr) \
+ "KVM_REG_RISCV_CSR_ZICFISS | KVM_REG_RISCV_CSR_REG(" #csr ")"
static const char *general_csr_id_to_str(__u64 reg_off)
{
@@ -425,6 +429,18 @@ static const char *smstateen_csr_id_to_str(__u64 reg_off)
return NULL;
}
+static const char *zicfiss_csr_id_to_str(__u64 reg_off)
+{
+ /* reg_off is the offset into struct kvm_riscv_zicfiss_csr */
+ switch (reg_off) {
+ case KVM_REG_RISCV_CSR_ZICFISS_REG(ssp):
+ return RISCV_CSR_ZICFISS(ssp);
+ }
+
+ TEST_FAIL("Unknown zicfiss csr reg: 0x%llx", reg_off);
+ return NULL;
+}
+
static const char *csr_id_to_str(const char *prefix, __u64 id)
{
__u64 reg_off = id & ~(REG_MASK | KVM_REG_RISCV_CSR);
@@ -441,6 +457,8 @@ static const char *csr_id_to_str(const char *prefix, __u64 id)
return aia_csr_id_to_str(reg_off);
case KVM_REG_RISCV_CSR_SMSTATEEN:
return smstateen_csr_id_to_str(reg_off);
+ case KVM_REG_RISCV_CSR_ZICFISS:
+ return zicfiss_csr_id_to_str(reg_off);
}
return strdup_printf("%lld | %lld /* UNKNOWN */", reg_subtype, reg_off);
@@ -585,6 +603,8 @@ static const char *isa_ext_single_id_to_str(__u64 reg_off)
KVM_ISA_EXT_ARR(ZICBOP),
KVM_ISA_EXT_ARR(ZICBOZ),
KVM_ISA_EXT_ARR(ZICCRSE),
+ KVM_ISA_EXT_ARR(ZICFILP),
+ KVM_ISA_EXT_ARR(ZICFISS),
KVM_ISA_EXT_ARR(ZICNTR),
KVM_ISA_EXT_ARR(ZICOND),
KVM_ISA_EXT_ARR(ZICSR),
@@ -748,6 +768,12 @@ static const char *sbi_fwft_id_to_str(__u64 reg_off)
case 6: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pte_ad_hw_updating.enable)";
case 7: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pte_ad_hw_updating.flags)";
case 8: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pte_ad_hw_updating.value)";
+ case 9: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(landing_pad.enable)";
+ case 10: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(landing_pad.flags)";
+ case 11: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(landing_pad.value)";
+ case 12: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(shadow_stack.enable)";
+ case 13: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(shadow_stack.flags)";
+ case 14: return "KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(shadow_stack.value)";
}
return strdup_printf("KVM_REG_RISCV_SBI_FWFT | %lld /* UNKNOWN */", reg_off);
}
@@ -954,6 +980,20 @@ static __u64 sbi_fwft_pte_ad_hw_updating_regs[] = {
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(pte_ad_hw_updating.value),
};
+static __u64 sbi_fwft_landing_pad_regs[] = {
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_FWFT,
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(landing_pad.enable),
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(landing_pad.flags),
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(landing_pad.value),
+};
+
+static __u64 sbi_fwft_shadow_stack_regs[] = {
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_FWFT,
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(shadow_stack.enable),
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(shadow_stack.flags),
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_STATE | KVM_REG_RISCV_SBI_FWFT | KVM_REG_RISCV_SBI_FWFT_REG(shadow_stack.value),
+};
+
static __u64 zicbom_regs[] = {
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_CONFIG | KVM_REG_RISCV_CONFIG_REG(zicbom_block_size),
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICBOM,
@@ -969,6 +1009,11 @@ static __u64 zicboz_regs[] = {
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICBOZ,
};
+static __u64 zicfiss_regs[] = {
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_ZICFISS | KVM_REG_RISCV_CSR_ZICFISS_REG(ssp),
+ KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICFISS,
+};
+
static __u64 aia_regs[] = {
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(siselect),
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio1),
@@ -1220,6 +1265,8 @@ KVM_ISA_EXT_SUBLIST_CONFIG(zicbom, ZICBOM);
KVM_ISA_EXT_SUBLIST_CONFIG(zicbop, ZICBOP);
KVM_ISA_EXT_SUBLIST_CONFIG(zicboz, ZICBOZ);
KVM_ISA_EXT_SIMPLE_CONFIG(ziccrse, ZICCRSE);
+KVM_ISA_EXT_SIMPLE_CONFIG(zicfilp, ZICFILP);
+KVM_ISA_EXT_SUBLIST_CONFIG(zicfiss, ZICFISS);
KVM_ISA_EXT_SIMPLE_CONFIG(zicntr, ZICNTR);
KVM_ISA_EXT_SIMPLE_CONFIG(zicond, ZICOND);
KVM_ISA_EXT_SIMPLE_CONFIG(zicsr, ZICSR);
@@ -1279,6 +1326,24 @@ static struct vcpu_reg_list config_sbi_fwft_pte_ad_hw_updating = {
},
};
+static struct vcpu_reg_list config_sbi_fwft_landing_pad = {
+ .sublists = {
+ SUBLIST_BASE,
+ SUBLIST_ISA(zicfilp, ZICFILP),
+ SUBLIST_SBI(fwft_landing_pad, FWFT),
+ {0},
+ },
+};
+
+static struct vcpu_reg_list config_sbi_fwft_shadow_stack = {
+ .sublists = {
+ SUBLIST_BASE,
+ SUBLIST_ISA(zicfiss, ZICFISS),
+ SUBLIST_SBI(fwft_shadow_stack, FWFT),
+ {0},
+ },
+};
+
struct vcpu_reg_list *vcpu_configs[] = {
&config_sbi_base,
&config_sbi_sta,
@@ -1289,6 +1354,8 @@ struct vcpu_reg_list *vcpu_configs[] = {
&config_sbi_fwft_misaligned_deleg,
&config_sbi_fwft_pointer_masking,
&config_sbi_fwft_pte_ad_hw_updating,
+ &config_sbi_fwft_landing_pad,
+ &config_sbi_fwft_shadow_stack,
&config_aia,
&config_fp_f,
&config_fp_d,
@@ -1332,6 +1399,8 @@ struct vcpu_reg_list *vcpu_configs[] = {
&config_zicbop,
&config_zicboz,
&config_ziccrse,
+ &config_zicfilp,
+ &config_zicfiss,
&config_zicntr,
&config_zicond,
&config_zicsr,
--
2.55.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v5 1/8] RISC-V: KVM: Add support for Svadu FWFT features
2026-07-06 2:20 ` [PATCH v5 1/8] RISC-V: KVM: Add support for Svadu FWFT features Inochi Amaoto
@ 2026-07-07 2:46 ` Inochi Amaoto
2026-07-07 7:43 ` Anup Patel
0 siblings, 1 reply; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-07 2:46 UTC (permalink / raw)
To: Anup Patel
Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Atish Patra, Paolo Bonzini, Shuah Khan, Charlie Jenkins,
Sergey Matyukevich, Thomas Huth, Inochi Amaoto, Deepak Gupta,
linux-riscv, linux-kernel, kvm, kvm-riscv, linux-kselftest,
Yixun Lan, Longbin Li, Quan Zhou
On Mon, Jul 06, 2026 at 10:20:37AM +0800, Inochi Amaoto wrote:
> Hardware updating of PTE A/D bits is controlled through ADUE bit in
> henvcfg Expose the feature only if both Svadu and Svade are supported
> for VS-mode.
>
> Allow the VMM to enable/disable this feature by change the ISA
> extension state in the guest.
>
> Assisted-by: YuanSheng:claude-4.7-opus
> Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
> Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> ---
> arch/riscv/include/uapi/asm/kvm.h | 1 +
> arch/riscv/kvm/vcpu_sbi_fwft.c | 77 +++++++++++++++++++++++++++++++
> 2 files changed, 78 insertions(+)
>
> diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
> index 504e73305343..7bbea8812d92 100644
> --- a/arch/riscv/include/uapi/asm/kvm.h
> +++ b/arch/riscv/include/uapi/asm/kvm.h
> @@ -240,6 +240,7 @@ 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;
> };
>
> /* 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 ab39ac464ffd..01db40b53295 100644
> --- a/arch/riscv/kvm/vcpu_sbi_fwft.c
> +++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
> @@ -11,6 +11,7 @@
> #include <linux/kvm_host.h>
> #include <asm/cpufeature.h>
> #include <asm/sbi.h>
> +#include <asm/kvm_nacl.h>
> #include <asm/kvm_vcpu_sbi.h>
> #include <asm/kvm_vcpu_sbi_fwft.h>
>
> @@ -94,6 +95,45 @@ 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,
> + u64 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, u64 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) {
> + ncsr_write(CSR_HENVCFG, vcpu->arch.cfg.henvcfg);
> + if (IS_ENABLED(CONFIG_32BIT))
> + ncsr_write(CSR_HENVCFGH, vcpu->arch.cfg.henvcfg >> 32);
> + }
> +
> + return SBI_SUCCESS;
> +}
> +
Hi, Anup,
The sashiko bot point out calling NACL helper is not safe here as
preemption is not allowed when calling this_cpu_ptr() and it is
used by the NACL helper. Since I have no idea about how to fix it,
is it acceptable to use csr read/write directly here as other FWFT
feature?
Regards,
Inochi
The original reply from the bot is
Is it safe to call ncsr_write() here without preemption disabled?
KVM handles SBI ecalls with preemption enabled. The ncsr_write() macro
evaluates nacl_shmem(), which relies on this_cpu_ptr(). Using this_cpu_ptr()
with preemption enabled will trigger a CONFIG_DEBUG_PREEMPT warning.
Could the thread be migrated to another CPU after computing the pointer but
before writing to it, resulting in per-CPU memory corruption by writing to
the NACL shared memory of another physical CPU?
Additionally, when NACL is disabled, it falls back to csr_write(), which
writes directly to the physical CPU's host CSRs (CSR_HENVCFG). Could this
leave the host with modified hardware state if the vCPU thread migrates?
> +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, u64 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();
> @@ -137,6 +177,34 @@ 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)
> +{
> + if (kvm_sbi_fwft_pte_ad_hw_updating_supported(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)
> @@ -246,6 +314,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.55.0
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v5 1/8] RISC-V: KVM: Add support for Svadu FWFT features
2026-07-07 2:46 ` Inochi Amaoto
@ 2026-07-07 7:43 ` Anup Patel
2026-07-07 7:51 ` Inochi Amaoto
0 siblings, 1 reply; 12+ messages in thread
From: Anup Patel @ 2026-07-07 7:43 UTC (permalink / raw)
To: Inochi Amaoto
Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Atish Patra, Paolo Bonzini, Shuah Khan, Charlie Jenkins,
Sergey Matyukevich, Thomas Huth, Deepak Gupta, linux-riscv,
linux-kernel, kvm, kvm-riscv, linux-kselftest, Yixun Lan,
Longbin Li, Quan Zhou
On Tue, Jul 7, 2026 at 8:16 AM Inochi Amaoto <inochiama@gmail.com> wrote:
>
> On Mon, Jul 06, 2026 at 10:20:37AM +0800, Inochi Amaoto wrote:
> > Hardware updating of PTE A/D bits is controlled through ADUE bit in
> > henvcfg Expose the feature only if both Svadu and Svade are supported
> > for VS-mode.
> >
> > Allow the VMM to enable/disable this feature by change the ISA
> > extension state in the guest.
> >
> > Assisted-by: YuanSheng:claude-4.7-opus
> > Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
> > Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
> > Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> > ---
> > arch/riscv/include/uapi/asm/kvm.h | 1 +
> > arch/riscv/kvm/vcpu_sbi_fwft.c | 77 +++++++++++++++++++++++++++++++
> > 2 files changed, 78 insertions(+)
> >
> > diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
> > index 504e73305343..7bbea8812d92 100644
> > --- a/arch/riscv/include/uapi/asm/kvm.h
> > +++ b/arch/riscv/include/uapi/asm/kvm.h
> > @@ -240,6 +240,7 @@ 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;
> > };
> >
> > /* 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 ab39ac464ffd..01db40b53295 100644
> > --- a/arch/riscv/kvm/vcpu_sbi_fwft.c
> > +++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
> > @@ -11,6 +11,7 @@
> > #include <linux/kvm_host.h>
> > #include <asm/cpufeature.h>
> > #include <asm/sbi.h>
> > +#include <asm/kvm_nacl.h>
> > #include <asm/kvm_vcpu_sbi.h>
> > #include <asm/kvm_vcpu_sbi_fwft.h>
> >
> > @@ -94,6 +95,45 @@ 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,
> > + u64 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, u64 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) {
> > + ncsr_write(CSR_HENVCFG, vcpu->arch.cfg.henvcfg);
> > + if (IS_ENABLED(CONFIG_32BIT))
> > + ncsr_write(CSR_HENVCFGH, vcpu->arch.cfg.henvcfg >> 32);
> > + }
> > +
> > + return SBI_SUCCESS;
> > +}
> > +
>
> Hi, Anup,
>
> The sashiko bot point out calling NACL helper is not safe here as
> preemption is not allowed when calling this_cpu_ptr() and it is
> used by the NACL helper. Since I have no idea about how to fix it,
> is it acceptable to use csr read/write directly here as other FWFT
> feature?
I think its okay use regular csr_read/write() over here because FWFT
calls are not in hotpath so it won't have much impact on nested
virtualization performance.
Regards,
Anup
>
> Regards,
> Inochi
>
>
> The original reply from the bot is
>
> Is it safe to call ncsr_write() here without preemption disabled?
>
> KVM handles SBI ecalls with preemption enabled. The ncsr_write() macro
> evaluates nacl_shmem(), which relies on this_cpu_ptr(). Using this_cpu_ptr()
> with preemption enabled will trigger a CONFIG_DEBUG_PREEMPT warning.
>
> Could the thread be migrated to another CPU after computing the pointer but
> before writing to it, resulting in per-CPU memory corruption by writing to
> the NACL shared memory of another physical CPU?
>
> Additionally, when NACL is disabled, it falls back to csr_write(), which
> writes directly to the physical CPU's host CSRs (CSR_HENVCFG). Could this
> leave the host with modified hardware state if the vCPU thread migrates?
>
>
> > +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, u64 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();
> > @@ -137,6 +177,34 @@ 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)
> > +{
> > + if (kvm_sbi_fwft_pte_ad_hw_updating_supported(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)
> > @@ -246,6 +314,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.55.0
> >
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v5 1/8] RISC-V: KVM: Add support for Svadu FWFT features
2026-07-07 7:43 ` Anup Patel
@ 2026-07-07 7:51 ` Inochi Amaoto
0 siblings, 0 replies; 12+ messages in thread
From: Inochi Amaoto @ 2026-07-07 7:51 UTC (permalink / raw)
To: Anup Patel, Inochi Amaoto
Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Atish Patra, Paolo Bonzini, Shuah Khan, Charlie Jenkins,
Sergey Matyukevich, Thomas Huth, Deepak Gupta, linux-riscv,
linux-kernel, kvm, kvm-riscv, linux-kselftest, Yixun Lan,
Longbin Li, Quan Zhou
On Tue, Jul 07, 2026 at 01:13:58PM +0530, Anup Patel wrote:
> On Tue, Jul 7, 2026 at 8:16 AM Inochi Amaoto <inochiama@gmail.com> wrote:
> >
> > On Mon, Jul 06, 2026 at 10:20:37AM +0800, Inochi Amaoto wrote:
> > > Hardware updating of PTE A/D bits is controlled through ADUE bit in
> > > henvcfg Expose the feature only if both Svadu and Svade are supported
> > > for VS-mode.
> > >
> > > Allow the VMM to enable/disable this feature by change the ISA
> > > extension state in the guest.
> > >
> > > Assisted-by: YuanSheng:claude-4.7-opus
> > > Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
> > > Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
> > > Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> > > ---
> > > arch/riscv/include/uapi/asm/kvm.h | 1 +
> > > arch/riscv/kvm/vcpu_sbi_fwft.c | 77 +++++++++++++++++++++++++++++++
> > > 2 files changed, 78 insertions(+)
> > >
> > > diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
> > > index 504e73305343..7bbea8812d92 100644
> > > --- a/arch/riscv/include/uapi/asm/kvm.h
> > > +++ b/arch/riscv/include/uapi/asm/kvm.h
> > > @@ -240,6 +240,7 @@ 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;
> > > };
> > >
> > > /* 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 ab39ac464ffd..01db40b53295 100644
> > > --- a/arch/riscv/kvm/vcpu_sbi_fwft.c
> > > +++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
> > > @@ -11,6 +11,7 @@
> > > #include <linux/kvm_host.h>
> > > #include <asm/cpufeature.h>
> > > #include <asm/sbi.h>
> > > +#include <asm/kvm_nacl.h>
> > > #include <asm/kvm_vcpu_sbi.h>
> > > #include <asm/kvm_vcpu_sbi_fwft.h>
> > >
> > > @@ -94,6 +95,45 @@ 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,
> > > + u64 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, u64 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) {
> > > + ncsr_write(CSR_HENVCFG, vcpu->arch.cfg.henvcfg);
> > > + if (IS_ENABLED(CONFIG_32BIT))
> > > + ncsr_write(CSR_HENVCFGH, vcpu->arch.cfg.henvcfg >> 32);
> > > + }
> > > +
> > > + return SBI_SUCCESS;
> > > +}
> > > +
> >
> > Hi, Anup,
> >
> > The sashiko bot point out calling NACL helper is not safe here as
> > preemption is not allowed when calling this_cpu_ptr() and it is
> > used by the NACL helper. Since I have no idea about how to fix it,
> > is it acceptable to use csr read/write directly here as other FWFT
> > feature?
>
> I think its okay use regular csr_read/write() over here because FWFT
> calls are not in hotpath so it won't have much impact on nested
> virtualization performance.
>
Great, I will switch to the csr_read/write() in the next version. Thanks.
Regards,
Inochi
> Regards,
> Anup
>
> >
> > Regards,
> > Inochi
> >
> >
> > The original reply from the bot is
> >
> > Is it safe to call ncsr_write() here without preemption disabled?
> >
> > KVM handles SBI ecalls with preemption enabled. The ncsr_write() macro
> > evaluates nacl_shmem(), which relies on this_cpu_ptr(). Using this_cpu_ptr()
> > with preemption enabled will trigger a CONFIG_DEBUG_PREEMPT warning.
> >
> > Could the thread be migrated to another CPU after computing the pointer but
> > before writing to it, resulting in per-CPU memory corruption by writing to
> > the NACL shared memory of another physical CPU?
> >
> > Additionally, when NACL is disabled, it falls back to csr_write(), which
> > writes directly to the physical CPU's host CSRs (CSR_HENVCFG). Could this
> > leave the host with modified hardware state if the vCPU thread migrates?
> >
> >
> > > +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, u64 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();
> > > @@ -137,6 +177,34 @@ 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)
> > > +{
> > > + if (kvm_sbi_fwft_pte_ad_hw_updating_supported(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)
> > > @@ -246,6 +314,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.55.0
> > >
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-07-07 7:52 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06 2:20 [PATCH v5 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 1/8] RISC-V: KVM: Add support for Svadu FWFT features Inochi Amaoto
2026-07-07 2:46 ` Inochi Amaoto
2026-07-07 7:43 ` Anup Patel
2026-07-07 7:51 ` Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 2/8] KVM: riscv: selftests: add Svadu FWFT extension to get-reg-list test Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 3/8] RISC-V: KVM: Allow Zicfiss/Zicfilp extensions for Guest/VM Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 4/8] RISC-V: KVM: Add ssp context save/restore Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 5/8] RISC-V: KVM: Handle software-check exits for VCPU Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 6/8] RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 7/8] RISC-V: KVM: Add support for control-flow integrity FWFT features Inochi Amaoto
2026-07-06 2:20 ` [PATCH v5 8/8] KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test Inochi Amaoto
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox