master
1/* RISC-V architecture probe interface
2 Copyright (C) 2024-2025 Free Software Foundation, Inc.
3
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library. If not, see
18 <https://www.gnu.org/licenses/>. */
19
20#ifndef _SYS_HWPROBE_H
21#define _SYS_HWPROBE_H 1
22
23#include <features.h>
24#include <sched.h>
25#include <stddef.h>
26#include <errno.h>
27#ifdef __has_include
28# if __has_include (<asm/hwprobe.h>)
29# include <asm/hwprobe.h>
30# endif
31#endif
32
33/* Define a (probably stale) version of the interface if the Linux headers
34 aren't present. */
35#ifndef RISCV_HWPROBE_KEY_MVENDORID
36struct riscv_hwprobe {
37 signed long long int key;
38 unsigned long long int value;
39};
40
41#define RISCV_HWPROBE_KEY_MVENDORID 0
42#define RISCV_HWPROBE_KEY_MARCHID 1
43#define RISCV_HWPROBE_KEY_MIMPID 2
44#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3
45#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0)
46#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
47#define RISCV_HWPROBE_IMA_FD (1 << 0)
48#define RISCV_HWPROBE_IMA_C (1 << 1)
49#define RISCV_HWPROBE_IMA_V (1 << 2)
50#define RISCV_HWPROBE_EXT_ZBA (1 << 3)
51#define RISCV_HWPROBE_EXT_ZBB (1 << 4)
52#define RISCV_HWPROBE_EXT_ZBS (1 << 5)
53#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6)
54#define RISCV_HWPROBE_KEY_CPUPERF_0 5
55#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
56#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
57#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0)
58#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)
59#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
60#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
61#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6
62
63#endif /* RISCV_HWPROBE_KEY_MVENDORID */
64
65__BEGIN_DECLS
66
67#if defined __cplusplus || !__GNUC_PREREQ (2, 7)
68# define __RISCV_HWPROBE_CPUS_TYPE cpu_set_t *
69#else
70/* The fourth argument to __riscv_hwprobe should be a null pointer or a
71 pointer to a cpu_set_t (either the fixed-size type or allocated with
72 CPU_ALLOC). However, early versions of this header file used the
73 argument type unsigned long int *. The transparent union allows
74 the argument to be either cpu_set_t * or unsigned long int * for
75 compatibility. The older header file requiring unsigned long int *
76 can be identified by the lack of the __RISCV_HWPROBE_CPUS_TYPE macro.
77 In C++ and with compilers that do not support transparent unions, the
78 argument type must be cpu_set_t *. */
79typedef union {
80 cpu_set_t *__cs;
81 unsigned long int *__ul;
82} __RISCV_HWPROBE_CPUS_TYPE __attribute__ ((__transparent_union__));
83# define __RISCV_HWPROBE_CPUS_TYPE __RISCV_HWPROBE_CPUS_TYPE
84#endif
85
86extern int __riscv_hwprobe (struct riscv_hwprobe *__pairs,
87 size_t __pair_count, size_t __cpusetsize,
88 __RISCV_HWPROBE_CPUS_TYPE __cpus,
89 unsigned int __flags)
90 __THROW __nonnull ((1)) __attr_access ((__read_write__, 1, 2));
91
92/* A pointer to the __riscv_hwprobe function is passed as the second
93 argument to ifunc selector routines. Include a function pointer type for
94 convenience in calling the function in those settings. */
95typedef int (*__riscv_hwprobe_t) (struct riscv_hwprobe *__pairs,
96 size_t __pair_count, size_t __cpusetsize,
97 __RISCV_HWPROBE_CPUS_TYPE __cpus,
98 unsigned int __flags)
99 __nonnull ((1)) __attr_access ((__read_write__, 1, 2));
100
101/* Helper function usable from ifunc selectors that probes a single key. */
102static __inline int
103__riscv_hwprobe_one(__riscv_hwprobe_t hwprobe_func,
104 long long int key,
105 unsigned long long int *value)
106{
107 struct riscv_hwprobe pair;
108 int rc;
109
110 /* Earlier versions of glibc pass NULL as the second ifunc parameter. Other C
111 libraries on non-Linux systems may pass +1 as this function pointer to
112 indicate no support. Users copying this function to exotic worlds
113 (non-Linux non-glibc) may want to do additional validity checks here. */
114 if (hwprobe_func == NULL)
115 return ENOSYS;
116
117 pair.key = key;
118 rc = hwprobe_func (&pair, 1, 0, NULL, 0);
119 if (rc != 0)
120 return rc;
121
122 if (pair.key < 0)
123 return ENOENT;
124
125 *value = pair.value;
126 return 0;
127}
128
129__END_DECLS
130
131#endif /* sys/hwprobe.h */