aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h
blob: 40415aae801bdd5a2b72ba4211a489a63d941fd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* RISC-V architecture probe interface
   Copyright (C) 2024-2025 Free Software Foundation, Inc.

   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library.  If not, see
   <https://www.gnu.org/licenses/>.  */

#ifndef _SYS_HWPROBE_H
#define _SYS_HWPROBE_H 1

#include <features.h>
#include <sched.h>
#include <stddef.h>
#include <errno.h>
#ifdef __has_include
# if __has_include (<asm/hwprobe.h>)
#  include <asm/hwprobe.h>
# endif
#endif

/* Define a (probably stale) version of the interface if the Linux headers
   aren't present.  */
#ifndef RISCV_HWPROBE_KEY_MVENDORID
struct riscv_hwprobe {
	signed long long int key;
	unsigned long long int value;
};

#define RISCV_HWPROBE_KEY_MVENDORID 0
#define RISCV_HWPROBE_KEY_MARCHID 1
#define RISCV_HWPROBE_KEY_MIMPID 2
#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3
#define  RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0)
#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
#define  RISCV_HWPROBE_IMA_FD (1 << 0)
#define  RISCV_HWPROBE_IMA_C (1 << 1)
#define  RISCV_HWPROBE_IMA_V (1 << 2)
#define  RISCV_HWPROBE_EXT_ZBA (1 << 3)
#define  RISCV_HWPROBE_EXT_ZBB (1 << 4)
#define  RISCV_HWPROBE_EXT_ZBS (1 << 5)
#define  RISCV_HWPROBE_EXT_ZICBOZ (1 << 6)
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
#define  RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
#define  RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
#define  RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0)
#define  RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)
#define  RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
#define  RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6

#endif /* RISCV_HWPROBE_KEY_MVENDORID */

__BEGIN_DECLS

#if defined __cplusplus || !__GNUC_PREREQ (2, 7)
# define __RISCV_HWPROBE_CPUS_TYPE cpu_set_t *
#else
/* The fourth argument to __riscv_hwprobe should be a null pointer or a
   pointer to a cpu_set_t (either the fixed-size type or allocated with
   CPU_ALLOC).  However, early versions of this header file used the
   argument type unsigned long int *.  The transparent union allows
   the argument to be either cpu_set_t * or unsigned long int * for
   compatibility.  The older header file requiring unsigned long int *
   can be identified by the lack of the __RISCV_HWPROBE_CPUS_TYPE macro.
   In C++ and with compilers that do not support transparent unions, the
   argument type must be cpu_set_t *.  */
typedef union {
	cpu_set_t *__cs;
	unsigned long int *__ul;
} __RISCV_HWPROBE_CPUS_TYPE __attribute__ ((__transparent_union__));
# define __RISCV_HWPROBE_CPUS_TYPE __RISCV_HWPROBE_CPUS_TYPE
#endif

extern int __riscv_hwprobe (struct riscv_hwprobe *__pairs,
			    size_t __pair_count, size_t __cpusetsize,
			    __RISCV_HWPROBE_CPUS_TYPE __cpus,
			    unsigned int __flags)
     __THROW __nonnull ((1)) __attr_access ((__read_write__, 1, 2));

/* A pointer to the __riscv_hwprobe function is passed as the second
   argument to ifunc selector routines. Include a function pointer type for
   convenience in calling the function in those settings. */
typedef int (*__riscv_hwprobe_t) (struct riscv_hwprobe *__pairs,
				  size_t __pair_count, size_t __cpusetsize,
				  __RISCV_HWPROBE_CPUS_TYPE __cpus,
				  unsigned int __flags)
     __nonnull ((1)) __attr_access ((__read_write__, 1, 2));

/* Helper function usable from ifunc selectors that probes a single key. */
static __inline int
__riscv_hwprobe_one(__riscv_hwprobe_t hwprobe_func,
                    long long int key,
                    unsigned long long int *value)
{
  struct riscv_hwprobe pair;
  int rc;

  /* Earlier versions of glibc pass NULL as the second ifunc parameter. Other C
     libraries on non-Linux systems may pass +1 as this function pointer to
     indicate no support. Users copying this function to exotic worlds
     (non-Linux non-glibc) may want to do additional validity checks here. */
  if (hwprobe_func == NULL)
    return ENOSYS;

  pair.key = key;
  rc = hwprobe_func (&pair, 1, 0, NULL, 0);
  if (rc != 0)
    return rc;

  if (pair.key < 0)
    return ENOENT;

  *value = pair.value;
  return 0;
}

__END_DECLS

#endif /* sys/hwprobe.h */