[PATCH v2] riscv: hwprobe: allow querying available RISCV_HWPROBE_KEY_IMA_EXT_0 bits

Paris Oplopoios parisoplop at gmail.com
Thu Aug 14 06:21:18 PDT 2025


> 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 at 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 at 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 at 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 at 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 at lists.infradead.org
> >>>>> http://lists.infradead.org/mailman/listinfo/linux-riscv



More information about the linux-riscv mailing list