unsigned long _size; // Size of the struct, so it can grow.
unsigned long _hwcap;
unsigned long _hwcap2;
+ unsigned long _hwcap3;
+ unsigned long _hwcap4;
}
*/
tree field3 = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
get_identifier ("_hwcap2"),
long_unsigned_type_node);
+ tree field4 = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
+ get_identifier ("_hwcap3"),
+ long_unsigned_type_node);
+ tree field5 = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
+ get_identifier ("_hwcap4"),
+ long_unsigned_type_node);
DECL_FIELD_CONTEXT (field1) = ifunc_arg_type;
DECL_FIELD_CONTEXT (field2) = ifunc_arg_type;
DECL_FIELD_CONTEXT (field3) = ifunc_arg_type;
+ DECL_FIELD_CONTEXT (field4) = ifunc_arg_type;
+ DECL_FIELD_CONTEXT (field5) = ifunc_arg_type;
TYPE_FIELDS (ifunc_arg_type) = field1;
DECL_CHAIN (field1) = field2;
DECL_CHAIN (field2) = field3;
+ DECL_CHAIN (field3) = field4;
+ DECL_CHAIN (field4) = field5;
layout_type (ifunc_arg_type);
# define HWCAP2_LSE128 (1UL << 47)
#endif
-#if __has_include(<sys/ifunc.h>)
-# include <sys/ifunc.h>
-#else
+/* The following struct is ABI-correct description of the 2nd argument for an
+ ifunc resolver as per SYSVABI spec (see link below). It is safe to extend
+ it with new fields. The ifunc resolver implementations must always check
+ the runtime size of the buffer using the value in the _size field.
+ https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst. */
typedef struct __ifunc_arg_t {
unsigned long _size;
unsigned long _hwcap;
unsigned long _hwcap2;
+ unsigned long _hwcap3;
+ unsigned long _hwcap4;
} __ifunc_arg_t;
+
# define _IFUNC_ARG_HWCAP (1ULL << 62)
-#endif
/* From the file which imported `host-config.h' we can ascertain which
architectural extension provides relevant atomic support. From this,
#if __has_include(<sys/auxv.h>)
#include <sys/auxv.h>
-#if __has_include(<sys/ifunc.h>)
-#include <sys/ifunc.h>
-#else
+/* The following struct is ABI-correct description of the 2nd argument for an
+ ifunc resolver as per SYSVABI spec (see link below). It is safe to extend
+ it with new fields. The ifunc resolver implementations must always check
+ the runtime size of the buffer using the value in the _size field.
+ https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst. */
typedef struct __ifunc_arg_t {
unsigned long _size;
unsigned long _hwcap;
unsigned long _hwcap2;
+ unsigned long _hwcap3;
+ unsigned long _hwcap4;
} __ifunc_arg_t;
-#endif
#if __has_include(<asm/hwcap.h>)
#include <asm/hwcap.h>
#define HWCAP2_LRCPC3 (1UL << 46)
#endif
+#ifndef AT_HWCAP3
+#define AT_HWCAP3 29
+#endif
+
+#ifndef AT_HWCAP4
+#define AT_HWCAP4 30
+#endif
+
+#define __IFUNC_ARG_SIZE_HWCAP2 (sizeof (unsigned long) * 3)
+#define __IFUNC_ARG_SIZE_HWCAP3 (sizeof (unsigned long) * 4)
+#define __IFUNC_ARG_SIZE_HWCAP4 (sizeof (unsigned long) * 5)
+
static void
__init_cpu_features_constructor (unsigned long hwcap,
const __ifunc_arg_t *arg)
#define extractBits(val, start, number) \
(val & ((1UL << number) - 1UL) << start) >> start
unsigned long hwcap2 = 0;
- if (hwcap & _IFUNC_ARG_HWCAP)
+ if ((hwcap & _IFUNC_ARG_HWCAP) && arg->_size >= __IFUNC_ARG_SIZE_HWCAP2)
hwcap2 = arg->_hwcap2;
+ unsigned long hwcap3 __attribute__ ((unused)) = 0;
+ if ((hwcap & _IFUNC_ARG_HWCAP) && arg->_size >= __IFUNC_ARG_SIZE_HWCAP3)
+ hwcap3 = arg->_hwcap3;
+ unsigned long hwcap4 __attribute__ ((unused)) = 0;
+ if ((hwcap & _IFUNC_ARG_HWCAP) && arg->_size >= __IFUNC_ARG_SIZE_HWCAP4)
+ hwcap4 = arg->_hwcap4;
if (hwcap & HWCAP_CRC32)
setCPUFeature(FEAT_CRC);
if (hwcap & HWCAP_PMULL)
{
unsigned long hwcap;
unsigned long hwcap2;
+ unsigned long hwcap3;
+ unsigned long hwcap4;
/* CPU features already initialized. */
if (__atomic_load_n (&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
return;
- hwcap = getauxval(AT_HWCAP);
- hwcap2 = getauxval(AT_HWCAP2);
+ hwcap = getauxval (AT_HWCAP);
+ hwcap2 = getauxval (AT_HWCAP2);
+ hwcap3 = getauxval (AT_HWCAP3);
+ hwcap4 = getauxval (AT_HWCAP4);
+
__ifunc_arg_t arg;
- arg._size = sizeof(__ifunc_arg_t);
+ arg._size = sizeof (__ifunc_arg_t);
arg._hwcap = hwcap;
arg._hwcap2 = hwcap2;
- __init_cpu_features_constructor(hwcap | _IFUNC_ARG_HWCAP, &arg);
+ arg._hwcap3 = hwcap3;
+ arg._hwcap4 = hwcap4;
+ __init_cpu_features_constructor (hwcap | _IFUNC_ARG_HWCAP, &arg);
#undef extractBits
#undef getCPUFeature
#undef setCPUFeature