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 */