[PATCH 3/6] riscv: hwprobe: Report Zicfilp and Zicfiss only when available

From: Radim Krčmář

Date: Tue Oct 06 2026 - 03:57:43 EST


User-mode use of Zicfilp and Zicfiss requires senvcfg.LPE and
senvcfg.SSE, respectively, which we set only when is_user_lpad_enabled()
and is_user_shstk_enabled() (CONFIG_RISCV_USER_CFI, the extension on all
harts, and not disabled by riscv_nousercfi). hwprobe reports the
extensions from the per-hart ISA bitmaps alone, so it can advertise
extensions that are always disabled in user-mode.

Report correct environment to user-mode.

The changes to arch/riscv/include/asm/usercfi.h avoid
IS_ENABLED(CONFIG_RISCV_USER_CFI) guards in the conditions.

Fixes: 30c3099036a9 ("riscv/hwprobe: add zicfilp / zicfiss enumeration in hwprobe")
Signed-off-by: Radim Krčmář <radim.krcmar@xxxxxxxxxxxxxxxx>
---
Cases where new harts fail to enable user cfi aren't curently handled
very well.

The rest of usercfi.h is currently using macros instead of inline
functions, but I couldn't really bear to follow the same pattern...

arch/riscv/include/asm/usercfi.h | 9 ++++++---
arch/riscv/kernel/sys_hwprobe.c | 9 +++++++--
2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/riscv/include/asm/usercfi.h b/arch/riscv/include/asm/usercfi.h
index 61ee02cee297..bbde171bccde 100644
--- a/arch/riscv/include/asm/usercfi.h
+++ b/arch/riscv/include/asm/usercfi.h
@@ -48,6 +48,8 @@ bool is_indir_lp_enabled(struct task_struct *task);
bool is_indir_lp_locked(struct task_struct *task);
void set_indir_lp_status(struct task_struct *task, bool enable);
void set_indir_lp_lock(struct task_struct *task, bool lock);
+bool is_user_shstk_enabled(void);
+bool is_user_lpad_enabled(void);

#define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK (PR_SHADOW_STACK_ENABLE)
#define PR_CFI_SUPPORTED_STATUS_MASK (PR_CFI_ENABLE | PR_CFI_DISABLE | PR_CFI_LOCK)
@@ -88,10 +90,11 @@ void set_indir_lp_lock(struct task_struct *task, bool lock);

#define get_active_shstk(task) 0UL

-#endif /* CONFIG_RISCV_USER_CFI */
+static __always_inline bool is_user_shstk_enabled(void) { return false; }

-bool is_user_shstk_enabled(void);
-bool is_user_lpad_enabled(void);
+static __always_inline bool is_user_lpad_enabled(void) { return false; }
+
+#endif /* CONFIG_RISCV_USER_CFI */

#endif /* __ASSEMBLER__ */

diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
index c74e36e8fcdd..477d8fd780a6 100644
--- a/arch/riscv/kernel/sys_hwprobe.c
+++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -14,6 +14,7 @@
#include <asm/switch_to.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
+#include <asm/usercfi.h>
#include <asm/vector.h>
#include <asm/vendor_extensions/mips_hwprobe.h>
#include <asm/vendor_extensions/sifive_hwprobe.h>
@@ -97,6 +98,9 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
if (riscv_isa_extension_available(NULL, ZICBOZ))
pair->value |= RISCV_HWPROBE_EXT_ZICBOZ;

+ if (is_user_lpad_enabled())
+ pair->value |= RISCV_HWPROBE_EXT_ZICFILP;
+
/*
* Loop through and record extensions that 1) anyone has, and 2) anyone
* doesn't have.
@@ -127,7 +131,6 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
EXT_KEY(isainfo->isa, ZCLSD, pair->value, missing);
EXT_KEY(isainfo->isa, ZCMOP, pair->value, missing);
EXT_KEY(isainfo->isa, ZICBOP, pair->value, missing);
- EXT_KEY(isainfo->isa, ZICFILP, pair->value, missing);
EXT_KEY(isainfo->isa, ZICNTR, pair->value, missing);
EXT_KEY(isainfo->isa, ZICOND, pair->value, missing);
EXT_KEY(isainfo->isa, ZIHINTNTL, pair->value, missing);
@@ -197,6 +200,9 @@ static void hwprobe_isa_ext1(struct riscv_hwprobe *pair,

pair->value = 0;

+ if (is_user_shstk_enabled())
+ pair->value |= RISCV_HWPROBE_EXT_ZICFISS;
+
/*
* Loop through and record extensions that 1) anyone has, and 2) anyone
* doesn't have.
@@ -210,7 +216,6 @@ static void hwprobe_isa_ext1(struct riscv_hwprobe *pair,
* configuration, as no other checks, besides presence
* in the hart_isa bitmap, are made.
*/
- EXT_KEY(isainfo->isa, ZICFISS, pair->value, missing);
EXT_KEY(isainfo->isa, ZICCLSM, pair->value, missing);
EXT_KEY(isainfo->isa, ZICCAMOA, pair->value, missing);
EXT_KEY(isainfo->isa, ZICCIF, pair->value, missing);
--
2.55.0