linux-riscv.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
@ 2025-08-13 16:33 Paris Oplopoios
  2025-08-13 18:05 ` [PATCH v2] " offtkp
  2025-08-19 19:37 ` [PATCH] " Andrew Jones
  0 siblings, 2 replies; 16+ messages in thread
From: Paris Oplopoios @ 2025-08-13 16:33 UTC (permalink / raw)
  To: linux-riscv; +Cc: paul.walmsley, palmer, aou, alex

When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
bit in the resulting bitmask means extension is not available or the kernel is
not recent enough to support the bit. Currently, there's no way to
differentiate between the two.

This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL, which
returns a bitmask of all queryable supported by the kernel
in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a fallback
extension detection method when the bit they want to query is not available
in the kernel they are running on.

Example usage:

    struct riscv_hwprobe req = { RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL, 0 };
    int ret = syscall(__NR_riscv_hwprobe, &req, 1, 0, NULL, 0);
    if (ret == 0) {
        uint64_t bitmask = req.value;
        if (bitmask & RISCV_HWPROBE_EXT_ZABHA) {
            // Check for existence of Zabha extension using riscv_hwprobe
        } else {
            // Fallback to checking if an instruction in the Zabha
            // extension results in an illegal instruction exception
        }
    }

Signed-off-by: Paris Oplopoios <parisoplop@gmail.com>

---

diff --git a/Documentation/arch/riscv/hwprobe.rst
b/Documentation/arch/riscv/hwprobe.rst
index 2aa9be272d5d..6d77def0a46e 100644
--- a/Documentation/arch/riscv/hwprobe.rst
+++ b/Documentation/arch/riscv/hwprobe.rst
@@ -360,4 +360,7 @@ The following keys are defined:

     * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
         vendor extension is supported in version 1.0 of Matrix
Multiply Accumulate
-    Instruction Extensions Specification.
\ No newline at end of file
+    Instruction Extensions Specification.
+
+* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing
the extensions
+  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
\ No newline at end of file
diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
index 7fe0a379474a..501d49b7a02a 100644
--- a/arch/riscv/include/asm/hwprobe.h
+++ b/arch/riscv/include/asm/hwprobe.h
@@ -8,7 +8,8 @@

 #include <uapi/asm/hwprobe.h>

-#define RISCV_HWPROBE_MAX_KEY 13
+#define RISCV_HWPROBE_MAX_KEY 14
+#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE    ((1ULL << 59) - 1)

 static inline bool riscv_hwprobe_key_is_valid(__s64 key)
 {
diff --git a/arch/riscv/include/uapi/asm/hwprobe.h
b/arch/riscv/include/uapi/asm/hwprobe.h
index aaf6ad970499..a3b92df4dc05 100644
--- a/arch/riscv/include/uapi/asm/hwprobe.h
+++ b/arch/riscv/include/uapi/asm/hwprobe.h
@@ -82,6 +82,7 @@ struct riscv_hwprobe {
 #define        RISCV_HWPROBE_EXT_ZAAMO        (1ULL << 56)
 #define        RISCV_HWPROBE_EXT_ZALRSC    (1ULL << 57)
 #define        RISCV_HWPROBE_EXT_ZABHA        (1ULL << 58)
+/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
 #define RISCV_HWPROBE_KEY_CPUPERF_0    5
 #define        RISCV_HWPROBE_MISALIGNED_UNKNOWN    (0 << 0)
 #define        RISCV_HWPROBE_MISALIGNED_EMULATED    (1 << 0)
@@ -106,6 +107,7 @@ struct riscv_hwprobe {
 #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0    11
 #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE    12
 #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0    13
+#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
 /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */

 /* Flags */
diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
index 0b170e18a2be..40e7fa5f85f3 100644
--- a/arch/riscv/kernel/sys_hwprobe.c
+++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
         hwprobe_isa_vendor_ext_thead_0(pair, cpus);
         break;

+    case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
+        pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
+        break;
+
     /*
      * For forward compatibility, unknown keys don't fail the whole
      * call, but get their element key set to -1 and value set to 0

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-13 16:33 [PATCH] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits Paris Oplopoios
@ 2025-08-13 18:05 ` offtkp
  2025-08-14  9:37   ` Alexandre Ghiti
  2025-08-14 22:13   ` [PATCH v3] " offtkp
  2025-08-19 19:37 ` [PATCH] " Andrew Jones
  1 sibling, 2 replies; 16+ messages in thread
From: offtkp @ 2025-08-13 18:05 UTC (permalink / raw)
  To: linux-riscv; +Cc: paul.walmsley, palmer, aou, alex, offtkp

When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
bit in the resulting bitmask means the extension is not available or the
kernel is not recent enough to support the bit. Currently, there's no
way to differentiate between the two.

This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
which returns a bitmask of all the queryable extensions supported by the
kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
fallback extension detection method when the bit they want to query is
not available in the kernel they are running on.

Signed-off-by: offtkp <parisoplop@gmail.com>
---
Changes in v2:
- convert spaces to tabs
- use git format-patch to create diff

 Documentation/arch/riscv/hwprobe.rst  | 5 ++++-
 arch/riscv/include/asm/hwprobe.h      | 3 ++-
 arch/riscv/include/uapi/asm/hwprobe.h | 2 ++
 arch/riscv/kernel/sys_hwprobe.c       | 4 ++++
 4 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
index 2aa9be272d5d..6d77def0a46e 100644
--- a/Documentation/arch/riscv/hwprobe.rst
+++ b/Documentation/arch/riscv/hwprobe.rst
@@ -360,4 +360,7 @@ The following keys are defined:
 
     * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
         vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
-	Instruction Extensions Specification.
\ No newline at end of file
+	Instruction Extensions Specification.
+
+* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
+  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
\ No newline at end of file
diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
index 7fe0a379474a..501d49b7a02a 100644
--- a/arch/riscv/include/asm/hwprobe.h
+++ b/arch/riscv/include/asm/hwprobe.h
@@ -8,7 +8,8 @@
 
 #include <uapi/asm/hwprobe.h>
 
-#define RISCV_HWPROBE_MAX_KEY 13
+#define RISCV_HWPROBE_MAX_KEY 14
+#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE	((1ULL << 59) - 1)
 
 static inline bool riscv_hwprobe_key_is_valid(__s64 key)
 {
diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
index aaf6ad970499..a3b92df4dc05 100644
--- a/arch/riscv/include/uapi/asm/hwprobe.h
+++ b/arch/riscv/include/uapi/asm/hwprobe.h
@@ -82,6 +82,7 @@ struct riscv_hwprobe {
 #define		RISCV_HWPROBE_EXT_ZAAMO		(1ULL << 56)
 #define		RISCV_HWPROBE_EXT_ZALRSC	(1ULL << 57)
 #define		RISCV_HWPROBE_EXT_ZABHA		(1ULL << 58)
+/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
 #define RISCV_HWPROBE_KEY_CPUPERF_0	5
 #define		RISCV_HWPROBE_MISALIGNED_UNKNOWN	(0 << 0)
 #define		RISCV_HWPROBE_MISALIGNED_EMULATED	(1 << 0)
@@ -106,6 +107,7 @@ struct riscv_hwprobe {
 #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0	11
 #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE	12
 #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0	13
+#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
 /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
 
 /* Flags */
diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
index 0b170e18a2be..40e7fa5f85f3 100644
--- a/arch/riscv/kernel/sys_hwprobe.c
+++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
 		hwprobe_isa_vendor_ext_thead_0(pair, cpus);
 		break;
 
+	case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
+		pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
+		break;
+
 	/*
 	 * For forward compatibility, unknown keys don't fail the whole
 	 * call, but get their element key set to -1 and value set to 0

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-13 18:05 ` [PATCH v2] " offtkp
@ 2025-08-14  9:37   ` Alexandre Ghiti
  2025-08-14 10:32     ` Paris Oplopoios
  2025-08-14 22:13   ` [PATCH v3] " offtkp
  1 sibling, 1 reply; 16+ messages in thread
From: Alexandre Ghiti @ 2025-08-14  9:37 UTC (permalink / raw)
  To: offtkp, linux-riscv; +Cc: paul.walmsley, palmer, aou

Hi Paris,

On 8/13/25 20:05, offtkp wrote:
> When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
> bit in the resulting bitmask means the extension is not available or the
> kernel is not recent enough to support the bit. Currently, there's no
> way to differentiate between the two.
>
> This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
> which returns a bitmask of all the queryable extensions supported by the
> kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
> fallback extension detection method when the bit they want to query is
> not available in the kernel they are running on.


Admittedly, I'm not convinced this is necessary. As you showed in your 
v1, trying to figure out if an extension is available will likely result 
in a SIGILL, so that will kill your application. Why don't you check the 
kernel config or even the hwprobe.h header? Since basically here, you 
use a syscall to return an information that is visible already from 
userspace.

But maybe I'm missing an interesting usecase, just let me know.

Thanks,

Alex


>
> Signed-off-by: offtkp <parisoplop@gmail.com>
> ---
> Changes in v2:
> - convert spaces to tabs
> - use git format-patch to create diff
>
>   Documentation/arch/riscv/hwprobe.rst  | 5 ++++-
>   arch/riscv/include/asm/hwprobe.h      | 3 ++-
>   arch/riscv/include/uapi/asm/hwprobe.h | 2 ++
>   arch/riscv/kernel/sys_hwprobe.c       | 4 ++++
>   4 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
> index 2aa9be272d5d..6d77def0a46e 100644
> --- a/Documentation/arch/riscv/hwprobe.rst
> +++ b/Documentation/arch/riscv/hwprobe.rst
> @@ -360,4 +360,7 @@ The following keys are defined:
>   
>       * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
>           vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
> -	Instruction Extensions Specification.
> \ No newline at end of file
> +	Instruction Extensions Specification.
> +
> +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
> +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
> \ No newline at end of file
> diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
> index 7fe0a379474a..501d49b7a02a 100644
> --- a/arch/riscv/include/asm/hwprobe.h
> +++ b/arch/riscv/include/asm/hwprobe.h
> @@ -8,7 +8,8 @@
>   
>   #include <uapi/asm/hwprobe.h>
>   
> -#define RISCV_HWPROBE_MAX_KEY 13
> +#define RISCV_HWPROBE_MAX_KEY 14
> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE	((1ULL << 59) - 1)
>   
>   static inline bool riscv_hwprobe_key_is_valid(__s64 key)
>   {
> diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
> index aaf6ad970499..a3b92df4dc05 100644
> --- a/arch/riscv/include/uapi/asm/hwprobe.h
> +++ b/arch/riscv/include/uapi/asm/hwprobe.h
> @@ -82,6 +82,7 @@ struct riscv_hwprobe {
>   #define		RISCV_HWPROBE_EXT_ZAAMO		(1ULL << 56)
>   #define		RISCV_HWPROBE_EXT_ZALRSC	(1ULL << 57)
>   #define		RISCV_HWPROBE_EXT_ZABHA		(1ULL << 58)
> +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
>   #define RISCV_HWPROBE_KEY_CPUPERF_0	5
>   #define		RISCV_HWPROBE_MISALIGNED_UNKNOWN	(0 << 0)
>   #define		RISCV_HWPROBE_MISALIGNED_EMULATED	(1 << 0)
> @@ -106,6 +107,7 @@ struct riscv_hwprobe {
>   #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0	11
>   #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE	12
>   #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0	13
> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
>   /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
>   
>   /* Flags */
> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> index 0b170e18a2be..40e7fa5f85f3 100644
> --- a/arch/riscv/kernel/sys_hwprobe.c
> +++ b/arch/riscv/kernel/sys_hwprobe.c
> @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
>   		hwprobe_isa_vendor_ext_thead_0(pair, cpus);
>   		break;
>   
> +	case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
> +		pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
> +		break;
> +
>   	/*
>   	 * For forward compatibility, unknown keys don't fail the whole
>   	 * call, but get their element key set to -1 and value set to 0
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-14  9:37   ` Alexandre Ghiti
@ 2025-08-14 10:32     ` Paris Oplopoios
  2025-08-14 11:22       ` Alexandre Ghiti
  0 siblings, 1 reply; 16+ messages in thread
From: Paris Oplopoios @ 2025-08-14 10:32 UTC (permalink / raw)
  To: Alexandre Ghiti; +Cc: linux-riscv, paul.walmsley, palmer, aou

Hello Alexandre,

> trying to figure out if an extension is available will likely result in a SIGILL, so that will kill your application

SIGILL can be captured with a signal handler and extension support can
be checked this way. Not all extensions can be detected using this
method, and it's much more straightforward to ask the kernel.

> Why don't you check the kernel config or even the hwprobe.h header? Since basically here, you use a syscall to return an information that is visible already from userspace.

To give an example, imagine a new extension Znew comes out, it
occupies the bit 1<<59. Let's say my kernel version was built with
support for detecting it and yours wasn't, but we both have the same
hardware. I compile a binary of a program that wants to do runtime
extension detection and I want to distribute it.

If I use the config or the hwprobe.h header during compilation time,
the compiled binary is assuming that both mine and your system have
this new bit. So when my program tries to detect it, it will find it
on my hardware but not yours. That's because my kernel was built to
support this bit in hwprobe but yours wasn't.

But in reality your hardware does have the extension. However, how
will my program differentiate from "doesn't have an extension" and
"kernel version not new enough"? Maybe I'd like to know that the
kernel doesn't have the bit, and notify the user with an "update your
kernel" message. Maybe I'd like to do the fallback SIGILL extension
detection instead.

PS: I'm assuming you meant checking config/hwprobe.h at compilation
time. If you meant parsing it at runtime, that simply wouldn't be
possible on all environments (think chroots).

On Thu, 14 Aug 2025 at 12:37, Alexandre Ghiti <alex@ghiti.fr> wrote:
>
> Hi Paris,
>
> On 8/13/25 20:05, offtkp wrote:
> > When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
> > bit in the resulting bitmask means the extension is not available or the
> > kernel is not recent enough to support the bit. Currently, there's no
> > way to differentiate between the two.
> >
> > This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
> > which returns a bitmask of all the queryable extensions supported by the
> > kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
> > fallback extension detection method when the bit they want to query is
> > not available in the kernel they are running on.
>
>
> Admittedly, I'm not convinced this is necessary. As you showed in your
> v1, trying to figure out if an extension is available will likely result
> in a SIGILL, so that will kill your application. Why don't you check the
> kernel config or even the hwprobe.h header? Since basically here, you
> use a syscall to return an information that is visible already from
> userspace.
>
> But maybe I'm missing an interesting usecase, just let me know.
>
> Thanks,
>
> Alex
>
>
> >
> > Signed-off-by: offtkp <parisoplop@gmail.com>
> > ---
> > Changes in v2:
> > - convert spaces to tabs
> > - use git format-patch to create diff
> >
> >   Documentation/arch/riscv/hwprobe.rst  | 5 ++++-
> >   arch/riscv/include/asm/hwprobe.h      | 3 ++-
> >   arch/riscv/include/uapi/asm/hwprobe.h | 2 ++
> >   arch/riscv/kernel/sys_hwprobe.c       | 4 ++++
> >   4 files changed, 12 insertions(+), 2 deletions(-)
> >
> > diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
> > index 2aa9be272d5d..6d77def0a46e 100644
> > --- a/Documentation/arch/riscv/hwprobe.rst
> > +++ b/Documentation/arch/riscv/hwprobe.rst
> > @@ -360,4 +360,7 @@ The following keys are defined:
> >
> >       * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
> >           vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
> > -     Instruction Extensions Specification.
> > \ No newline at end of file
> > +     Instruction Extensions Specification.
> > +
> > +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
> > +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
> > \ No newline at end of file
> > diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
> > index 7fe0a379474a..501d49b7a02a 100644
> > --- a/arch/riscv/include/asm/hwprobe.h
> > +++ b/arch/riscv/include/asm/hwprobe.h
> > @@ -8,7 +8,8 @@
> >
> >   #include <uapi/asm/hwprobe.h>
> >
> > -#define RISCV_HWPROBE_MAX_KEY 13
> > +#define RISCV_HWPROBE_MAX_KEY 14
> > +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE      ((1ULL << 59) - 1)
> >
> >   static inline bool riscv_hwprobe_key_is_valid(__s64 key)
> >   {
> > diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
> > index aaf6ad970499..a3b92df4dc05 100644
> > --- a/arch/riscv/include/uapi/asm/hwprobe.h
> > +++ b/arch/riscv/include/uapi/asm/hwprobe.h
> > @@ -82,6 +82,7 @@ struct riscv_hwprobe {
> >   #define             RISCV_HWPROBE_EXT_ZAAMO         (1ULL << 56)
> >   #define             RISCV_HWPROBE_EXT_ZALRSC        (1ULL << 57)
> >   #define             RISCV_HWPROBE_EXT_ZABHA         (1ULL << 58)
> > +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
> >   #define RISCV_HWPROBE_KEY_CPUPERF_0 5
> >   #define             RISCV_HWPROBE_MISALIGNED_UNKNOWN        (0 << 0)
> >   #define             RISCV_HWPROBE_MISALIGNED_EMULATED       (1 << 0)
> > @@ -106,6 +107,7 @@ struct riscv_hwprobe {
> >   #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0        11
> >   #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE 12
> >   #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0       13
> > +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
> >   /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
> >
> >   /* Flags */
> > diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> > index 0b170e18a2be..40e7fa5f85f3 100644
> > --- a/arch/riscv/kernel/sys_hwprobe.c
> > +++ b/arch/riscv/kernel/sys_hwprobe.c
> > @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
> >               hwprobe_isa_vendor_ext_thead_0(pair, cpus);
> >               break;
> >
> > +     case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
> > +             pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
> > +             break;
> > +
> >       /*
> >        * For forward compatibility, unknown keys don't fail the whole
> >        * call, but get their element key set to -1 and value set to 0
> >
> > _______________________________________________
> > linux-riscv mailing list
> > linux-riscv@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-14 10:32     ` Paris Oplopoios
@ 2025-08-14 11:22       ` Alexandre Ghiti
  2025-08-14 11:57         ` Paris Oplopoios
  0 siblings, 1 reply; 16+ messages in thread
From: Alexandre Ghiti @ 2025-08-14 11:22 UTC (permalink / raw)
  To: Paris Oplopoios; +Cc: linux-riscv, paul.walmsley, palmer, aou

On 8/14/25 12:32, Paris Oplopoios wrote:
> Hello Alexandre,
>
>> trying to figure out if an extension is available will likely result in a SIGILL, so that will kill your application
> SIGILL can be captured with a signal handler and extension support can
> be checked this way. Not all extensions can be detected using this
> method, and it's much more straightforward to ask the kernel.
>
>> Why don't you check the kernel config or even the hwprobe.h header? Since basically here, you use a syscall to return an information that is visible already from userspace.
> To give an example, imagine a new extension Znew comes out, it
> occupies the bit 1<<59. Let's say my kernel version was built with
> support for detecting it and yours wasn't, but we both have the same
> hardware. I compile a binary of a program that wants to do runtime
> extension detection and I want to distribute it.
>
> If I use the config or the hwprobe.h header during compilation time,
> the compiled binary is assuming that both mine and your system have
> this new bit. So when my program tries to detect it, it will find it
> on my hardware but not yours. That's because my kernel was built to
> support this bit in hwprobe but yours wasn't.
>
> But in reality your hardware does have the extension. However, how
> will my program differentiate from "doesn't have an extension" and
> "kernel version not new enough"? Maybe I'd like to know that the
> kernel doesn't have the bit, and notify the user with an "update your
> kernel" message. Maybe I'd like to do the fallback SIGILL extension
> detection instead.


What about parsing the isa string? And do you have a real usecase in 
mind? I mean which project would benefit from this?


>
> PS: I'm assuming you meant checking config/hwprobe.h at compilation
> time. If you meant parsing it at runtime, that simply wouldn't be
> possible on all environments (think chroots).
>
> On Thu, 14 Aug 2025 at 12:37, Alexandre Ghiti <alex@ghiti.fr> wrote:
>> Hi Paris,
>>
>> On 8/13/25 20:05, offtkp wrote:
>>> When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
>>> bit in the resulting bitmask means the extension is not available or the
>>> kernel is not recent enough to support the bit. Currently, there's no
>>> way to differentiate between the two.
>>>
>>> This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
>>> which returns a bitmask of all the queryable extensions supported by the
>>> kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
>>> fallback extension detection method when the bit they want to query is
>>> not available in the kernel they are running on.
>>
>> Admittedly, I'm not convinced this is necessary. As you showed in your
>> v1, trying to figure out if an extension is available will likely result
>> in a SIGILL, so that will kill your application. Why don't you check the
>> kernel config or even the hwprobe.h header? Since basically here, you
>> use a syscall to return an information that is visible already from
>> userspace.
>>
>> But maybe I'm missing an interesting usecase, just let me know.
>>
>> Thanks,
>>
>> Alex
>>
>>
>>> Signed-off-by: offtkp <parisoplop@gmail.com>
>>> ---
>>> Changes in v2:
>>> - convert spaces to tabs
>>> - use git format-patch to create diff
>>>
>>>    Documentation/arch/riscv/hwprobe.rst  | 5 ++++-
>>>    arch/riscv/include/asm/hwprobe.h      | 3 ++-
>>>    arch/riscv/include/uapi/asm/hwprobe.h | 2 ++
>>>    arch/riscv/kernel/sys_hwprobe.c       | 4 ++++
>>>    4 files changed, 12 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
>>> index 2aa9be272d5d..6d77def0a46e 100644
>>> --- a/Documentation/arch/riscv/hwprobe.rst
>>> +++ b/Documentation/arch/riscv/hwprobe.rst
>>> @@ -360,4 +360,7 @@ The following keys are defined:
>>>
>>>        * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
>>>            vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
>>> -     Instruction Extensions Specification.
>>> \ No newline at end of file
>>> +     Instruction Extensions Specification.
>>> +
>>> +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
>>> +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
>>> \ No newline at end of file
>>> diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
>>> index 7fe0a379474a..501d49b7a02a 100644
>>> --- a/arch/riscv/include/asm/hwprobe.h
>>> +++ b/arch/riscv/include/asm/hwprobe.h
>>> @@ -8,7 +8,8 @@
>>>
>>>    #include <uapi/asm/hwprobe.h>
>>>
>>> -#define RISCV_HWPROBE_MAX_KEY 13
>>> +#define RISCV_HWPROBE_MAX_KEY 14
>>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE      ((1ULL << 59) - 1)
>>>
>>>    static inline bool riscv_hwprobe_key_is_valid(__s64 key)
>>>    {
>>> diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
>>> index aaf6ad970499..a3b92df4dc05 100644
>>> --- a/arch/riscv/include/uapi/asm/hwprobe.h
>>> +++ b/arch/riscv/include/uapi/asm/hwprobe.h
>>> @@ -82,6 +82,7 @@ struct riscv_hwprobe {
>>>    #define             RISCV_HWPROBE_EXT_ZAAMO         (1ULL << 56)
>>>    #define             RISCV_HWPROBE_EXT_ZALRSC        (1ULL << 57)
>>>    #define             RISCV_HWPROBE_EXT_ZABHA         (1ULL << 58)
>>> +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
>>>    #define RISCV_HWPROBE_KEY_CPUPERF_0 5
>>>    #define             RISCV_HWPROBE_MISALIGNED_UNKNOWN        (0 << 0)
>>>    #define             RISCV_HWPROBE_MISALIGNED_EMULATED       (1 << 0)
>>> @@ -106,6 +107,7 @@ struct riscv_hwprobe {
>>>    #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0        11
>>>    #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE 12
>>>    #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0       13
>>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
>>>    /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
>>>
>>>    /* Flags */
>>> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
>>> index 0b170e18a2be..40e7fa5f85f3 100644
>>> --- a/arch/riscv/kernel/sys_hwprobe.c
>>> +++ b/arch/riscv/kernel/sys_hwprobe.c
>>> @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
>>>                hwprobe_isa_vendor_ext_thead_0(pair, cpus);
>>>                break;
>>>
>>> +     case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
>>> +             pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
>>> +             break;
>>> +
>>>        /*
>>>         * For forward compatibility, unknown keys don't fail the whole
>>>         * call, but get their element key set to -1 and value set to 0
>>>
>>> _______________________________________________
>>> linux-riscv mailing list
>>> linux-riscv@lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-14 11:22       ` Alexandre Ghiti
@ 2025-08-14 11:57         ` Paris Oplopoios
  2025-08-14 12:55           ` Alexandre Ghiti
  0 siblings, 1 reply; 16+ messages in thread
From: Paris Oplopoios @ 2025-08-14 11:57 UTC (permalink / raw)
  To: Alexandre Ghiti; +Cc: linux-riscv, paul.walmsley, palmer, aou

> What about parsing the isa string?

Yes, parsing the ISA string would work. But if we're going
to do that, we might as well not use hwprobe at all. In my
opinion, using the syscall is much easier to implement and maintain.


> And do you have a real usecase in
> mind? I mean which project would benefit from this?

Yes, I want this feature for an x86-on-RISC-V userspace emulator
called felix86. We do runtime extension detection for our JIT.
Currently, for any extension that defines instructions we use the SIGILL
method previously described, because there's no way to tell with just
a hwprobe call whether a 0 bit means extension not present or kernel
too old. But we can't do this for all extensions, some don't define
instructions.

The end goal would be being able to detect an extension using hwprobe, and if
it's not detectable, notifying the user that we can't detect it and
they can mark
it as enabled in the emulator's config file.

On Thu, 14 Aug 2025 at 14:22, Alexandre Ghiti <alex@ghiti.fr> wrote:
>
> On 8/14/25 12:32, Paris Oplopoios wrote:
> > Hello Alexandre,
> >
> >> trying to figure out if an extension is available will likely result in a SIGILL, so that will kill your application
> > SIGILL can be captured with a signal handler and extension support can
> > be checked this way. Not all extensions can be detected using this
> > method, and it's much more straightforward to ask the kernel.
> >
> >> Why don't you check the kernel config or even the hwprobe.h header? Since basically here, you use a syscall to return an information that is visible already from userspace.
> > To give an example, imagine a new extension Znew comes out, it
> > occupies the bit 1<<59. Let's say my kernel version was built with
> > support for detecting it and yours wasn't, but we both have the same
> > hardware. I compile a binary of a program that wants to do runtime
> > extension detection and I want to distribute it.
> >
> > If I use the config or the hwprobe.h header during compilation time,
> > the compiled binary is assuming that both mine and your system have
> > this new bit. So when my program tries to detect it, it will find it
> > on my hardware but not yours. That's because my kernel was built to
> > support this bit in hwprobe but yours wasn't.
> >
> > But in reality your hardware does have the extension. However, how
> > will my program differentiate from "doesn't have an extension" and
> > "kernel version not new enough"? Maybe I'd like to know that the
> > kernel doesn't have the bit, and notify the user with an "update your
> > kernel" message. Maybe I'd like to do the fallback SIGILL extension
> > detection instead.
>
>
> What about parsing the isa string? And do you have a real usecase in
> mind? I mean which project would benefit from this?
>
>
> >
> > PS: I'm assuming you meant checking config/hwprobe.h at compilation
> > time. If you meant parsing it at runtime, that simply wouldn't be
> > possible on all environments (think chroots).
> >
> > On Thu, 14 Aug 2025 at 12:37, Alexandre Ghiti <alex@ghiti.fr> wrote:
> >> Hi Paris,
> >>
> >> On 8/13/25 20:05, offtkp wrote:
> >>> When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
> >>> bit in the resulting bitmask means the extension is not available or the
> >>> kernel is not recent enough to support the bit. Currently, there's no
> >>> way to differentiate between the two.
> >>>
> >>> This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
> >>> which returns a bitmask of all the queryable extensions supported by the
> >>> kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
> >>> fallback extension detection method when the bit they want to query is
> >>> not available in the kernel they are running on.
> >>
> >> Admittedly, I'm not convinced this is necessary. As you showed in your
> >> v1, trying to figure out if an extension is available will likely result
> >> in a SIGILL, so that will kill your application. Why don't you check the
> >> kernel config or even the hwprobe.h header? Since basically here, you
> >> use a syscall to return an information that is visible already from
> >> userspace.
> >>
> >> But maybe I'm missing an interesting usecase, just let me know.
> >>
> >> Thanks,
> >>
> >> Alex
> >>
> >>
> >>> Signed-off-by: offtkp <parisoplop@gmail.com>
> >>> ---
> >>> Changes in v2:
> >>> - convert spaces to tabs
> >>> - use git format-patch to create diff
> >>>
> >>>    Documentation/arch/riscv/hwprobe.rst  | 5 ++++-
> >>>    arch/riscv/include/asm/hwprobe.h      | 3 ++-
> >>>    arch/riscv/include/uapi/asm/hwprobe.h | 2 ++
> >>>    arch/riscv/kernel/sys_hwprobe.c       | 4 ++++
> >>>    4 files changed, 12 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
> >>> index 2aa9be272d5d..6d77def0a46e 100644
> >>> --- a/Documentation/arch/riscv/hwprobe.rst
> >>> +++ b/Documentation/arch/riscv/hwprobe.rst
> >>> @@ -360,4 +360,7 @@ The following keys are defined:
> >>>
> >>>        * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
> >>>            vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
> >>> -     Instruction Extensions Specification.
> >>> \ No newline at end of file
> >>> +     Instruction Extensions Specification.
> >>> +
> >>> +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
> >>> +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
> >>> \ No newline at end of file
> >>> diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
> >>> index 7fe0a379474a..501d49b7a02a 100644
> >>> --- a/arch/riscv/include/asm/hwprobe.h
> >>> +++ b/arch/riscv/include/asm/hwprobe.h
> >>> @@ -8,7 +8,8 @@
> >>>
> >>>    #include <uapi/asm/hwprobe.h>
> >>>
> >>> -#define RISCV_HWPROBE_MAX_KEY 13
> >>> +#define RISCV_HWPROBE_MAX_KEY 14
> >>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE      ((1ULL << 59) - 1)
> >>>
> >>>    static inline bool riscv_hwprobe_key_is_valid(__s64 key)
> >>>    {
> >>> diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
> >>> index aaf6ad970499..a3b92df4dc05 100644
> >>> --- a/arch/riscv/include/uapi/asm/hwprobe.h
> >>> +++ b/arch/riscv/include/uapi/asm/hwprobe.h
> >>> @@ -82,6 +82,7 @@ struct riscv_hwprobe {
> >>>    #define             RISCV_HWPROBE_EXT_ZAAMO         (1ULL << 56)
> >>>    #define             RISCV_HWPROBE_EXT_ZALRSC        (1ULL << 57)
> >>>    #define             RISCV_HWPROBE_EXT_ZABHA         (1ULL << 58)
> >>> +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
> >>>    #define RISCV_HWPROBE_KEY_CPUPERF_0 5
> >>>    #define             RISCV_HWPROBE_MISALIGNED_UNKNOWN        (0 << 0)
> >>>    #define             RISCV_HWPROBE_MISALIGNED_EMULATED       (1 << 0)
> >>> @@ -106,6 +107,7 @@ struct riscv_hwprobe {
> >>>    #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0        11
> >>>    #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE 12
> >>>    #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0       13
> >>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
> >>>    /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
> >>>
> >>>    /* Flags */
> >>> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> >>> index 0b170e18a2be..40e7fa5f85f3 100644
> >>> --- a/arch/riscv/kernel/sys_hwprobe.c
> >>> +++ b/arch/riscv/kernel/sys_hwprobe.c
> >>> @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
> >>>                hwprobe_isa_vendor_ext_thead_0(pair, cpus);
> >>>                break;
> >>>
> >>> +     case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
> >>> +             pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
> >>> +             break;
> >>> +
> >>>        /*
> >>>         * For forward compatibility, unknown keys don't fail the whole
> >>>         * call, but get their element key set to -1 and value set to 0
> >>>
> >>> _______________________________________________
> >>> linux-riscv mailing list
> >>> linux-riscv@lists.infradead.org
> >>> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-14 11:57         ` Paris Oplopoios
@ 2025-08-14 12:55           ` Alexandre Ghiti
  2025-08-14 13:21             ` Paris Oplopoios
  0 siblings, 1 reply; 16+ messages in thread
From: Alexandre Ghiti @ 2025-08-14 12:55 UTC (permalink / raw)
  To: Paris Oplopoios; +Cc: linux-riscv, paul.walmsley, palmer, aou, Conor Dooley

On 8/14/25 13:57, Paris Oplopoios wrote:
>> What about parsing the isa string?
> Yes, parsing the ISA string would work. But if we're going
> to do that, we might as well not use hwprobe at all. In my
> opinion, using the syscall is much easier to implement and maintain.


You're right.


>
>
>> And do you have a real usecase in
>> mind? I mean which project would benefit from this?
> Yes, I want this feature for an x86-on-RISC-V userspace emulator
> called felix86. We do runtime extension detection for our JIT.
> Currently, for any extension that defines instructions we use the SIGILL
> method previously described, because there's no way to tell with just
> a hwprobe call whether a 0 bit means extension not present or kernel
> too old. But we can't do this for all extensions, some don't define
> instructions.
>
> The end goal would be being able to detect an extension using hwprobe, and if
> it's not detectable, notifying the user that we can't detect it and
> they can mark
> it as enabled in the emulator's config file.


Ok, I'm not opposed anymore, but I have added Conor in cc to have his 
opinion. Can you add that ^ to the change log? And now let's talk about 
the patch, see my comments below.


>
> On Thu, 14 Aug 2025 at 14:22, Alexandre Ghiti <alex@ghiti.fr> wrote:
>> On 8/14/25 12:32, Paris Oplopoios wrote:
>>> Hello Alexandre,
>>>
>>>> trying to figure out if an extension is available will likely result in a SIGILL, so that will kill your application
>>> SIGILL can be captured with a signal handler and extension support can
>>> be checked this way. Not all extensions can be detected using this
>>> method, and it's much more straightforward to ask the kernel.
>>>
>>>> Why don't you check the kernel config or even the hwprobe.h header? Since basically here, you use a syscall to return an information that is visible already from userspace.
>>> To give an example, imagine a new extension Znew comes out, it
>>> occupies the bit 1<<59. Let's say my kernel version was built with
>>> support for detecting it and yours wasn't, but we both have the same
>>> hardware. I compile a binary of a program that wants to do runtime
>>> extension detection and I want to distribute it.
>>>
>>> If I use the config or the hwprobe.h header during compilation time,
>>> the compiled binary is assuming that both mine and your system have
>>> this new bit. So when my program tries to detect it, it will find it
>>> on my hardware but not yours. That's because my kernel was built to
>>> support this bit in hwprobe but yours wasn't.
>>>
>>> But in reality your hardware does have the extension. However, how
>>> will my program differentiate from "doesn't have an extension" and
>>> "kernel version not new enough"? Maybe I'd like to know that the
>>> kernel doesn't have the bit, and notify the user with an "update your
>>> kernel" message. Maybe I'd like to do the fallback SIGILL extension
>>> detection instead.
>>
>> What about parsing the isa string? And do you have a real usecase in
>> mind? I mean which project would benefit from this?
>>
>>
>>> PS: I'm assuming you meant checking config/hwprobe.h at compilation
>>> time. If you meant parsing it at runtime, that simply wouldn't be
>>> possible on all environments (think chroots).
>>>
>>> On Thu, 14 Aug 2025 at 12:37, Alexandre Ghiti <alex@ghiti.fr> wrote:
>>>> Hi Paris,
>>>>
>>>> On 8/13/25 20:05, offtkp wrote:
>>>>> When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
>>>>> bit in the resulting bitmask means the extension is not available or the
>>>>> kernel is not recent enough to support the bit. Currently, there's no
>>>>> way to differentiate between the two.
>>>>>
>>>>> This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
>>>>> which returns a bitmask of all the queryable extensions supported by the
>>>>> kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
>>>>> fallback extension detection method when the bit they want to query is
>>>>> not available in the kernel they are running on.
>>>> Admittedly, I'm not convinced this is necessary. As you showed in your
>>>> v1, trying to figure out if an extension is available will likely result
>>>> in a SIGILL, so that will kill your application. Why don't you check the
>>>> kernel config or even the hwprobe.h header? Since basically here, you
>>>> use a syscall to return an information that is visible already from
>>>> userspace.
>>>>
>>>> But maybe I'm missing an interesting usecase, just let me know.
>>>>
>>>> Thanks,
>>>>
>>>> Alex
>>>>
>>>>
>>>>> Signed-off-by: offtkp <parisoplop@gmail.com>
>>>>> ---
>>>>> Changes in v2:
>>>>> - convert spaces to tabs
>>>>> - use git format-patch to create diff
>>>>>
>>>>>     Documentation/arch/riscv/hwprobe.rst  | 5 ++++-
>>>>>     arch/riscv/include/asm/hwprobe.h      | 3 ++-
>>>>>     arch/riscv/include/uapi/asm/hwprobe.h | 2 ++
>>>>>     arch/riscv/kernel/sys_hwprobe.c       | 4 ++++
>>>>>     4 files changed, 12 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
>>>>> index 2aa9be272d5d..6d77def0a46e 100644
>>>>> --- a/Documentation/arch/riscv/hwprobe.rst
>>>>> +++ b/Documentation/arch/riscv/hwprobe.rst
>>>>> @@ -360,4 +360,7 @@ The following keys are defined:
>>>>>
>>>>>         * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
>>>>>             vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
>>>>> -     Instruction Extensions Specification.
>>>>> \ No newline at end of file
>>>>> +     Instruction Extensions Specification.
>>>>> +
>>>>> +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
>>>>> +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
>>>>> \ No newline at end of file
>>>>> diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
>>>>> index 7fe0a379474a..501d49b7a02a 100644
>>>>> --- a/arch/riscv/include/asm/hwprobe.h
>>>>> +++ b/arch/riscv/include/asm/hwprobe.h
>>>>> @@ -8,7 +8,8 @@
>>>>>
>>>>>     #include <uapi/asm/hwprobe.h>
>>>>>
>>>>> -#define RISCV_HWPROBE_MAX_KEY 13
>>>>> +#define RISCV_HWPROBE_MAX_KEY 14
>>>>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE      ((1ULL << 59) - 1)


59 should not be hardcoded, even with your comment below. Let's 
introduce something like RISCV_HWPROBE_EXT_COUNT or similar.


>>>>>
>>>>>     static inline bool riscv_hwprobe_key_is_valid(__s64 key)
>>>>>     {
>>>>> diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
>>>>> index aaf6ad970499..a3b92df4dc05 100644
>>>>> --- a/arch/riscv/include/uapi/asm/hwprobe.h
>>>>> +++ b/arch/riscv/include/uapi/asm/hwprobe.h
>>>>> @@ -82,6 +82,7 @@ struct riscv_hwprobe {
>>>>>     #define             RISCV_HWPROBE_EXT_ZAAMO         (1ULL << 56)
>>>>>     #define             RISCV_HWPROBE_EXT_ZALRSC        (1ULL << 57)
>>>>>     #define             RISCV_HWPROBE_EXT_ZABHA         (1ULL << 58)
>>>>> +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
>>>>>     #define RISCV_HWPROBE_KEY_CPUPERF_0 5
>>>>>     #define             RISCV_HWPROBE_MISALIGNED_UNKNOWN        (0 << 0)
>>>>>     #define             RISCV_HWPROBE_MISALIGNED_EMULATED       (1 << 0)
>>>>> @@ -106,6 +107,7 @@ struct riscv_hwprobe {
>>>>>     #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0        11
>>>>>     #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE 12
>>>>>     #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0       13
>>>>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
>>>>>     /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
>>>>>
>>>>>     /* Flags */
>>>>> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
>>>>> index 0b170e18a2be..40e7fa5f85f3 100644
>>>>> --- a/arch/riscv/kernel/sys_hwprobe.c
>>>>> +++ b/arch/riscv/kernel/sys_hwprobe.c
>>>>> @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
>>>>>                 hwprobe_isa_vendor_ext_thead_0(pair, cpus);
>>>>>                 break;
>>>>>
>>>>> +     case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
>>>>> +             pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;


You don't really need to return a mask here, you can simply return 
RISCV_HWPROBE_EXT_COUNT and let the userspace deal with the mask.


>>>>> +             break;
>>>>> +
>>>>>         /*
>>>>>          * For forward compatibility, unknown keys don't fail the whole
>>>>>          * call, but get their element key set to -1 and value set to 0
>>>>>
>>>>> _______________________________________________
>>>>> linux-riscv mailing list
>>>>> linux-riscv@lists.infradead.org
>>>>> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-14 12:55           ` Alexandre Ghiti
@ 2025-08-14 13:21             ` Paris Oplopoios
  2025-08-14 13:56               ` Alexandre Ghiti
  0 siblings, 1 reply; 16+ messages in thread
From: Paris Oplopoios @ 2025-08-14 13:21 UTC (permalink / raw)
  To: Alexandre Ghiti; +Cc: linux-riscv, paul.walmsley, palmer, aou, Conor Dooley

> Can you add that ^ to the change log?

I'm new to kernel development, could you elaborate? Do you want me to make
a v3 patch and add the points from our conversation to the changelog?

> 59 should not be hardcoded, even with your comment below. Let's introduce
> something like RISCV_HWPROBE_EXT_COUNT or similar.
> You don't really need to return a mask here, you can simply return
> RISCV_HWPROBE_EXT_COUNT and let the userspace deal with the mask.

I do agree that the number 59 shouldn't be hardcoded, but I think returning
a mask is more user-friendly. If we return a number, the userspace
would have to do:

     if (value == 64) {
         mask = -1ull;
     } else {
         mask = (1ull << value) - 1;
     }

to construct a mask and be able to check availability via (mask &
RISCV_HWPROBE_EXT_ZNEW).
IMO, this makes the API more unfriendly than returning a mask.

I think perhaps a better solution is constructing the mask by ORing
all the available extensions
and returning that. What do you think?

On Thu, 14 Aug 2025 at 15:55, Alexandre Ghiti <alex@ghiti.fr> wrote:
>
> On 8/14/25 13:57, Paris Oplopoios wrote:
> >> What about parsing the isa string?
> > Yes, parsing the ISA string would work. But if we're going
> > to do that, we might as well not use hwprobe at all. In my
> > opinion, using the syscall is much easier to implement and maintain.
>
>
> You're right.
>
>
> >
> >
> >> And do you have a real usecase in
> >> mind? I mean which project would benefit from this?
> > Yes, I want this feature for an x86-on-RISC-V userspace emulator
> > called felix86. We do runtime extension detection for our JIT.
> > Currently, for any extension that defines instructions we use the SIGILL
> > method previously described, because there's no way to tell with just
> > a hwprobe call whether a 0 bit means extension not present or kernel
> > too old. But we can't do this for all extensions, some don't define
> > instructions.
> >
> > The end goal would be being able to detect an extension using hwprobe, and if
> > it's not detectable, notifying the user that we can't detect it and
> > they can mark
> > it as enabled in the emulator's config file.
>
>
> Ok, I'm not opposed anymore, but I have added Conor in cc to have his
> opinion. Can you add that ^ to the change log? And now let's talk about
> the patch, see my comments below.
>
>
> >
> > On Thu, 14 Aug 2025 at 14:22, Alexandre Ghiti <alex@ghiti.fr> wrote:
> >> On 8/14/25 12:32, Paris Oplopoios wrote:
> >>> Hello Alexandre,
> >>>
> >>>> trying to figure out if an extension is available will likely result in a SIGILL, so that will kill your application
> >>> SIGILL can be captured with a signal handler and extension support can
> >>> be checked this way. Not all extensions can be detected using this
> >>> method, and it's much more straightforward to ask the kernel.
> >>>
> >>>> Why don't you check the kernel config or even the hwprobe.h header? Since basically here, you use a syscall to return an information that is visible already from userspace.
> >>> To give an example, imagine a new extension Znew comes out, it
> >>> occupies the bit 1<<59. Let's say my kernel version was built with
> >>> support for detecting it and yours wasn't, but we both have the same
> >>> hardware. I compile a binary of a program that wants to do runtime
> >>> extension detection and I want to distribute it.
> >>>
> >>> If I use the config or the hwprobe.h header during compilation time,
> >>> the compiled binary is assuming that both mine and your system have
> >>> this new bit. So when my program tries to detect it, it will find it
> >>> on my hardware but not yours. That's because my kernel was built to
> >>> support this bit in hwprobe but yours wasn't.
> >>>
> >>> But in reality your hardware does have the extension. However, how
> >>> will my program differentiate from "doesn't have an extension" and
> >>> "kernel version not new enough"? Maybe I'd like to know that the
> >>> kernel doesn't have the bit, and notify the user with an "update your
> >>> kernel" message. Maybe I'd like to do the fallback SIGILL extension
> >>> detection instead.
> >>
> >> What about parsing the isa string? And do you have a real usecase in
> >> mind? I mean which project would benefit from this?
> >>
> >>
> >>> PS: I'm assuming you meant checking config/hwprobe.h at compilation
> >>> time. If you meant parsing it at runtime, that simply wouldn't be
> >>> possible on all environments (think chroots).
> >>>
> >>> On Thu, 14 Aug 2025 at 12:37, Alexandre Ghiti <alex@ghiti.fr> wrote:
> >>>> Hi Paris,
> >>>>
> >>>> On 8/13/25 20:05, offtkp wrote:
> >>>>> When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
> >>>>> bit in the resulting bitmask means the extension is not available or the
> >>>>> kernel is not recent enough to support the bit. Currently, there's no
> >>>>> way to differentiate between the two.
> >>>>>
> >>>>> This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
> >>>>> which returns a bitmask of all the queryable extensions supported by the
> >>>>> kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
> >>>>> fallback extension detection method when the bit they want to query is
> >>>>> not available in the kernel they are running on.
> >>>> Admittedly, I'm not convinced this is necessary. As you showed in your
> >>>> v1, trying to figure out if an extension is available will likely result
> >>>> in a SIGILL, so that will kill your application. Why don't you check the
> >>>> kernel config or even the hwprobe.h header? Since basically here, you
> >>>> use a syscall to return an information that is visible already from
> >>>> userspace.
> >>>>
> >>>> But maybe I'm missing an interesting usecase, just let me know.
> >>>>
> >>>> Thanks,
> >>>>
> >>>> Alex
> >>>>
> >>>>
> >>>>> Signed-off-by: offtkp <parisoplop@gmail.com>
> >>>>> ---
> >>>>> Changes in v2:
> >>>>> - convert spaces to tabs
> >>>>> - use git format-patch to create diff
> >>>>>
> >>>>>     Documentation/arch/riscv/hwprobe.rst  | 5 ++++-
> >>>>>     arch/riscv/include/asm/hwprobe.h      | 3 ++-
> >>>>>     arch/riscv/include/uapi/asm/hwprobe.h | 2 ++
> >>>>>     arch/riscv/kernel/sys_hwprobe.c       | 4 ++++
> >>>>>     4 files changed, 12 insertions(+), 2 deletions(-)
> >>>>>
> >>>>> diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
> >>>>> index 2aa9be272d5d..6d77def0a46e 100644
> >>>>> --- a/Documentation/arch/riscv/hwprobe.rst
> >>>>> +++ b/Documentation/arch/riscv/hwprobe.rst
> >>>>> @@ -360,4 +360,7 @@ The following keys are defined:
> >>>>>
> >>>>>         * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
> >>>>>             vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
> >>>>> -     Instruction Extensions Specification.
> >>>>> \ No newline at end of file
> >>>>> +     Instruction Extensions Specification.
> >>>>> +
> >>>>> +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
> >>>>> +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
> >>>>> \ No newline at end of file
> >>>>> diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
> >>>>> index 7fe0a379474a..501d49b7a02a 100644
> >>>>> --- a/arch/riscv/include/asm/hwprobe.h
> >>>>> +++ b/arch/riscv/include/asm/hwprobe.h
> >>>>> @@ -8,7 +8,8 @@
> >>>>>
> >>>>>     #include <uapi/asm/hwprobe.h>
> >>>>>
> >>>>> -#define RISCV_HWPROBE_MAX_KEY 13
> >>>>> +#define RISCV_HWPROBE_MAX_KEY 14
> >>>>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE      ((1ULL << 59) - 1)
>
>
> 59 should not be hardcoded, even with your comment below. Let's
> introduce something like RISCV_HWPROBE_EXT_COUNT or similar.
>
>
> >>>>>
> >>>>>     static inline bool riscv_hwprobe_key_is_valid(__s64 key)
> >>>>>     {
> >>>>> diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
> >>>>> index aaf6ad970499..a3b92df4dc05 100644
> >>>>> --- a/arch/riscv/include/uapi/asm/hwprobe.h
> >>>>> +++ b/arch/riscv/include/uapi/asm/hwprobe.h
> >>>>> @@ -82,6 +82,7 @@ struct riscv_hwprobe {
> >>>>>     #define             RISCV_HWPROBE_EXT_ZAAMO         (1ULL << 56)
> >>>>>     #define             RISCV_HWPROBE_EXT_ZALRSC        (1ULL << 57)
> >>>>>     #define             RISCV_HWPROBE_EXT_ZABHA         (1ULL << 58)
> >>>>> +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
> >>>>>     #define RISCV_HWPROBE_KEY_CPUPERF_0 5
> >>>>>     #define             RISCV_HWPROBE_MISALIGNED_UNKNOWN        (0 << 0)
> >>>>>     #define             RISCV_HWPROBE_MISALIGNED_EMULATED       (1 << 0)
> >>>>> @@ -106,6 +107,7 @@ struct riscv_hwprobe {
> >>>>>     #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0        11
> >>>>>     #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE 12
> >>>>>     #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0       13
> >>>>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
> >>>>>     /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
> >>>>>
> >>>>>     /* Flags */
> >>>>> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> >>>>> index 0b170e18a2be..40e7fa5f85f3 100644
> >>>>> --- a/arch/riscv/kernel/sys_hwprobe.c
> >>>>> +++ b/arch/riscv/kernel/sys_hwprobe.c
> >>>>> @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
> >>>>>                 hwprobe_isa_vendor_ext_thead_0(pair, cpus);
> >>>>>                 break;
> >>>>>
> >>>>> +     case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
> >>>>> +             pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
>
>
> You don't really need to return a mask here, you can simply return
> RISCV_HWPROBE_EXT_COUNT and let the userspace deal with the mask.
>
>
> >>>>> +             break;
> >>>>> +
> >>>>>         /*
> >>>>>          * For forward compatibility, unknown keys don't fail the whole
> >>>>>          * call, but get their element key set to -1 and value set to 0
> >>>>>
> >>>>> _______________________________________________
> >>>>> linux-riscv mailing list
> >>>>> linux-riscv@lists.infradead.org
> >>>>> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-14 13:21             ` Paris Oplopoios
@ 2025-08-14 13:56               ` Alexandre Ghiti
  2025-08-14 14:20                 ` Paris Oplopoios
  0 siblings, 1 reply; 16+ messages in thread
From: Alexandre Ghiti @ 2025-08-14 13:56 UTC (permalink / raw)
  To: Paris Oplopoios; +Cc: linux-riscv, paul.walmsley, palmer, aou, Conor Dooley

On 8/14/25 15:21, Paris Oplopoios wrote:
>> Can you add that ^ to the change log?
> I'm new to kernel development, could you elaborate? Do you want me to make
> a v3 patch and add the points from our conversation to the changelog?


Yes, I think it's nice to have the motivations behind a patch in the 
change log.


>
>> 59 should not be hardcoded, even with your comment below. Let's introduce
>> something like RISCV_HWPROBE_EXT_COUNT or similar.
>> You don't really need to return a mask here, you can simply return
>> RISCV_HWPROBE_EXT_COUNT and let the userspace deal with the mask.
> I do agree that the number 59 shouldn't be hardcoded, but I think returning
> a mask is more user-friendly. If we return a number, the userspace
> would have to do:
>
>       if (value == 64) {
>           mask = -1ull;
>       } else {
>           mask = (1ull << value) - 1;
>       }
>
> to construct a mask and be able to check availability via (mask &
> RISCV_HWPROBE_EXT_ZNEW).
> IMO, this makes the API more unfriendly than returning a mask.


You can simply get the position of the bit RISCV_HWPROBE_EXT_ZNEW and 
make sure it's lower than RISCV_HWPROBE_EXT_COUNT, which is way easier 
than dealing with >64bit bitmasks.

I have to admit that I don't know how the interface was thought when the 
number of extensions will be greater than 64, I guess we'll introduce 
RISCV_HWPROBE_KEY_IMA_EXT_1 and the user will have to ask explicitly for 
those. But to ask for more, the user will first need to know that more 
extensions exist. One way would be to ask for the number of extensions 
first, which would be RISCV_HWPROBE_EXT_COUNT. And then we kill two 
birds with one stone :)

I may have missed something though because current applications would 
not know about this and will have to be updated.


>
> I think perhaps a better solution is constructing the mask by ORing
> all the available extensions
> and returning that. What do you think?


Sorry I did not get what you mean here.


>
> On Thu, 14 Aug 2025 at 15:55, Alexandre Ghiti <alex@ghiti.fr> wrote:
>> On 8/14/25 13:57, Paris Oplopoios wrote:
>>>> What about parsing the isa string?
>>> Yes, parsing the ISA string would work. But if we're going
>>> to do that, we might as well not use hwprobe at all. In my
>>> opinion, using the syscall is much easier to implement and maintain.
>>
>> You're right.
>>
>>
>>>
>>>> And do you have a real usecase in
>>>> mind? I mean which project would benefit from this?
>>> Yes, I want this feature for an x86-on-RISC-V userspace emulator
>>> called felix86. We do runtime extension detection for our JIT.
>>> Currently, for any extension that defines instructions we use the SIGILL
>>> method previously described, because there's no way to tell with just
>>> a hwprobe call whether a 0 bit means extension not present or kernel
>>> too old. But we can't do this for all extensions, some don't define
>>> instructions.
>>>
>>> The end goal would be being able to detect an extension using hwprobe, and if
>>> it's not detectable, notifying the user that we can't detect it and
>>> they can mark
>>> it as enabled in the emulator's config file.
>>
>> Ok, I'm not opposed anymore, but I have added Conor in cc to have his
>> opinion. Can you add that ^ to the change log? And now let's talk about
>> the patch, see my comments below.
>>
>>
>>> On Thu, 14 Aug 2025 at 14:22, Alexandre Ghiti <alex@ghiti.fr> wrote:
>>>> On 8/14/25 12:32, Paris Oplopoios wrote:
>>>>> Hello Alexandre,
>>>>>
>>>>>> trying to figure out if an extension is available will likely result in a SIGILL, so that will kill your application
>>>>> SIGILL can be captured with a signal handler and extension support can
>>>>> be checked this way. Not all extensions can be detected using this
>>>>> method, and it's much more straightforward to ask the kernel.
>>>>>
>>>>>> Why don't you check the kernel config or even the hwprobe.h header? Since basically here, you use a syscall to return an information that is visible already from userspace.
>>>>> To give an example, imagine a new extension Znew comes out, it
>>>>> occupies the bit 1<<59. Let's say my kernel version was built with
>>>>> support for detecting it and yours wasn't, but we both have the same
>>>>> hardware. I compile a binary of a program that wants to do runtime
>>>>> extension detection and I want to distribute it.
>>>>>
>>>>> If I use the config or the hwprobe.h header during compilation time,
>>>>> the compiled binary is assuming that both mine and your system have
>>>>> this new bit. So when my program tries to detect it, it will find it
>>>>> on my hardware but not yours. That's because my kernel was built to
>>>>> support this bit in hwprobe but yours wasn't.
>>>>>
>>>>> But in reality your hardware does have the extension. However, how
>>>>> will my program differentiate from "doesn't have an extension" and
>>>>> "kernel version not new enough"? Maybe I'd like to know that the
>>>>> kernel doesn't have the bit, and notify the user with an "update your
>>>>> kernel" message. Maybe I'd like to do the fallback SIGILL extension
>>>>> detection instead.
>>>> What about parsing the isa string? And do you have a real usecase in
>>>> mind? I mean which project would benefit from this?
>>>>
>>>>
>>>>> PS: I'm assuming you meant checking config/hwprobe.h at compilation
>>>>> time. If you meant parsing it at runtime, that simply wouldn't be
>>>>> possible on all environments (think chroots).
>>>>>
>>>>> On Thu, 14 Aug 2025 at 12:37, Alexandre Ghiti <alex@ghiti.fr> wrote:
>>>>>> Hi Paris,
>>>>>>
>>>>>> On 8/13/25 20:05, offtkp wrote:
>>>>>>> When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
>>>>>>> bit in the resulting bitmask means the extension is not available or the
>>>>>>> kernel is not recent enough to support the bit. Currently, there's no
>>>>>>> way to differentiate between the two.
>>>>>>>
>>>>>>> This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
>>>>>>> which returns a bitmask of all the queryable extensions supported by the
>>>>>>> kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
>>>>>>> fallback extension detection method when the bit they want to query is
>>>>>>> not available in the kernel they are running on.
>>>>>> Admittedly, I'm not convinced this is necessary. As you showed in your
>>>>>> v1, trying to figure out if an extension is available will likely result
>>>>>> in a SIGILL, so that will kill your application. Why don't you check the
>>>>>> kernel config or even the hwprobe.h header? Since basically here, you
>>>>>> use a syscall to return an information that is visible already from
>>>>>> userspace.
>>>>>>
>>>>>> But maybe I'm missing an interesting usecase, just let me know.
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Alex
>>>>>>
>>>>>>
>>>>>>> Signed-off-by: offtkp <parisoplop@gmail.com>
>>>>>>> ---
>>>>>>> Changes in v2:
>>>>>>> - convert spaces to tabs
>>>>>>> - use git format-patch to create diff
>>>>>>>
>>>>>>>      Documentation/arch/riscv/hwprobe.rst  | 5 ++++-
>>>>>>>      arch/riscv/include/asm/hwprobe.h      | 3 ++-
>>>>>>>      arch/riscv/include/uapi/asm/hwprobe.h | 2 ++
>>>>>>>      arch/riscv/kernel/sys_hwprobe.c       | 4 ++++
>>>>>>>      4 files changed, 12 insertions(+), 2 deletions(-)
>>>>>>>
>>>>>>> diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
>>>>>>> index 2aa9be272d5d..6d77def0a46e 100644
>>>>>>> --- a/Documentation/arch/riscv/hwprobe.rst
>>>>>>> +++ b/Documentation/arch/riscv/hwprobe.rst
>>>>>>> @@ -360,4 +360,7 @@ The following keys are defined:
>>>>>>>
>>>>>>>          * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
>>>>>>>              vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
>>>>>>> -     Instruction Extensions Specification.
>>>>>>> \ No newline at end of file
>>>>>>> +     Instruction Extensions Specification.
>>>>>>> +
>>>>>>> +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
>>>>>>> +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
>>>>>>> \ No newline at end of file
>>>>>>> diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
>>>>>>> index 7fe0a379474a..501d49b7a02a 100644
>>>>>>> --- a/arch/riscv/include/asm/hwprobe.h
>>>>>>> +++ b/arch/riscv/include/asm/hwprobe.h
>>>>>>> @@ -8,7 +8,8 @@
>>>>>>>
>>>>>>>      #include <uapi/asm/hwprobe.h>
>>>>>>>
>>>>>>> -#define RISCV_HWPROBE_MAX_KEY 13
>>>>>>> +#define RISCV_HWPROBE_MAX_KEY 14
>>>>>>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE      ((1ULL << 59) - 1)
>>
>> 59 should not be hardcoded, even with your comment below. Let's
>> introduce something like RISCV_HWPROBE_EXT_COUNT or similar.
>>
>>
>>>>>>>      static inline bool riscv_hwprobe_key_is_valid(__s64 key)
>>>>>>>      {
>>>>>>> diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
>>>>>>> index aaf6ad970499..a3b92df4dc05 100644
>>>>>>> --- a/arch/riscv/include/uapi/asm/hwprobe.h
>>>>>>> +++ b/arch/riscv/include/uapi/asm/hwprobe.h
>>>>>>> @@ -82,6 +82,7 @@ struct riscv_hwprobe {
>>>>>>>      #define             RISCV_HWPROBE_EXT_ZAAMO         (1ULL << 56)
>>>>>>>      #define             RISCV_HWPROBE_EXT_ZALRSC        (1ULL << 57)
>>>>>>>      #define             RISCV_HWPROBE_EXT_ZABHA         (1ULL << 58)
>>>>>>> +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
>>>>>>>      #define RISCV_HWPROBE_KEY_CPUPERF_0 5
>>>>>>>      #define             RISCV_HWPROBE_MISALIGNED_UNKNOWN        (0 << 0)
>>>>>>>      #define             RISCV_HWPROBE_MISALIGNED_EMULATED       (1 << 0)
>>>>>>> @@ -106,6 +107,7 @@ struct riscv_hwprobe {
>>>>>>>      #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0        11
>>>>>>>      #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE 12
>>>>>>>      #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0       13
>>>>>>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
>>>>>>>      /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
>>>>>>>
>>>>>>>      /* Flags */
>>>>>>> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
>>>>>>> index 0b170e18a2be..40e7fa5f85f3 100644
>>>>>>> --- a/arch/riscv/kernel/sys_hwprobe.c
>>>>>>> +++ b/arch/riscv/kernel/sys_hwprobe.c
>>>>>>> @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
>>>>>>>                  hwprobe_isa_vendor_ext_thead_0(pair, cpus);
>>>>>>>                  break;
>>>>>>>
>>>>>>> +     case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
>>>>>>> +             pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
>>
>> You don't really need to return a mask here, you can simply return
>> RISCV_HWPROBE_EXT_COUNT and let the userspace deal with the mask.
>>
>>
>>>>>>> +             break;
>>>>>>> +
>>>>>>>          /*
>>>>>>>           * For forward compatibility, unknown keys don't fail the whole
>>>>>>>           * call, but get their element key set to -1 and value set to 0
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> linux-riscv mailing list
>>>>>>> linux-riscv@lists.infradead.org
>>>>>>> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-14 13:56               ` Alexandre Ghiti
@ 2025-08-14 14:20                 ` Paris Oplopoios
  0 siblings, 0 replies; 16+ messages in thread
From: Paris Oplopoios @ 2025-08-14 14:20 UTC (permalink / raw)
  To: Alexandre Ghiti; +Cc: linux-riscv, paul.walmsley, palmer, aou, Conor Dooley

> You can simply get the position of the bit RISCV_HWPROBE_EXT_ZNEW and
> make sure it's lower than RISCV_HWPROBE_EXT_COUNT, which is way easier
> than dealing with >64bit bitmasks.

There won't really ever be >64bit bitmasks, as they get split into
different keys.

> I have to admit that I don't know how the interface was thought when the
> number of extensions will be greater than 64, I guess we'll introduce
> RISCV_HWPROBE_KEY_IMA_EXT_1
Yes, I'm pretty sure that's the idea.

> One way would be to ask for the number of extensions
> first, which would be RISCV_HWPROBE_EXT_COUNT. And then we kill two
> birds with one stone :)

If it absolutely had to be a count, it would still need to be a count per key.
Currently, there's RISCV_HWPROBE_KEY_IMA_EXT_0. In the future most likely
there will be a RISCV_HWPROBE_KEY_IMA_EXT_1.
But you also need to consider there's keys for custom extensions, such as
RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0, RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0,
and most likely more in the future. A single global extension counter wouldn't
cover this.

> Sorry I did not get what you mean here.
Example:

#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL (RISCV_HWPROBE_IMA_FD |
     RISCV_HWPROBE_IMA_C | RISCV_HWPROBE_IMA_V | ... | RISCV_HWPROBE_EXT_ZABHA)

On Thu, 14 Aug 2025 at 16:56, Alexandre Ghiti <alex@ghiti.fr> wrote:
>
> On 8/14/25 15:21, Paris Oplopoios wrote:
> >> Can you add that ^ to the change log?
> > I'm new to kernel development, could you elaborate? Do you want me to make
> > a v3 patch and add the points from our conversation to the changelog?
>
>
> Yes, I think it's nice to have the motivations behind a patch in the
> change log.
>
>
> >
> >> 59 should not be hardcoded, even with your comment below. Let's introduce
> >> something like RISCV_HWPROBE_EXT_COUNT or similar.
> >> You don't really need to return a mask here, you can simply return
> >> RISCV_HWPROBE_EXT_COUNT and let the userspace deal with the mask.
> > I do agree that the number 59 shouldn't be hardcoded, but I think returning
> > a mask is more user-friendly. If we return a number, the userspace
> > would have to do:
> >
> >       if (value == 64) {
> >           mask = -1ull;
> >       } else {
> >           mask = (1ull << value) - 1;
> >       }
> >
> > to construct a mask and be able to check availability via (mask &
> > RISCV_HWPROBE_EXT_ZNEW).
> > IMO, this makes the API more unfriendly than returning a mask.
>
>
> You can simply get the position of the bit RISCV_HWPROBE_EXT_ZNEW and
> make sure it's lower than RISCV_HWPROBE_EXT_COUNT, which is way easier
> than dealing with >64bit bitmasks.
>
> I have to admit that I don't know how the interface was thought when the
> number of extensions will be greater than 64, I guess we'll introduce
> RISCV_HWPROBE_KEY_IMA_EXT_1 and the user will have to ask explicitly for
> those. But to ask for more, the user will first need to know that more
> extensions exist. One way would be to ask for the number of extensions
> first, which would be RISCV_HWPROBE_EXT_COUNT. And then we kill two
> birds with one stone :)
>
> I may have missed something though because current applications would
> not know about this and will have to be updated.
>
>
> >
> > I think perhaps a better solution is constructing the mask by ORing
> > all the available extensions
> > and returning that. What do you think?
>
>
> Sorry I did not get what you mean here.
>
>
> >
> > On Thu, 14 Aug 2025 at 15:55, Alexandre Ghiti <alex@ghiti.fr> wrote:
> >> On 8/14/25 13:57, Paris Oplopoios wrote:
> >>>> What about parsing the isa string?
> >>> Yes, parsing the ISA string would work. But if we're going
> >>> to do that, we might as well not use hwprobe at all. In my
> >>> opinion, using the syscall is much easier to implement and maintain.
> >>
> >> You're right.
> >>
> >>
> >>>
> >>>> And do you have a real usecase in
> >>>> mind? I mean which project would benefit from this?
> >>> Yes, I want this feature for an x86-on-RISC-V userspace emulator
> >>> called felix86. We do runtime extension detection for our JIT.
> >>> Currently, for any extension that defines instructions we use the SIGILL
> >>> method previously described, because there's no way to tell with just
> >>> a hwprobe call whether a 0 bit means extension not present or kernel
> >>> too old. But we can't do this for all extensions, some don't define
> >>> instructions.
> >>>
> >>> The end goal would be being able to detect an extension using hwprobe, and if
> >>> it's not detectable, notifying the user that we can't detect it and
> >>> they can mark
> >>> it as enabled in the emulator's config file.
> >>
> >> Ok, I'm not opposed anymore, but I have added Conor in cc to have his
> >> opinion. Can you add that ^ to the change log? And now let's talk about
> >> the patch, see my comments below.
> >>
> >>
> >>> On Thu, 14 Aug 2025 at 14:22, Alexandre Ghiti <alex@ghiti.fr> wrote:
> >>>> On 8/14/25 12:32, Paris Oplopoios wrote:
> >>>>> Hello Alexandre,
> >>>>>
> >>>>>> trying to figure out if an extension is available will likely result in a SIGILL, so that will kill your application
> >>>>> SIGILL can be captured with a signal handler and extension support can
> >>>>> be checked this way. Not all extensions can be detected using this
> >>>>> method, and it's much more straightforward to ask the kernel.
> >>>>>
> >>>>>> Why don't you check the kernel config or even the hwprobe.h header? Since basically here, you use a syscall to return an information that is visible already from userspace.
> >>>>> To give an example, imagine a new extension Znew comes out, it
> >>>>> occupies the bit 1<<59. Let's say my kernel version was built with
> >>>>> support for detecting it and yours wasn't, but we both have the same
> >>>>> hardware. I compile a binary of a program that wants to do runtime
> >>>>> extension detection and I want to distribute it.
> >>>>>
> >>>>> If I use the config or the hwprobe.h header during compilation time,
> >>>>> the compiled binary is assuming that both mine and your system have
> >>>>> this new bit. So when my program tries to detect it, it will find it
> >>>>> on my hardware but not yours. That's because my kernel was built to
> >>>>> support this bit in hwprobe but yours wasn't.
> >>>>>
> >>>>> But in reality your hardware does have the extension. However, how
> >>>>> will my program differentiate from "doesn't have an extension" and
> >>>>> "kernel version not new enough"? Maybe I'd like to know that the
> >>>>> kernel doesn't have the bit, and notify the user with an "update your
> >>>>> kernel" message. Maybe I'd like to do the fallback SIGILL extension
> >>>>> detection instead.
> >>>> What about parsing the isa string? And do you have a real usecase in
> >>>> mind? I mean which project would benefit from this?
> >>>>
> >>>>
> >>>>> PS: I'm assuming you meant checking config/hwprobe.h at compilation
> >>>>> time. If you meant parsing it at runtime, that simply wouldn't be
> >>>>> possible on all environments (think chroots).
> >>>>>
> >>>>> On Thu, 14 Aug 2025 at 12:37, Alexandre Ghiti <alex@ghiti.fr> wrote:
> >>>>>> Hi Paris,
> >>>>>>
> >>>>>> On 8/13/25 20:05, offtkp wrote:
> >>>>>>> When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
> >>>>>>> bit in the resulting bitmask means the extension is not available or the
> >>>>>>> kernel is not recent enough to support the bit. Currently, there's no
> >>>>>>> way to differentiate between the two.
> >>>>>>>
> >>>>>>> This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
> >>>>>>> which returns a bitmask of all the queryable extensions supported by the
> >>>>>>> kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
> >>>>>>> fallback extension detection method when the bit they want to query is
> >>>>>>> not available in the kernel they are running on.
> >>>>>> Admittedly, I'm not convinced this is necessary. As you showed in your
> >>>>>> v1, trying to figure out if an extension is available will likely result
> >>>>>> in a SIGILL, so that will kill your application. Why don't you check the
> >>>>>> kernel config or even the hwprobe.h header? Since basically here, you
> >>>>>> use a syscall to return an information that is visible already from
> >>>>>> userspace.
> >>>>>>
> >>>>>> But maybe I'm missing an interesting usecase, just let me know.
> >>>>>>
> >>>>>> Thanks,
> >>>>>>
> >>>>>> Alex
> >>>>>>
> >>>>>>
> >>>>>>> Signed-off-by: offtkp <parisoplop@gmail.com>
> >>>>>>> ---
> >>>>>>> Changes in v2:
> >>>>>>> - convert spaces to tabs
> >>>>>>> - use git format-patch to create diff
> >>>>>>>
> >>>>>>>      Documentation/arch/riscv/hwprobe.rst  | 5 ++++-
> >>>>>>>      arch/riscv/include/asm/hwprobe.h      | 3 ++-
> >>>>>>>      arch/riscv/include/uapi/asm/hwprobe.h | 2 ++
> >>>>>>>      arch/riscv/kernel/sys_hwprobe.c       | 4 ++++
> >>>>>>>      4 files changed, 12 insertions(+), 2 deletions(-)
> >>>>>>>
> >>>>>>> diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
> >>>>>>> index 2aa9be272d5d..6d77def0a46e 100644
> >>>>>>> --- a/Documentation/arch/riscv/hwprobe.rst
> >>>>>>> +++ b/Documentation/arch/riscv/hwprobe.rst
> >>>>>>> @@ -360,4 +360,7 @@ The following keys are defined:
> >>>>>>>
> >>>>>>>          * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
> >>>>>>>              vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
> >>>>>>> -     Instruction Extensions Specification.
> >>>>>>> \ No newline at end of file
> >>>>>>> +     Instruction Extensions Specification.
> >>>>>>> +
> >>>>>>> +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
> >>>>>>> +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
> >>>>>>> \ No newline at end of file
> >>>>>>> diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
> >>>>>>> index 7fe0a379474a..501d49b7a02a 100644
> >>>>>>> --- a/arch/riscv/include/asm/hwprobe.h
> >>>>>>> +++ b/arch/riscv/include/asm/hwprobe.h
> >>>>>>> @@ -8,7 +8,8 @@
> >>>>>>>
> >>>>>>>      #include <uapi/asm/hwprobe.h>
> >>>>>>>
> >>>>>>> -#define RISCV_HWPROBE_MAX_KEY 13
> >>>>>>> +#define RISCV_HWPROBE_MAX_KEY 14
> >>>>>>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE      ((1ULL << 59) - 1)
> >>
> >> 59 should not be hardcoded, even with your comment below. Let's
> >> introduce something like RISCV_HWPROBE_EXT_COUNT or similar.
> >>
> >>
> >>>>>>>      static inline bool riscv_hwprobe_key_is_valid(__s64 key)
> >>>>>>>      {
> >>>>>>> diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
> >>>>>>> index aaf6ad970499..a3b92df4dc05 100644
> >>>>>>> --- a/arch/riscv/include/uapi/asm/hwprobe.h
> >>>>>>> +++ b/arch/riscv/include/uapi/asm/hwprobe.h
> >>>>>>> @@ -82,6 +82,7 @@ struct riscv_hwprobe {
> >>>>>>>      #define             RISCV_HWPROBE_EXT_ZAAMO         (1ULL << 56)
> >>>>>>>      #define             RISCV_HWPROBE_EXT_ZALRSC        (1ULL << 57)
> >>>>>>>      #define             RISCV_HWPROBE_EXT_ZABHA         (1ULL << 58)
> >>>>>>> +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
> >>>>>>>      #define RISCV_HWPROBE_KEY_CPUPERF_0 5
> >>>>>>>      #define             RISCV_HWPROBE_MISALIGNED_UNKNOWN        (0 << 0)
> >>>>>>>      #define             RISCV_HWPROBE_MISALIGNED_EMULATED       (1 << 0)
> >>>>>>> @@ -106,6 +107,7 @@ struct riscv_hwprobe {
> >>>>>>>      #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0        11
> >>>>>>>      #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE 12
> >>>>>>>      #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0       13
> >>>>>>> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
> >>>>>>>      /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
> >>>>>>>
> >>>>>>>      /* Flags */
> >>>>>>> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> >>>>>>> index 0b170e18a2be..40e7fa5f85f3 100644
> >>>>>>> --- a/arch/riscv/kernel/sys_hwprobe.c
> >>>>>>> +++ b/arch/riscv/kernel/sys_hwprobe.c
> >>>>>>> @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
> >>>>>>>                  hwprobe_isa_vendor_ext_thead_0(pair, cpus);
> >>>>>>>                  break;
> >>>>>>>
> >>>>>>> +     case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
> >>>>>>> +             pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
> >>
> >> You don't really need to return a mask here, you can simply return
> >> RISCV_HWPROBE_EXT_COUNT and let the userspace deal with the mask.
> >>
> >>
> >>>>>>> +             break;
> >>>>>>> +
> >>>>>>>          /*
> >>>>>>>           * For forward compatibility, unknown keys don't fail the whole
> >>>>>>>           * call, but get their element key set to -1 and value set to 0
> >>>>>>>
> >>>>>>> _______________________________________________
> >>>>>>> linux-riscv mailing list
> >>>>>>> linux-riscv@lists.infradead.org
> >>>>>>> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v3] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-13 18:05 ` [PATCH v2] " offtkp
  2025-08-14  9:37   ` Alexandre Ghiti
@ 2025-08-14 22:13   ` offtkp
  2025-08-25 17:02     ` [PATCH v3 RESEND] " offtkp
  1 sibling, 1 reply; 16+ messages in thread
From: offtkp @ 2025-08-14 22:13 UTC (permalink / raw)
  To: linux-riscv; +Cc: paul.walmsley, palmer, aou, alex, conor, offtkp

When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
bit in the resulting bitmask means the extension is not available or the
kernel is not recent enough to support the bit. Currently, there's no
way to differentiate between the two.

This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
which returns a bitmask of all the queryable extensions supported by the
kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
fallback extension detection method when the bit they want to query is
not available in the kernel they are running on.

Signed-off-by: offtkp <parisoplop@gmail.com>
---
Changes in v3:
- remove the 59 magic number and create the mask as a define

Conversation from v2 to show motivation for this patch as a whole:

> And do you have a real usecase in
> mind? I mean which project would benefit from this?
Yes, I want this feature for an x86-on-RISC-V userspace emulator
called felix86. We do runtime extension detection for our JIT.
Currently, for any extension that defines instructions we use the SIGILL
method previously described, because there's no way to tell with just
a hwprobe call whether a 0 bit means extension not present or kernel
too old. But we can't do this for all extensions, some don't define
instructions.

The end goal would be being able to detect an extension using hwprobe,
and if it's not detectable, notifying the user that we can't detect it and
they can mark it as enabled in the emulator's config file.



 Documentation/arch/riscv/hwprobe.rst  |  5 ++++-
 arch/riscv/include/asm/hwprobe.h      | 29 ++++++++++++++++++++++++++-
 arch/riscv/include/uapi/asm/hwprobe.h |  2 ++
 arch/riscv/kernel/sys_hwprobe.c       |  4 ++++
 4 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
index 2aa9be272d5d..6d77def0a46e 100644
--- a/Documentation/arch/riscv/hwprobe.rst
+++ b/Documentation/arch/riscv/hwprobe.rst
@@ -360,4 +360,7 @@ The following keys are defined:
 
     * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
         vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
-	Instruction Extensions Specification.
\ No newline at end of file
+	Instruction Extensions Specification.
+
+* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
+  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
\ No newline at end of file
diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
index 7fe0a379474a..a06eeec11e2c 100644
--- a/arch/riscv/include/asm/hwprobe.h
+++ b/arch/riscv/include/asm/hwprobe.h
@@ -8,7 +8,34 @@
 
 #include <uapi/asm/hwprobe.h>
 
-#define RISCV_HWPROBE_MAX_KEY 13
+#define RISCV_HWPROBE_MAX_KEY 14
+#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE	(RISCV_HWPROBE_IMA_FD | \
+	RISCV_HWPROBE_IMA_C | RISCV_HWPROBE_IMA_V | RISCV_HWPROBE_EXT_ZBA | \
+	RISCV_HWPROBE_EXT_ZBB | RISCV_HWPROBE_EXT_ZBS | RISCV_HWPROBE_EXT_ZICBOZ | \
+	RISCV_HWPROBE_EXT_ZBC | RISCV_HWPROBE_EXT_ZBKB | RISCV_HWPROBE_EXT_ZBKC | \
+	RISCV_HWPROBE_EXT_ZBKX | RISCV_HWPROBE_EXT_ZKND | RISCV_HWPROBE_EXT_ZKNE | \
+	RISCV_HWPROBE_EXT_ZKNH | RISCV_HWPROBE_EXT_ZKSED | \
+	RISCV_HWPROBE_EXT_ZKSH | RISCV_HWPROBE_EXT_ZKT | RISCV_HWPROBE_EXT_ZVBB | \
+	RISCV_HWPROBE_EXT_ZVBC | RISCV_HWPROBE_EXT_ZVKB | RISCV_HWPROBE_EXT_ZVKG | \
+	RISCV_HWPROBE_EXT_ZVKNED | RISCV_HWPROBE_EXT_ZVKNHA | \
+	RISCV_HWPROBE_EXT_ZVKNHB | RISCV_HWPROBE_EXT_ZVKSED | \
+	RISCV_HWPROBE_EXT_ZVKSH | RISCV_HWPROBE_EXT_ZVKT | \
+	RISCV_HWPROBE_EXT_ZFH | RISCV_HWPROBE_EXT_ZFHMIN | \
+	RISCV_HWPROBE_EXT_ZIHINTNTL | RISCV_HWPROBE_EXT_ZVFH | \
+	RISCV_HWPROBE_EXT_ZVFHMIN | RISCV_HWPROBE_EXT_ZFA | \
+	RISCV_HWPROBE_EXT_ZTSO | RISCV_HWPROBE_EXT_ZACAS | \
+	RISCV_HWPROBE_EXT_ZICOND | RISCV_HWPROBE_EXT_ZIHINTPAUSE | \
+	RISCV_HWPROBE_EXT_ZVE32X | RISCV_HWPROBE_EXT_ZVE32F | \
+	RISCV_HWPROBE_EXT_ZVE64X | RISCV_HWPROBE_EXT_ZVE64F | \
+	RISCV_HWPROBE_EXT_ZVE64D | RISCV_HWPROBE_EXT_ZIMOP | \
+	RISCV_HWPROBE_EXT_ZCA | RISCV_HWPROBE_EXT_ZCB | RISCV_HWPROBE_EXT_ZCD | \
+	RISCV_HWPROBE_EXT_ZCF | RISCV_HWPROBE_EXT_ZCMOP | \
+	RISCV_HWPROBE_EXT_ZAWRS | RISCV_HWPROBE_EXT_SUPM | \
+	RISCV_HWPROBE_EXT_ZICNTR | RISCV_HWPROBE_EXT_ZIHPM | \
+	RISCV_HWPROBE_EXT_ZFBFMIN | RISCV_HWPROBE_EXT_ZVFBFMIN | \
+	RISCV_HWPROBE_EXT_ZVFBFWMA | RISCV_HWPROBE_EXT_ZICBOM | \
+	RISCV_HWPROBE_EXT_ZAAMO | RISCV_HWPROBE_EXT_ZALRSC | \
+	RISCV_HWPROBE_EXT_ZABHA)
 
 static inline bool riscv_hwprobe_key_is_valid(__s64 key)
 {
diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
index aaf6ad970499..a3b92df4dc05 100644
--- a/arch/riscv/include/uapi/asm/hwprobe.h
+++ b/arch/riscv/include/uapi/asm/hwprobe.h
@@ -82,6 +82,7 @@ struct riscv_hwprobe {
 #define		RISCV_HWPROBE_EXT_ZAAMO		(1ULL << 56)
 #define		RISCV_HWPROBE_EXT_ZALRSC	(1ULL << 57)
 #define		RISCV_HWPROBE_EXT_ZABHA		(1ULL << 58)
+/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
 #define RISCV_HWPROBE_KEY_CPUPERF_0	5
 #define		RISCV_HWPROBE_MISALIGNED_UNKNOWN	(0 << 0)
 #define		RISCV_HWPROBE_MISALIGNED_EMULATED	(1 << 0)
@@ -106,6 +107,7 @@ struct riscv_hwprobe {
 #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0	11
 #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE	12
 #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0	13
+#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
 /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
 
 /* Flags */
diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
index 0b170e18a2be..40e7fa5f85f3 100644
--- a/arch/riscv/kernel/sys_hwprobe.c
+++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
 		hwprobe_isa_vendor_ext_thead_0(pair, cpus);
 		break;
 
+	case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
+		pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
+		break;
+
 	/*
 	 * For forward compatibility, unknown keys don't fail the whole
 	 * call, but get their element key set to -1 and value set to 0

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-13 16:33 [PATCH] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits Paris Oplopoios
  2025-08-13 18:05 ` [PATCH v2] " offtkp
@ 2025-08-19 19:37 ` Andrew Jones
  2025-08-19 19:56   ` Paris Oplopoios
  1 sibling, 1 reply; 16+ messages in thread
From: Andrew Jones @ 2025-08-19 19:37 UTC (permalink / raw)
  To: Paris Oplopoios; +Cc: linux-riscv, paul.walmsley, palmer, aou, alex

On Wed, Aug 13, 2025 at 07:33:48PM +0300, Paris Oplopoios wrote:
> When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
> bit in the resulting bitmask means extension is not available or the kernel is
> not recent enough to support the bit. Currently, there's no way to
> differentiate between the two.
> 
> This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL, which
> returns a bitmask of all queryable supported by the kernel
> in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a fallback
> extension detection method when the bit they want to query is not available
> in the kernel they are running on.
> 
> Example usage:
> 
>     struct riscv_hwprobe req = { RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL, 0 };
>     int ret = syscall(__NR_riscv_hwprobe, &req, 1, 0, NULL, 0);
>     if (ret == 0) {
>         uint64_t bitmask = req.value;
>         if (bitmask & RISCV_HWPROBE_EXT_ZABHA) {
>             // Check for existence of Zabha extension using riscv_hwprobe
>         } else {
>             // Fallback to checking if an instruction in the Zabha
>             // extension results in an illegal instruction exception

The new key allows us to know when the kernel is aware of an extension
or not. When the kernel is aware of the extension, then a hwprobe of
the extension's key generates a result that unambiguously states whether
or not the extension is available. However, when the kernel is unaware of
the extension, then we still know nothing about its availability. IOW,
how does the new key help? The fact that this example use still has this
fallback path in it implies it doesn't.

What I think we need is a way to better automatically expose Z-extensions
which are in the DT/ACPI. I like the idea of generating a sysfs node for
each extension string. Those nodes could then have properties such as the
kernel's awareness of it, etc. I proposed something in the past like that,
but it was considered too Linux-specific.

Thanks,
drew

>         }
>     }
> 
> Signed-off-by: Paris Oplopoios <parisoplop@gmail.com>
> 
> ---
> 
> diff --git a/Documentation/arch/riscv/hwprobe.rst
> b/Documentation/arch/riscv/hwprobe.rst
> index 2aa9be272d5d..6d77def0a46e 100644
> --- a/Documentation/arch/riscv/hwprobe.rst
> +++ b/Documentation/arch/riscv/hwprobe.rst
> @@ -360,4 +360,7 @@ The following keys are defined:
> 
>      * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
>          vendor extension is supported in version 1.0 of Matrix
> Multiply Accumulate
> -    Instruction Extensions Specification.
> \ No newline at end of file
> +    Instruction Extensions Specification.
> +
> +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing
> the extensions
> +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
> \ No newline at end of file
> diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
> index 7fe0a379474a..501d49b7a02a 100644
> --- a/arch/riscv/include/asm/hwprobe.h
> +++ b/arch/riscv/include/asm/hwprobe.h
> @@ -8,7 +8,8 @@
> 
>  #include <uapi/asm/hwprobe.h>
> 
> -#define RISCV_HWPROBE_MAX_KEY 13
> +#define RISCV_HWPROBE_MAX_KEY 14
> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE    ((1ULL << 59) - 1)
> 
>  static inline bool riscv_hwprobe_key_is_valid(__s64 key)
>  {
> diff --git a/arch/riscv/include/uapi/asm/hwprobe.h
> b/arch/riscv/include/uapi/asm/hwprobe.h
> index aaf6ad970499..a3b92df4dc05 100644
> --- a/arch/riscv/include/uapi/asm/hwprobe.h
> +++ b/arch/riscv/include/uapi/asm/hwprobe.h
> @@ -82,6 +82,7 @@ struct riscv_hwprobe {
>  #define        RISCV_HWPROBE_EXT_ZAAMO        (1ULL << 56)
>  #define        RISCV_HWPROBE_EXT_ZALRSC    (1ULL << 57)
>  #define        RISCV_HWPROBE_EXT_ZABHA        (1ULL << 58)
> +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
>  #define RISCV_HWPROBE_KEY_CPUPERF_0    5
>  #define        RISCV_HWPROBE_MISALIGNED_UNKNOWN    (0 << 0)
>  #define        RISCV_HWPROBE_MISALIGNED_EMULATED    (1 << 0)
> @@ -106,6 +107,7 @@ struct riscv_hwprobe {
>  #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0    11
>  #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE    12
>  #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0    13
> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
>  /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
> 
>  /* Flags */
> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> index 0b170e18a2be..40e7fa5f85f3 100644
> --- a/arch/riscv/kernel/sys_hwprobe.c
> +++ b/arch/riscv/kernel/sys_hwprobe.c
> @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
>          hwprobe_isa_vendor_ext_thead_0(pair, cpus);
>          break;
> 
> +    case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
> +        pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
> +        break;
> +
>      /*
>       * For forward compatibility, unknown keys don't fail the whole
>       * call, but get their element key set to -1 and value set to 0
> 
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-19 19:37 ` [PATCH] " Andrew Jones
@ 2025-08-19 19:56   ` Paris Oplopoios
  0 siblings, 0 replies; 16+ messages in thread
From: Paris Oplopoios @ 2025-08-19 19:56 UTC (permalink / raw)
  To: Andrew Jones; +Cc: linux-riscv, paul.walmsley, palmer, aou, alex

> When the kernel is aware of the extension

The way I understand it, there's currently no way for a program to
know whether or not the kernel is aware of an extension. When the
syscall returns a cleared bit for some key, you are left to wonder
whether this means the kernel is unaware or if the extension is
unavailable. A value of 1 means that the extension is available, but a
value of 0, unless it has any higher 1 bits, is ambiguous.

The new key helps because we get to decide what to do in the case of
no kernel availability. We can decide to print a message or do the
fallback or something else. Point is, right now we can't know whether
the extension is available in the kernel. For our extension detection
we never use the riscv_hwprobe API for this reason and always do a
SIGILL handler based detection when possible.

> What I think we need is a way to better automatically expose Z-extensions
> which are in the DT/ACPI. I like the idea of generating a sysfs node for
> each extension string. Those nodes could then have properties such as the
> kernel's awareness of it, etc. I proposed something in the past like that,
> but it was considered too Linux-specific.

That would be good too.

On Tue, 19 Aug 2025 at 22:37, Andrew Jones <ajones@ventanamicro.com> wrote:
>
> On Wed, Aug 13, 2025 at 07:33:48PM +0300, Paris Oplopoios wrote:
> > When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
> > bit in the resulting bitmask means extension is not available or the kernel is
> > not recent enough to support the bit. Currently, there's no way to
> > differentiate between the two.
> >
> > This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL, which
> > returns a bitmask of all queryable supported by the kernel
> > in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a fallback
> > extension detection method when the bit they want to query is not available
> > in the kernel they are running on.
> >
> > Example usage:
> >
> >     struct riscv_hwprobe req = { RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL, 0 };
> >     int ret = syscall(__NR_riscv_hwprobe, &req, 1, 0, NULL, 0);
> >     if (ret == 0) {
> >         uint64_t bitmask = req.value;
> >         if (bitmask & RISCV_HWPROBE_EXT_ZABHA) {
> >             // Check for existence of Zabha extension using riscv_hwprobe
> >         } else {
> >             // Fallback to checking if an instruction in the Zabha
> >             // extension results in an illegal instruction exception
>
> The new key allows us to know when the kernel is aware of an extension
> or not. When the kernel is aware of the extension, then a hwprobe of
> the extension's key generates a result that unambiguously states whether
> or not the extension is available. However, when the kernel is unaware of
> the extension, then we still know nothing about its availability. IOW,
> how does the new key help? The fact that this example use still has this
> fallback path in it implies it doesn't.
>
> What I think we need is a way to better automatically expose Z-extensions
> which are in the DT/ACPI. I like the idea of generating a sysfs node for
> each extension string. Those nodes could then have properties such as the
> kernel's awareness of it, etc. I proposed something in the past like that,
> but it was considered too Linux-specific.
>
> Thanks,
> drew
>
> >         }
> >     }
> >
> > Signed-off-by: Paris Oplopoios <parisoplop@gmail.com>
> >
> > ---
> >
> > diff --git a/Documentation/arch/riscv/hwprobe.rst
> > b/Documentation/arch/riscv/hwprobe.rst
> > index 2aa9be272d5d..6d77def0a46e 100644
> > --- a/Documentation/arch/riscv/hwprobe.rst
> > +++ b/Documentation/arch/riscv/hwprobe.rst
> > @@ -360,4 +360,7 @@ The following keys are defined:
> >
> >      * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
> >          vendor extension is supported in version 1.0 of Matrix
> > Multiply Accumulate
> > -    Instruction Extensions Specification.
> > \ No newline at end of file
> > +    Instruction Extensions Specification.
> > +
> > +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing
> > the extensions
> > +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
> > \ No newline at end of file
> > diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
> > index 7fe0a379474a..501d49b7a02a 100644
> > --- a/arch/riscv/include/asm/hwprobe.h
> > +++ b/arch/riscv/include/asm/hwprobe.h
> > @@ -8,7 +8,8 @@
> >
> >  #include <uapi/asm/hwprobe.h>
> >
> > -#define RISCV_HWPROBE_MAX_KEY 13
> > +#define RISCV_HWPROBE_MAX_KEY 14
> > +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE    ((1ULL << 59) - 1)
> >
> >  static inline bool riscv_hwprobe_key_is_valid(__s64 key)
> >  {
> > diff --git a/arch/riscv/include/uapi/asm/hwprobe.h
> > b/arch/riscv/include/uapi/asm/hwprobe.h
> > index aaf6ad970499..a3b92df4dc05 100644
> > --- a/arch/riscv/include/uapi/asm/hwprobe.h
> > +++ b/arch/riscv/include/uapi/asm/hwprobe.h
> > @@ -82,6 +82,7 @@ struct riscv_hwprobe {
> >  #define        RISCV_HWPROBE_EXT_ZAAMO        (1ULL << 56)
> >  #define        RISCV_HWPROBE_EXT_ZALRSC    (1ULL << 57)
> >  #define        RISCV_HWPROBE_EXT_ZABHA        (1ULL << 58)
> > +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
> >  #define RISCV_HWPROBE_KEY_CPUPERF_0    5
> >  #define        RISCV_HWPROBE_MISALIGNED_UNKNOWN    (0 << 0)
> >  #define        RISCV_HWPROBE_MISALIGNED_EMULATED    (1 << 0)
> > @@ -106,6 +107,7 @@ struct riscv_hwprobe {
> >  #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0    11
> >  #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE    12
> >  #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0    13
> > +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
> >  /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
> >
> >  /* Flags */
> > diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> > index 0b170e18a2be..40e7fa5f85f3 100644
> > --- a/arch/riscv/kernel/sys_hwprobe.c
> > +++ b/arch/riscv/kernel/sys_hwprobe.c
> > @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
> >          hwprobe_isa_vendor_ext_thead_0(pair, cpus);
> >          break;
> >
> > +    case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
> > +        pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
> > +        break;
> > +
> >      /*
> >       * For forward compatibility, unknown keys don't fail the whole
> >       * call, but get their element key set to -1 and value set to 0
> >
> > _______________________________________________
> > linux-riscv mailing list
> > linux-riscv@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v3 RESEND] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-14 22:13   ` [PATCH v3] " offtkp
@ 2025-08-25 17:02     ` offtkp
  2025-08-25 22:00       ` Andrew Jones
  0 siblings, 1 reply; 16+ messages in thread
From: offtkp @ 2025-08-25 17:02 UTC (permalink / raw)
  To: linux-riscv; +Cc: paul.walmsley, palmer, aou, alex, conor, offtkp

When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
bit in the resulting bitmask means the extension is not available or the
kernel is not recent enough to support the bit. Currently, there's no
way to differentiate between the two.

This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
which returns a bitmask of all the queryable extensions supported by the
kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
fallback extension detection method when the bit they want to query is
not available in the kernel they are running on.

Signed-off-by: offtkp <parisoplop@gmail.com>
---
Changes in v3:
- remove the 59 magic number and create the mask as a define

Conversation from v2 to show motivation for this patch as a whole:

> And do you have a real usecase in
> mind? I mean which project would benefit from this?
Yes, I want this feature for an x86-on-RISC-V userspace emulator
called felix86. We do runtime extension detection for our JIT.
Currently, for any extension that defines instructions we use the SIGILL
method previously described, because there's no way to tell with just
a hwprobe call whether a 0 bit means extension not present or kernel
too old. But we can't do this for all extensions, some don't define
instructions.

The end goal would be being able to detect an extension using hwprobe,
and if it's not detectable, notifying the user that we can't detect it and
they can mark it as enabled in the emulator's config file.



 Documentation/arch/riscv/hwprobe.rst  |  5 ++++-
 arch/riscv/include/asm/hwprobe.h      | 29 ++++++++++++++++++++++++++-
 arch/riscv/include/uapi/asm/hwprobe.h |  2 ++
 arch/riscv/kernel/sys_hwprobe.c       |  4 ++++
 4 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
index 2aa9be272d5d..6d77def0a46e 100644
--- a/Documentation/arch/riscv/hwprobe.rst
+++ b/Documentation/arch/riscv/hwprobe.rst
@@ -360,4 +360,7 @@ The following keys are defined:
 
     * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
         vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
-	Instruction Extensions Specification.
\ No newline at end of file
+	Instruction Extensions Specification.
+
+* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
+  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
\ No newline at end of file
diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
index 7fe0a379474a..a06eeec11e2c 100644
--- a/arch/riscv/include/asm/hwprobe.h
+++ b/arch/riscv/include/asm/hwprobe.h
@@ -8,7 +8,34 @@
 
 #include <uapi/asm/hwprobe.h>
 
-#define RISCV_HWPROBE_MAX_KEY 13
+#define RISCV_HWPROBE_MAX_KEY 14
+#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE	(RISCV_HWPROBE_IMA_FD | \
+	RISCV_HWPROBE_IMA_C | RISCV_HWPROBE_IMA_V | RISCV_HWPROBE_EXT_ZBA | \
+	RISCV_HWPROBE_EXT_ZBB | RISCV_HWPROBE_EXT_ZBS | RISCV_HWPROBE_EXT_ZICBOZ | \
+	RISCV_HWPROBE_EXT_ZBC | RISCV_HWPROBE_EXT_ZBKB | RISCV_HWPROBE_EXT_ZBKC | \
+	RISCV_HWPROBE_EXT_ZBKX | RISCV_HWPROBE_EXT_ZKND | RISCV_HWPROBE_EXT_ZKNE | \
+	RISCV_HWPROBE_EXT_ZKNH | RISCV_HWPROBE_EXT_ZKSED | \
+	RISCV_HWPROBE_EXT_ZKSH | RISCV_HWPROBE_EXT_ZKT | RISCV_HWPROBE_EXT_ZVBB | \
+	RISCV_HWPROBE_EXT_ZVBC | RISCV_HWPROBE_EXT_ZVKB | RISCV_HWPROBE_EXT_ZVKG | \
+	RISCV_HWPROBE_EXT_ZVKNED | RISCV_HWPROBE_EXT_ZVKNHA | \
+	RISCV_HWPROBE_EXT_ZVKNHB | RISCV_HWPROBE_EXT_ZVKSED | \
+	RISCV_HWPROBE_EXT_ZVKSH | RISCV_HWPROBE_EXT_ZVKT | \
+	RISCV_HWPROBE_EXT_ZFH | RISCV_HWPROBE_EXT_ZFHMIN | \
+	RISCV_HWPROBE_EXT_ZIHINTNTL | RISCV_HWPROBE_EXT_ZVFH | \
+	RISCV_HWPROBE_EXT_ZVFHMIN | RISCV_HWPROBE_EXT_ZFA | \
+	RISCV_HWPROBE_EXT_ZTSO | RISCV_HWPROBE_EXT_ZACAS | \
+	RISCV_HWPROBE_EXT_ZICOND | RISCV_HWPROBE_EXT_ZIHINTPAUSE | \
+	RISCV_HWPROBE_EXT_ZVE32X | RISCV_HWPROBE_EXT_ZVE32F | \
+	RISCV_HWPROBE_EXT_ZVE64X | RISCV_HWPROBE_EXT_ZVE64F | \
+	RISCV_HWPROBE_EXT_ZVE64D | RISCV_HWPROBE_EXT_ZIMOP | \
+	RISCV_HWPROBE_EXT_ZCA | RISCV_HWPROBE_EXT_ZCB | RISCV_HWPROBE_EXT_ZCD | \
+	RISCV_HWPROBE_EXT_ZCF | RISCV_HWPROBE_EXT_ZCMOP | \
+	RISCV_HWPROBE_EXT_ZAWRS | RISCV_HWPROBE_EXT_SUPM | \
+	RISCV_HWPROBE_EXT_ZICNTR | RISCV_HWPROBE_EXT_ZIHPM | \
+	RISCV_HWPROBE_EXT_ZFBFMIN | RISCV_HWPROBE_EXT_ZVFBFMIN | \
+	RISCV_HWPROBE_EXT_ZVFBFWMA | RISCV_HWPROBE_EXT_ZICBOM | \
+	RISCV_HWPROBE_EXT_ZAAMO | RISCV_HWPROBE_EXT_ZALRSC | \
+	RISCV_HWPROBE_EXT_ZABHA)
 
 static inline bool riscv_hwprobe_key_is_valid(__s64 key)
 {
diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
index aaf6ad970499..a3b92df4dc05 100644
--- a/arch/riscv/include/uapi/asm/hwprobe.h
+++ b/arch/riscv/include/uapi/asm/hwprobe.h
@@ -82,6 +82,7 @@ struct riscv_hwprobe {
 #define		RISCV_HWPROBE_EXT_ZAAMO		(1ULL << 56)
 #define		RISCV_HWPROBE_EXT_ZALRSC	(1ULL << 57)
 #define		RISCV_HWPROBE_EXT_ZABHA		(1ULL << 58)
+/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
 #define RISCV_HWPROBE_KEY_CPUPERF_0	5
 #define		RISCV_HWPROBE_MISALIGNED_UNKNOWN	(0 << 0)
 #define		RISCV_HWPROBE_MISALIGNED_EMULATED	(1 << 0)
@@ -106,6 +107,7 @@ struct riscv_hwprobe {
 #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0	11
 #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE	12
 #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0	13
+#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
 /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
 
 /* Flags */
diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
index 0b170e18a2be..40e7fa5f85f3 100644
--- a/arch/riscv/kernel/sys_hwprobe.c
+++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
 		hwprobe_isa_vendor_ext_thead_0(pair, cpus);
 		break;
 
+	case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
+		pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
+		break;
+
 	/*
 	 * For forward compatibility, unknown keys don't fail the whole
 	 * call, but get their element key set to -1 and value set to 0

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 RESEND] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-25 17:02     ` [PATCH v3 RESEND] " offtkp
@ 2025-08-25 22:00       ` Andrew Jones
  2025-08-25 23:12         ` Paris Oplopoios
  0 siblings, 1 reply; 16+ messages in thread
From: Andrew Jones @ 2025-08-25 22:00 UTC (permalink / raw)
  To: offtkp; +Cc: linux-riscv, paul.walmsley, palmer, aou, alex, conor

On Mon, Aug 25, 2025 at 08:02:21PM +0300, offtkp wrote:
> When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
> bit in the resulting bitmask means the extension is not available or the
> kernel is not recent enough to support the bit. Currently, there's no
> way to differentiate between the two.
> 
> This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
> which returns a bitmask of all the queryable extensions supported by the
> kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
> fallback extension detection method when the bit they want to query is
> not available in the kernel they are running on.
> 
> Signed-off-by: offtkp <parisoplop@gmail.com>
> ---
> Changes in v3:
> - remove the 59 magic number and create the mask as a define
> 
> Conversation from v2 to show motivation for this patch as a whole:
> 
> > And do you have a real usecase in
> > mind? I mean which project would benefit from this?
> Yes, I want this feature for an x86-on-RISC-V userspace emulator
> called felix86. We do runtime extension detection for our JIT.
> Currently, for any extension that defines instructions we use the SIGILL
> method previously described, because there's no way to tell with just
> a hwprobe call whether a 0 bit means extension not present or kernel
> too old. But we can't do this for all extensions, some don't define
> instructions.
> 
> The end goal would be being able to detect an extension using hwprobe,
> and if it's not detectable, notifying the user that we can't detect it and
> they can mark it as enabled in the emulator's config file.

As I pointed out on v2, I don't think this patch helps. When the kernel
is unaware of the extension, then we still know nothing about its
availability. This is only helpful when the kernel is aware of an
extension, but, in those cases, the current hwprobe can be trusted, so
we don't need this.

The problem is there's no good way to detect extensions that the kernel
is unaware of, which means the kernel needs to blindly expose what's in
the DT/ACPI somehow.

Thanks,
drew

> 
> 
> 
>  Documentation/arch/riscv/hwprobe.rst  |  5 ++++-
>  arch/riscv/include/asm/hwprobe.h      | 29 ++++++++++++++++++++++++++-
>  arch/riscv/include/uapi/asm/hwprobe.h |  2 ++
>  arch/riscv/kernel/sys_hwprobe.c       |  4 ++++
>  4 files changed, 38 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
> index 2aa9be272d5d..6d77def0a46e 100644
> --- a/Documentation/arch/riscv/hwprobe.rst
> +++ b/Documentation/arch/riscv/hwprobe.rst
> @@ -360,4 +360,7 @@ The following keys are defined:
>  
>      * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
>          vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
> -	Instruction Extensions Specification.
> \ No newline at end of file
> +	Instruction Extensions Specification.
> +
> +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
> +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
> \ No newline at end of file
> diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
> index 7fe0a379474a..a06eeec11e2c 100644
> --- a/arch/riscv/include/asm/hwprobe.h
> +++ b/arch/riscv/include/asm/hwprobe.h
> @@ -8,7 +8,34 @@
>  
>  #include <uapi/asm/hwprobe.h>
>  
> -#define RISCV_HWPROBE_MAX_KEY 13
> +#define RISCV_HWPROBE_MAX_KEY 14
> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE	(RISCV_HWPROBE_IMA_FD | \
> +	RISCV_HWPROBE_IMA_C | RISCV_HWPROBE_IMA_V | RISCV_HWPROBE_EXT_ZBA | \
> +	RISCV_HWPROBE_EXT_ZBB | RISCV_HWPROBE_EXT_ZBS | RISCV_HWPROBE_EXT_ZICBOZ | \
> +	RISCV_HWPROBE_EXT_ZBC | RISCV_HWPROBE_EXT_ZBKB | RISCV_HWPROBE_EXT_ZBKC | \
> +	RISCV_HWPROBE_EXT_ZBKX | RISCV_HWPROBE_EXT_ZKND | RISCV_HWPROBE_EXT_ZKNE | \
> +	RISCV_HWPROBE_EXT_ZKNH | RISCV_HWPROBE_EXT_ZKSED | \
> +	RISCV_HWPROBE_EXT_ZKSH | RISCV_HWPROBE_EXT_ZKT | RISCV_HWPROBE_EXT_ZVBB | \
> +	RISCV_HWPROBE_EXT_ZVBC | RISCV_HWPROBE_EXT_ZVKB | RISCV_HWPROBE_EXT_ZVKG | \
> +	RISCV_HWPROBE_EXT_ZVKNED | RISCV_HWPROBE_EXT_ZVKNHA | \
> +	RISCV_HWPROBE_EXT_ZVKNHB | RISCV_HWPROBE_EXT_ZVKSED | \
> +	RISCV_HWPROBE_EXT_ZVKSH | RISCV_HWPROBE_EXT_ZVKT | \
> +	RISCV_HWPROBE_EXT_ZFH | RISCV_HWPROBE_EXT_ZFHMIN | \
> +	RISCV_HWPROBE_EXT_ZIHINTNTL | RISCV_HWPROBE_EXT_ZVFH | \
> +	RISCV_HWPROBE_EXT_ZVFHMIN | RISCV_HWPROBE_EXT_ZFA | \
> +	RISCV_HWPROBE_EXT_ZTSO | RISCV_HWPROBE_EXT_ZACAS | \
> +	RISCV_HWPROBE_EXT_ZICOND | RISCV_HWPROBE_EXT_ZIHINTPAUSE | \
> +	RISCV_HWPROBE_EXT_ZVE32X | RISCV_HWPROBE_EXT_ZVE32F | \
> +	RISCV_HWPROBE_EXT_ZVE64X | RISCV_HWPROBE_EXT_ZVE64F | \
> +	RISCV_HWPROBE_EXT_ZVE64D | RISCV_HWPROBE_EXT_ZIMOP | \
> +	RISCV_HWPROBE_EXT_ZCA | RISCV_HWPROBE_EXT_ZCB | RISCV_HWPROBE_EXT_ZCD | \
> +	RISCV_HWPROBE_EXT_ZCF | RISCV_HWPROBE_EXT_ZCMOP | \
> +	RISCV_HWPROBE_EXT_ZAWRS | RISCV_HWPROBE_EXT_SUPM | \
> +	RISCV_HWPROBE_EXT_ZICNTR | RISCV_HWPROBE_EXT_ZIHPM | \
> +	RISCV_HWPROBE_EXT_ZFBFMIN | RISCV_HWPROBE_EXT_ZVFBFMIN | \
> +	RISCV_HWPROBE_EXT_ZVFBFWMA | RISCV_HWPROBE_EXT_ZICBOM | \
> +	RISCV_HWPROBE_EXT_ZAAMO | RISCV_HWPROBE_EXT_ZALRSC | \
> +	RISCV_HWPROBE_EXT_ZABHA)
>  
>  static inline bool riscv_hwprobe_key_is_valid(__s64 key)
>  {
> diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
> index aaf6ad970499..a3b92df4dc05 100644
> --- a/arch/riscv/include/uapi/asm/hwprobe.h
> +++ b/arch/riscv/include/uapi/asm/hwprobe.h
> @@ -82,6 +82,7 @@ struct riscv_hwprobe {
>  #define		RISCV_HWPROBE_EXT_ZAAMO		(1ULL << 56)
>  #define		RISCV_HWPROBE_EXT_ZALRSC	(1ULL << 57)
>  #define		RISCV_HWPROBE_EXT_ZABHA		(1ULL << 58)
> +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
>  #define RISCV_HWPROBE_KEY_CPUPERF_0	5
>  #define		RISCV_HWPROBE_MISALIGNED_UNKNOWN	(0 << 0)
>  #define		RISCV_HWPROBE_MISALIGNED_EMULATED	(1 << 0)
> @@ -106,6 +107,7 @@ struct riscv_hwprobe {
>  #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0	11
>  #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE	12
>  #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0	13
> +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
>  /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
>  
>  /* Flags */
> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> index 0b170e18a2be..40e7fa5f85f3 100644
> --- a/arch/riscv/kernel/sys_hwprobe.c
> +++ b/arch/riscv/kernel/sys_hwprobe.c
> @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
>  		hwprobe_isa_vendor_ext_thead_0(pair, cpus);
>  		break;
>  
> +	case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
> +		pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
> +		break;
> +
>  	/*
>  	 * For forward compatibility, unknown keys don't fail the whole
>  	 * call, but get their element key set to -1 and value set to 0
> 
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 RESEND] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits
  2025-08-25 22:00       ` Andrew Jones
@ 2025-08-25 23:12         ` Paris Oplopoios
  0 siblings, 0 replies; 16+ messages in thread
From: Paris Oplopoios @ 2025-08-25 23:12 UTC (permalink / raw)
  To: Andrew Jones; +Cc: linux-riscv, paul.walmsley, palmer, aou, alex, conor

I disagree. This sort of practice is used in other places in the
kernel, such as statx and stx_attributes with stx_attributes_mask.
Knowing that the kernel is unaware of the extension is important for
programs, regardless of if we can learn about its availability or not.
Another example is openat2. If you pass a flag in how.resolve that the
kernel doesn't support, an error is returned.

Whether or not we need a new API to detect extensions, hwprobe is not
reliable in its current state if we can't tell which bits the kernel
knows about at runtime.

On Tue, 26 Aug 2025 at 01:00, Andrew Jones <ajones@ventanamicro.com> wrote:
>
> On Mon, Aug 25, 2025 at 08:02:21PM +0300, offtkp wrote:
> > When probing for extensions using RISCV_HWPROBE_KEY_IMA_EXT_0, a missing
> > bit in the resulting bitmask means the extension is not available or the
> > kernel is not recent enough to support the bit. Currently, there's no
> > way to differentiate between the two.
> >
> > This adds a new riscv_hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL,
> > which returns a bitmask of all the queryable extensions supported by the
> > kernel in RISCV_HWPROBE_KEY_IMA_EXT_0. This can allow programs to use a
> > fallback extension detection method when the bit they want to query is
> > not available in the kernel they are running on.
> >
> > Signed-off-by: offtkp <parisoplop@gmail.com>
> > ---
> > Changes in v3:
> > - remove the 59 magic number and create the mask as a define
> >
> > Conversation from v2 to show motivation for this patch as a whole:
> >
> > > And do you have a real usecase in
> > > mind? I mean which project would benefit from this?
> > Yes, I want this feature for an x86-on-RISC-V userspace emulator
> > called felix86. We do runtime extension detection for our JIT.
> > Currently, for any extension that defines instructions we use the SIGILL
> > method previously described, because there's no way to tell with just
> > a hwprobe call whether a 0 bit means extension not present or kernel
> > too old. But we can't do this for all extensions, some don't define
> > instructions.
> >
> > The end goal would be being able to detect an extension using hwprobe,
> > and if it's not detectable, notifying the user that we can't detect it and
> > they can mark it as enabled in the emulator's config file.
>
> As I pointed out on v2, I don't think this patch helps. When the kernel
> is unaware of the extension, then we still know nothing about its
> availability. This is only helpful when the kernel is aware of an
> extension, but, in those cases, the current hwprobe can be trusted, so
> we don't need this.
>
> The problem is there's no good way to detect extensions that the kernel
> is unaware of, which means the kernel needs to blindly expose what's in
> the DT/ACPI somehow.
>
> Thanks,
> drew
>
> >
> >
> >
> >  Documentation/arch/riscv/hwprobe.rst  |  5 ++++-
> >  arch/riscv/include/asm/hwprobe.h      | 29 ++++++++++++++++++++++++++-
> >  arch/riscv/include/uapi/asm/hwprobe.h |  2 ++
> >  arch/riscv/kernel/sys_hwprobe.c       |  4 ++++
> >  4 files changed, 38 insertions(+), 2 deletions(-)
> >
> > diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
> > index 2aa9be272d5d..6d77def0a46e 100644
> > --- a/Documentation/arch/riscv/hwprobe.rst
> > +++ b/Documentation/arch/riscv/hwprobe.rst
> > @@ -360,4 +360,7 @@ The following keys are defined:
> >
> >      * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
> >          vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
> > -     Instruction Extensions Specification.
> > \ No newline at end of file
> > +     Instruction Extensions Specification.
> > +
> > +* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL`: A bitmask containing the extensions
> > +  that can be probed using the :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0` key.
> > \ No newline at end of file
> > diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
> > index 7fe0a379474a..a06eeec11e2c 100644
> > --- a/arch/riscv/include/asm/hwprobe.h
> > +++ b/arch/riscv/include/asm/hwprobe.h
> > @@ -8,7 +8,34 @@
> >
> >  #include <uapi/asm/hwprobe.h>
> >
> > -#define RISCV_HWPROBE_MAX_KEY 13
> > +#define RISCV_HWPROBE_MAX_KEY 14
> > +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE      (RISCV_HWPROBE_IMA_FD | \
> > +     RISCV_HWPROBE_IMA_C | RISCV_HWPROBE_IMA_V | RISCV_HWPROBE_EXT_ZBA | \
> > +     RISCV_HWPROBE_EXT_ZBB | RISCV_HWPROBE_EXT_ZBS | RISCV_HWPROBE_EXT_ZICBOZ | \
> > +     RISCV_HWPROBE_EXT_ZBC | RISCV_HWPROBE_EXT_ZBKB | RISCV_HWPROBE_EXT_ZBKC | \
> > +     RISCV_HWPROBE_EXT_ZBKX | RISCV_HWPROBE_EXT_ZKND | RISCV_HWPROBE_EXT_ZKNE | \
> > +     RISCV_HWPROBE_EXT_ZKNH | RISCV_HWPROBE_EXT_ZKSED | \
> > +     RISCV_HWPROBE_EXT_ZKSH | RISCV_HWPROBE_EXT_ZKT | RISCV_HWPROBE_EXT_ZVBB | \
> > +     RISCV_HWPROBE_EXT_ZVBC | RISCV_HWPROBE_EXT_ZVKB | RISCV_HWPROBE_EXT_ZVKG | \
> > +     RISCV_HWPROBE_EXT_ZVKNED | RISCV_HWPROBE_EXT_ZVKNHA | \
> > +     RISCV_HWPROBE_EXT_ZVKNHB | RISCV_HWPROBE_EXT_ZVKSED | \
> > +     RISCV_HWPROBE_EXT_ZVKSH | RISCV_HWPROBE_EXT_ZVKT | \
> > +     RISCV_HWPROBE_EXT_ZFH | RISCV_HWPROBE_EXT_ZFHMIN | \
> > +     RISCV_HWPROBE_EXT_ZIHINTNTL | RISCV_HWPROBE_EXT_ZVFH | \
> > +     RISCV_HWPROBE_EXT_ZVFHMIN | RISCV_HWPROBE_EXT_ZFA | \
> > +     RISCV_HWPROBE_EXT_ZTSO | RISCV_HWPROBE_EXT_ZACAS | \
> > +     RISCV_HWPROBE_EXT_ZICOND | RISCV_HWPROBE_EXT_ZIHINTPAUSE | \
> > +     RISCV_HWPROBE_EXT_ZVE32X | RISCV_HWPROBE_EXT_ZVE32F | \
> > +     RISCV_HWPROBE_EXT_ZVE64X | RISCV_HWPROBE_EXT_ZVE64F | \
> > +     RISCV_HWPROBE_EXT_ZVE64D | RISCV_HWPROBE_EXT_ZIMOP | \
> > +     RISCV_HWPROBE_EXT_ZCA | RISCV_HWPROBE_EXT_ZCB | RISCV_HWPROBE_EXT_ZCD | \
> > +     RISCV_HWPROBE_EXT_ZCF | RISCV_HWPROBE_EXT_ZCMOP | \
> > +     RISCV_HWPROBE_EXT_ZAWRS | RISCV_HWPROBE_EXT_SUPM | \
> > +     RISCV_HWPROBE_EXT_ZICNTR | RISCV_HWPROBE_EXT_ZIHPM | \
> > +     RISCV_HWPROBE_EXT_ZFBFMIN | RISCV_HWPROBE_EXT_ZVFBFMIN | \
> > +     RISCV_HWPROBE_EXT_ZVFBFWMA | RISCV_HWPROBE_EXT_ZICBOM | \
> > +     RISCV_HWPROBE_EXT_ZAAMO | RISCV_HWPROBE_EXT_ZALRSC | \
> > +     RISCV_HWPROBE_EXT_ZABHA)
> >
> >  static inline bool riscv_hwprobe_key_is_valid(__s64 key)
> >  {
> > diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
> > index aaf6ad970499..a3b92df4dc05 100644
> > --- a/arch/riscv/include/uapi/asm/hwprobe.h
> > +++ b/arch/riscv/include/uapi/asm/hwprobe.h
> > @@ -82,6 +82,7 @@ struct riscv_hwprobe {
> >  #define              RISCV_HWPROBE_EXT_ZAAMO         (1ULL << 56)
> >  #define              RISCV_HWPROBE_EXT_ZALRSC        (1ULL << 57)
> >  #define              RISCV_HWPROBE_EXT_ZABHA         (1ULL << 58)
> > +/* Change RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE when adding items. */
> >  #define RISCV_HWPROBE_KEY_CPUPERF_0  5
> >  #define              RISCV_HWPROBE_MISALIGNED_UNKNOWN        (0 << 0)
> >  #define              RISCV_HWPROBE_MISALIGNED_EMULATED       (1 << 0)
> > @@ -106,6 +107,7 @@ struct riscv_hwprobe {
> >  #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0 11
> >  #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE  12
> >  #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0        13
> > +#define RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL 14
> >  /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
> >
> >  /* Flags */
> > diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> > index 0b170e18a2be..40e7fa5f85f3 100644
> > --- a/arch/riscv/kernel/sys_hwprobe.c
> > +++ b/arch/riscv/kernel/sys_hwprobe.c
> > @@ -310,6 +310,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
> >               hwprobe_isa_vendor_ext_thead_0(pair, cpus);
> >               break;
> >
> > +     case RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL:
> > +             pair->value = RISCV_HWPROBE_KEY_IMA_EXT_0_AVAIL_VALUE;
> > +             break;
> > +
> >       /*
> >        * For forward compatibility, unknown keys don't fail the whole
> >        * call, but get their element key set to -1 and value set to 0
> >
> > _______________________________________________
> > linux-riscv mailing list
> > linux-riscv@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2025-08-25 23:14 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-13 16:33 [PATCH] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits Paris Oplopoios
2025-08-13 18:05 ` [PATCH v2] " offtkp
2025-08-14  9:37   ` Alexandre Ghiti
2025-08-14 10:32     ` Paris Oplopoios
2025-08-14 11:22       ` Alexandre Ghiti
2025-08-14 11:57         ` Paris Oplopoios
2025-08-14 12:55           ` Alexandre Ghiti
2025-08-14 13:21             ` Paris Oplopoios
2025-08-14 13:56               ` Alexandre Ghiti
2025-08-14 14:20                 ` Paris Oplopoios
2025-08-14 22:13   ` [PATCH v3] " offtkp
2025-08-25 17:02     ` [PATCH v3 RESEND] " offtkp
2025-08-25 22:00       ` Andrew Jones
2025-08-25 23:12         ` Paris Oplopoios
2025-08-19 19:37 ` [PATCH] " Andrew Jones
2025-08-19 19:56   ` Paris Oplopoios

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).