* [PATCH v4 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support
@ 2026-07-01 2:07 Inochi Amaoto
2026-07-01 2:07 ` [PATCH v4 1/8] RISC-V: KVM: Add support for Svadu FWFT features Inochi Amaoto
` (7 more replies)
0 siblings, 8 replies; 15+ messages in thread
From: Inochi Amaoto @ 2026-07-01 2:07 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan, Thomas Huth,
Sergey Matyukevich, Inochi Amaoto, Andy Chiu, 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 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 | 6 +
arch/riscv/kvm/vcpu_exit.c | 10 +
arch/riscv/kvm/vcpu_onereg.c | 66 ++++++-
arch/riscv/kvm/vcpu_sbi_fwft.c | 182 ++++++++++++++++++
.../selftests/kvm/riscv/get-reg-list.c | 88 +++++++++
9 files changed, 373 insertions(+), 2 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 1/8] RISC-V: KVM: Add support for Svadu FWFT features
2026-07-01 2:07 [PATCH v4 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
@ 2026-07-01 2:07 ` Inochi Amaoto
2026-07-01 2:30 ` sashiko-bot
2026-07-01 2:07 ` [PATCH v4 2/8] KVM: riscv: selftests: add Svadu FWFT extension to get-reg-list test Inochi Amaoto
` (6 subsequent siblings)
7 siblings, 1 reply; 15+ messages in thread
From: Inochi Amaoto @ 2026-07-01 2:07 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan, Thomas Huth,
Sergey Matyukevich, Inochi Amaoto, Andy Chiu, 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 | 75 +++++++++++++++++++++++++++++++
2 files changed, 76 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..7192c229a19e 100644
--- a/arch/riscv/kvm/vcpu_sbi_fwft.c
+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
@@ -94,6 +94,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) {
+ csr_write(CSR_HENVCFG, vcpu->arch.cfg.henvcfg);
+ if (IS_ENABLED(CONFIG_32BIT))
+ csr_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 +176,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)
@@ -246,6 +312,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] 15+ messages in thread
* [PATCH v4 2/8] KVM: riscv: selftests: add Svadu FWFT extension to get-reg-list test
2026-07-01 2:07 [PATCH v4 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
2026-07-01 2:07 ` [PATCH v4 1/8] RISC-V: KVM: Add support for Svadu FWFT features Inochi Amaoto
@ 2026-07-01 2:07 ` Inochi Amaoto
2026-07-01 2:07 ` [PATCH v4 3/8] RISC-V: KVM: Allow Zicfiss/Zicfilp extensions for Guest/VM Inochi Amaoto
` (5 subsequent siblings)
7 siblings, 0 replies; 15+ messages in thread
From: Inochi Amaoto @ 2026-07-01 2:07 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan, Thomas Huth,
Sergey Matyukevich, Inochi Amaoto, Andy Chiu, 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] 15+ messages in thread
* [PATCH v4 3/8] RISC-V: KVM: Allow Zicfiss/Zicfilp extensions for Guest/VM
2026-07-01 2:07 [PATCH v4 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
2026-07-01 2:07 ` [PATCH v4 1/8] RISC-V: KVM: Add support for Svadu FWFT features Inochi Amaoto
2026-07-01 2:07 ` [PATCH v4 2/8] KVM: riscv: selftests: add Svadu FWFT extension to get-reg-list test Inochi Amaoto
@ 2026-07-01 2:07 ` Inochi Amaoto
2026-07-01 2:07 ` [PATCH v4 4/8] RISC-V: KVM: Add ssp context save/restore Inochi Amaoto
` (4 subsequent siblings)
7 siblings, 0 replies; 15+ messages in thread
From: Inochi Amaoto @ 2026-07-01 2:07 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan, Thomas Huth,
Sergey Matyukevich, Inochi Amaoto, Andy Chiu, 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] 15+ messages in thread
* [PATCH v4 4/8] RISC-V: KVM: Add ssp context save/restore
2026-07-01 2:07 [PATCH v4 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
` (2 preceding siblings ...)
2026-07-01 2:07 ` [PATCH v4 3/8] RISC-V: KVM: Allow Zicfiss/Zicfilp extensions for Guest/VM Inochi Amaoto
@ 2026-07-01 2:07 ` Inochi Amaoto
2026-07-01 2:28 ` sashiko-bot
2026-07-01 2:07 ` [PATCH v4 5/8] RISC-V: KVM: Handle software-check exits for VCPU Inochi Amaoto
` (3 subsequent siblings)
7 siblings, 1 reply; 15+ messages in thread
From: Inochi Amaoto @ 2026-07-01 2:07 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan, Thomas Huth,
Sergey Matyukevich, Inochi Amaoto, Andy Chiu, 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 | 6 +++
arch/riscv/kvm/vcpu_onereg.c | 66 ++++++++++++++++++++++++++++++-
4 files changed, 85 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..1c2775a4834e 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -720,6 +720,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 +728,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 +742,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..bd59aebc8b2e 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;
@@ -688,7 +732,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 +784,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] 15+ messages in thread
* [PATCH v4 5/8] RISC-V: KVM: Handle software-check exits for VCPU
2026-07-01 2:07 [PATCH v4 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
` (3 preceding siblings ...)
2026-07-01 2:07 ` [PATCH v4 4/8] RISC-V: KVM: Add ssp context save/restore Inochi Amaoto
@ 2026-07-01 2:07 ` Inochi Amaoto
2026-07-01 2:31 ` sashiko-bot
2026-07-01 2:07 ` [PATCH v4 6/8] RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled Inochi Amaoto
` (2 subsequent siblings)
7 siblings, 1 reply; 15+ messages in thread
From: Inochi Amaoto @ 2026-07-01 2:07 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan, Thomas Huth,
Sergey Matyukevich, Inochi Amaoto, Andy Chiu, 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] 15+ messages in thread
* [PATCH v4 6/8] RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled.
2026-07-01 2:07 [PATCH v4 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
` (4 preceding siblings ...)
2026-07-01 2:07 ` [PATCH v4 5/8] RISC-V: KVM: Handle software-check exits for VCPU Inochi Amaoto
@ 2026-07-01 2:07 ` Inochi Amaoto
2026-07-01 2:20 ` sashiko-bot
2026-07-01 2:07 ` [PATCH v4 7/8] RISC-V: KVM: Add support for control-flow integrity FWFT features Inochi Amaoto
2026-07-01 2:07 ` [PATCH v4 8/8] KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test Inochi Amaoto
7 siblings, 1 reply; 15+ messages in thread
From: Inochi Amaoto @ 2026-07-01 2:07 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan, Thomas Huth,
Sergey Matyukevich, Inochi Amaoto, Andy Chiu, 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 | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 12eebeabdf14..61305da5256d 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -154,6 +154,12 @@ 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;
+ }
+
/* Update Guest SSTATUS */
ncsr_write(CSR_VSSTATUS, vsstatus);
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v4 7/8] RISC-V: KVM: Add support for control-flow integrity FWFT features
2026-07-01 2:07 [PATCH v4 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
` (5 preceding siblings ...)
2026-07-01 2:07 ` [PATCH v4 6/8] RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled Inochi Amaoto
@ 2026-07-01 2:07 ` Inochi Amaoto
2026-07-01 2:33 ` sashiko-bot
2026-07-01 2:07 ` [PATCH v4 8/8] KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test Inochi Amaoto
7 siblings, 1 reply; 15+ messages in thread
From: Inochi Amaoto @ 2026-07-01 2:07 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan, Thomas Huth,
Sergey Matyukevich, Inochi Amaoto, Andy Chiu, 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 7192c229a19e..cb9b9721ec88 100644
--- a/arch/riscv/kvm/vcpu_sbi_fwft.c
+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
@@ -176,6 +176,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 |= EXC_SOFTWARE_CHECK;
+ else
+ cfg->hedeleg &= ~EXC_SOFTWARE_CHECK;
+
+ if (!one_reg_access) {
+ csr_write(CSR_HEDELEG, cfg->hedeleg);
+ /*
+ * Both Bit LPE and SSE are in the lower part, so it is safe
+ * to only write the henvcfg
+ */
+ csr_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 &= ~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 &= ~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) &&
@@ -312,6 +401,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] 15+ messages in thread
* [PATCH v4 8/8] KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test
2026-07-01 2:07 [PATCH v4 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
` (6 preceding siblings ...)
2026-07-01 2:07 ` [PATCH v4 7/8] RISC-V: KVM: Add support for control-flow integrity FWFT features Inochi Amaoto
@ 2026-07-01 2:07 ` Inochi Amaoto
2026-07-01 2:23 ` sashiko-bot
7 siblings, 1 reply; 15+ messages in thread
From: Inochi Amaoto @ 2026-07-01 2:07 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Anup Patel, Atish Patra, Paolo Bonzini, Shuah Khan, Thomas Huth,
Sergey Matyukevich, Inochi Amaoto, Andy Chiu, 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 | 67 +++++++++++++++++++
1 file changed, 67 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..5963f62ce730 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_cfi_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,18 @@ 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_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_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 +1007,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 +1263,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 +1324,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 +1352,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 +1397,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] 15+ messages in thread
* Re: [PATCH v4 6/8] RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled.
2026-07-01 2:07 ` [PATCH v4 6/8] RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled Inochi Amaoto
@ 2026-07-01 2:20 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-01 2:20 UTC (permalink / raw)
To: Inochi Amaoto; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Missing clearance of SR_SPELP in guest_context.sstatus during trap redirection causes the guest to resume with an incorrect ELP state, leading to spurious landing pad faults.
--
commit 2ec992c0d3b802f1fb7b83ffb3d6328de134362d
Author: Inochi Amaoto <inochiama@gmail.com>
RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled.
This patch delegates the newly added SPELP bit from the Zicfilp extension
to VS/VU mode if it enables landing pad support.
> diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
> --- a/arch/riscv/kvm/vcpu_exit.c
> +++ b/arch/riscv/kvm/vcpu_exit.c
> @@ -154,6 +154,12 @@ 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;
[Severity: High]
Does this missing clearance cause the guest to resume with an incorrect ELP
state?
While this correctly saves the old ELP state to vsstatus, it appears to
leave SR_SPELP set in vcpu->arch.guest_context.sstatus. If a guest with
the Zicfilp extension enabled takes an exception while its active ELP state
is 1, won't the guest's exception handler be entered with an active ELP
state of 1 instead of 0?
Could this cause an immediate Software Check exception (landing pad fault)
when the guest exception handler executes its first instruction, resulting
in a trap loop or guest crash?
> + }
> +
> /* Update Guest SSTATUS */
> ncsr_write(CSR_VSSTATUS, vsstatus);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701020746.170157-1-inochiama@gmail.com?part=6
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 8/8] KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test
2026-07-01 2:07 ` [PATCH v4 8/8] KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test Inochi Amaoto
@ 2026-07-01 2:23 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-01 2:23 UTC (permalink / raw)
To: Inochi Amaoto; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] Missing base FWFT extension register in sbi_fwft_landing_pad_regs and sbi_fwft_shadow_stack_regs.
- [Low] Incorrect struct name referenced in comment for zicfiss_csr_id_to_str.
--
commit 277e1fec57d15d21d187626b4aa2c8ebecc81e21
Author: Inochi Amaoto <inochiama@gmail.com>
KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test
This commit adds Zicfiss and Zicfilp extensions support to the KVM RISC-V
get-reg-list selftest. It introduces parsing and printing of related CSRs
and SBI FWFT configurations.
> diff --git a/tools/testing/selftests/kvm/riscv/get-reg-list.c b/tools/testing/selftests/kvm/riscv/get-reg-list.c
> index 94e33b2ee7963..5963f62ce7302 100644
> --- a/tools/testing/selftests/kvm/riscv/get-reg-list.c
> +++ b/tools/testing/selftests/kvm/riscv/get-reg-list.c
[ ... ]
> @@ -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_cfi_csr */
[Severity: Low]
This isn't a bug, but there appears to be a typo in the comment. Should this
reference struct kvm_riscv_zicfiss_csr instead of struct kvm_riscv_cfi_csr
as defined in the KVM UAPI headers?
> + 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;
> +}
[ ... ]
> @@ -954,6 +980,18 @@ 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_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_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),
> +};
[Severity: Low]
Is the base FWFT extension register intentionally omitted from these sublists?
Looking at sbi_fwft_pte_ad_hw_updating_regs defined just above, it includes:
KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_FWFT
Should the base FWFT extension register also be included in
sbi_fwft_landing_pad_regs and sbi_fwft_shadow_stack_regs to match the pattern
established by other FWFT sublists?
> +
> 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,
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701020746.170157-1-inochiama@gmail.com?part=8
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 4/8] RISC-V: KVM: Add ssp context save/restore
2026-07-01 2:07 ` [PATCH v4 4/8] RISC-V: KVM: Add ssp context save/restore Inochi Amaoto
@ 2026-07-01 2:28 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-01 2:28 UTC (permalink / raw)
To: Inochi Amaoto; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Missing addition of the ZICFISS register count in `num_csr_regs()` causes KVM to under-calculate the required register list size, leading to an out-of-bounds write during the `KVM_GET_REG_LIST` ioctl.
- [Medium] Modifying CSR_SSP in C code before entering the VCPU assembly loop, and zeroing it upon return, overwrites the host's active Shadow Stack Pointer, potentially causing a host kernel panic if the host utilizes Supervisor-mode shadow stacks.
- [Medium] The guest's ZICFISS Shadow Stack Pointer (`zicfiss_csr`) is not cleared during VCPU context reset, leading to guest state leakage across reboots.
--
commit 3d9e79d289458c01fff126fe0b09e2d1859aeecc
Author: Inochi Amaoto <inochiama@gmail.com>
RISC-V: KVM: Add ssp context save/restore
This commit adds ssp context save/restore for guest VCPUs. It also adds the
Zicfiss registers to the ONE_REG interface to allow access from user space.
> diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
> index 60017ceec9d2a..e5ed3b0e5a55b 100644
> --- a/arch/riscv/include/asm/kvm_host.h
> +++ b/arch/riscv/include/asm/kvm_host.h
[ ... ]
> @@ -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;
> +
[Severity: Medium]
Is the zicfiss_csr structure cleared during a VCPU reset?
Looking at kvm_riscv_vcpu_context_reset() in arch/riscv/kvm/vcpu.c,
it doesn't appear to be zeroed:
memset(cntx, 0, sizeof(*cntx));
memset(csr, 0, sizeof(*csr));
memset(&vcpu->arch.smstateen_csr, 0, sizeof(vcpu->arch.smstateen_csr));
Could this lead to the guest's shadow stack pointer being preserved
across warm reboots or kexec, leaking architectural state?
> /* CPU reset state of Guest VCPU */
> struct kvm_vcpu_reset_state reset_state;
>
> diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
> index cf6e231e76e25..1c2775a4834eb 100644
> --- a/arch/riscv/kvm/vcpu.c
> +++ b/arch/riscv/kvm/vcpu.c
> @@ -720,6 +720,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 +728,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);
[Severity: Medium]
Since this modifies the host's CSR_SSP while still executing host C code,
will this cause any subsequent host function returns (before entering
assembly) to use the guest's shadow stack?
If the host kernel utilizes hardware shadow stacks for Supervisor mode,
this could result in a host kernel panic from an sspopchk failure.
> }
>
> 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 +742,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);
[Severity: Medium]
Will hardcoding CSR_SSP to 0 here overwrite the host's shadow stack pointer
rather than correctly restoring the saved host state?
> }
>
> /*
> diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
> index bb920e8923c93..bd59aebc8b2e9 100644
> --- a/arch/riscv/kvm/vcpu_onereg.c
> +++ b/arch/riscv/kvm/vcpu_onereg.c
[ ... ]
> @@ -688,7 +732,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 +784,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;
> }
[Severity: High]
Does num_csr_regs() also need to be updated to include the ZICFISS register
count?
If num_csr_regs() doesn't include the ZICFISS registers, userspace might
allocate a smaller array for KVM_GET_REG_LIST, causing the put_user()
calls above to write past the end of the userspace array.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701020746.170157-1-inochiama@gmail.com?part=4
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 1/8] RISC-V: KVM: Add support for Svadu FWFT features
2026-07-01 2:07 ` [PATCH v4 1/8] RISC-V: KVM: Add support for Svadu FWFT features Inochi Amaoto
@ 2026-07-01 2:30 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-01 2:30 UTC (permalink / raw)
To: Inochi Amaoto; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Missing Nested Virtualization (NACL) Synchronization in FWFT setter
- [High] State Corruption on Reset for SVADU-only guests
--
commit 3a9bb56abfad9f69ff748e7562ad8693be40c7f9
Author: Inochi Amaoto <inochiama@gmail.com>
RISC-V: KVM: Add support for Svadu FWFT features
This commit adds support for the Svadu FWFT feature in RISC-V KVM.
It exposes the PTE A/D hardware updating feature if both Svadu and Svade
are supported, and adds helper functions to get and set the ISA extension
state for the guest.
> diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
> index ab39ac464ffd8..7192c229a19e2 100644
> --- a/arch/riscv/kvm/vcpu_sbi_fwft.c
> +++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
[ ... ]
> @@ -94,6 +94,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) {
> + csr_write(CSR_HENVCFG, vcpu->arch.cfg.henvcfg);
> + if (IS_ENABLED(CONFIG_32BIT))
> + csr_write(CSR_HENVCFGH, vcpu->arch.cfg.henvcfg >> 32);
> + }
[Severity: High]
Will this cause state corruption when KVM nested acceleration (NACL) is
active?
When KVM acts as an L1 hypervisor using NACL, updating the CSR directly
with csr_write() fails to update the NACL shared memory page (nacl_shmem).
When L0 later switches context or resumes the L2 guest, it will reload
CSR_HENVCFG from the unmodified nacl_shmem, silently discarding the L2
guest's FWFT update.
Should this use ncsr_write() instead to ensure safe H-mode CSR
modifications for nested virtualization?
> +
> + return SBI_SUCCESS;
> +}
[ ... ]
> @@ -137,6 +176,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);
> +}
[Severity: High]
Could this break A/D bit updates for SVADU-only guests after a reboot?
A VCPU configured with SVADU but without SVADE requires ENVCFG_ADUE to be
set to 1 to function properly. This is correctly initialized the first
time in kvm_riscv_vcpu_config_ran_once().
However, when the guest initiates a system reset, this reset handler
unconditionally clears ENVCFG_ADUE. Because vcpu->arch.ran_atleast_once
is already true and is not cleared on reset,
kvm_riscv_vcpu_config_ran_once() will not run again.
Does this leave the SVADU-only VCPU resuming with ENVCFG_ADUE cleared,
causing hardware to fail updating A/D bits without SVADE to trap them?
> +
> +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);
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701020746.170157-1-inochiama@gmail.com?part=1
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 5/8] RISC-V: KVM: Handle software-check exits for VCPU
2026-07-01 2:07 ` [PATCH v4 5/8] RISC-V: KVM: Handle software-check exits for VCPU Inochi Amaoto
@ 2026-07-01 2:31 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-01 2:31 UTC (permalink / raw)
To: Inochi Amaoto; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] `vcpu_redirect` unconditionally sets `VSSTATUS.SPP` to 1 and fails to set `HSTATUS.SPVP` to 1, causing guest user-to-kernel privilege escalation or fatal guest crashes.
--
commit b591989d8fd2e996d0f963c15186f3a08e706f56
Author: Inochi Amaoto <inochiama@gmail.com>
RISC-V: KVM: Handle software-check exits for VCPU
The patch introduces handling for EXC_SOFTWARE_CHECK in RISC-V KVM to support
Zicfiss/Zicfilp extensions. It delegates these exceptions to VS mode via
vcpu_redirect().
> diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
> index 0bb0c51e3c890..12eebeabdf146 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);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Severity: High]
This is a pre-existing issue, but using vcpu_redirect() here exposes an
underlying architectural flaw in KVM RISC-V's exception redirection logic.
When KVM redirects a trap to the guest, kvm_riscv_vcpu_trap_redirect() attempts
to copy the host's sstatus.SPP bit into the guest's VSSTATUS.SPP:
arch/riscv/kvm/vcpu_exit.c:kvm_riscv_vcpu_trap_redirect() {
...
/* Change Guest SSTATUS.SPP bit */
vsstatus &= ~SR_SPP;
if (vcpu->arch.guest_context.sstatus & SR_SPP)
vsstatus |= SR_SPP;
...
Since taking a trap from V=1 to HS-mode always sets the host's sstatus.SPP to 1,
VSSTATUS.SPP is unconditionally set to 1. This falsely tells the guest OS that
the exception originated in supervisor mode, even if it actually occurred in
user mode (VU-mode).
Additionally, kvm_riscv_vcpu_trap_redirect() fails to update HSTATUS.SPVP:
...
/* Set Guest privilege mode to supervisor */
vcpu->arch.guest_context.sstatus |= SR_SPP;
}
Because sret from HS-mode uses HSTATUS.SPVP to determine the return privilege
mode for the guest, the guest will resume in VU-mode at the supervisor
exception vector (vstvec).
Does this enable guest user space to execute the kernel's trap handler with
user privileges, leading to privilege escalation or fatal guest crashes?
> + break;
> default:
> break;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701020746.170157-1-inochiama@gmail.com?part=5
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 7/8] RISC-V: KVM: Add support for control-flow integrity FWFT features
2026-07-01 2:07 ` [PATCH v4 7/8] RISC-V: KVM: Add support for control-flow integrity FWFT features Inochi Amaoto
@ 2026-07-01 2:33 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-01 2:33 UTC (permalink / raw)
To: Inochi Amaoto; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Incorrect usage of EXC_SOFTWARE_CHECK as a direct integer instead of a bitmask when configuring hedeleg, causing unintended exception delegation and un-delegation.
--
commit 061583fda9a0d491f0c4c0df10fbb4b0f97c7b4e
Author: Inochi Amaoto <inochiama@gmail.com>
RISC-V: KVM: Add support for control-flow integrity FWFT features
This commit exposes control-flow integrity features to the guest if
supported by the host, and allows the VMM to configure them via the SBI
FWFT interface.
> diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
> index 7192c229a19e2..cb9b9721ec882 100644
> --- a/arch/riscv/kvm/vcpu_sbi_fwft.c
> +++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
[ ... ]
> @@ -176,6 +176,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 |= EXC_SOFTWARE_CHECK;
> + else
> + cfg->hedeleg &= ~EXC_SOFTWARE_CHECK;
[Severity: High]
Does this code modify the correct bits in hedeleg?
EXC_SOFTWARE_CHECK is an exception cause (value 18, or 0x12). When used
directly in bitwise operations like this, it seems to modify bit 1
(instruction access fault) and bit 4 (load address misaligned) rather than
bit 18.
Should this use BIT(EXC_SOFTWARE_CHECK) or (1UL << EXC_SOFTWARE_CHECK)
instead to ensure the software check exception is delegated properly without
corrupting the other delegation states?
> +
> + if (!one_reg_access) {
> + csr_write(CSR_HEDELEG, cfg->hedeleg);
[ ... ]
> +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 &= ~EXC_SOFTWARE_CHECK;
> +}
[Severity: High]
Similar to the question above in kvm_sbi_fwft_set_cfi(), could this
undelegate the wrong exceptions because EXC_SOFTWARE_CHECK is used without
being converted to a bitmask first?
[ ... ]
> +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 &= ~EXC_SOFTWARE_CHECK;
> +}
[Severity: High]
Would it be necessary to update this location to use a bitmask as well?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701020746.170157-1-inochiama@gmail.com?part=7
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-07-01 2:33 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-01 2:07 [PATCH v4 0/8] RISC-V: KVM: Add Svadu/Zicfiss/Zicfilp FWFT support Inochi Amaoto
2026-07-01 2:07 ` [PATCH v4 1/8] RISC-V: KVM: Add support for Svadu FWFT features Inochi Amaoto
2026-07-01 2:30 ` sashiko-bot
2026-07-01 2:07 ` [PATCH v4 2/8] KVM: riscv: selftests: add Svadu FWFT extension to get-reg-list test Inochi Amaoto
2026-07-01 2:07 ` [PATCH v4 3/8] RISC-V: KVM: Allow Zicfiss/Zicfilp extensions for Guest/VM Inochi Amaoto
2026-07-01 2:07 ` [PATCH v4 4/8] RISC-V: KVM: Add ssp context save/restore Inochi Amaoto
2026-07-01 2:28 ` sashiko-bot
2026-07-01 2:07 ` [PATCH v4 5/8] RISC-V: KVM: Handle software-check exits for VCPU Inochi Amaoto
2026-07-01 2:31 ` sashiko-bot
2026-07-01 2:07 ` [PATCH v4 6/8] RISC-V: KVM: Delegate SPELP bit to VS/VU mode if landing pad is enabled Inochi Amaoto
2026-07-01 2:20 ` sashiko-bot
2026-07-01 2:07 ` [PATCH v4 7/8] RISC-V: KVM: Add support for control-flow integrity FWFT features Inochi Amaoto
2026-07-01 2:33 ` sashiko-bot
2026-07-01 2:07 ` [PATCH v4 8/8] KVM: riscv: selftests: add Zicfiss/Zicfilp extension to get-reg-list test Inochi Amaoto
2026-07-01 2:23 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox