x86: Install <cpu-features.h> [BZ #26124]

Message ID 20200617193100.1115529-1-hjl.tools@gmail.com
State Superseded
Headers
Series x86: Install <cpu-features.h> [BZ #26124] |

Commit Message

H.J. Lu June 17, 2020, 7:31 p.m. UTC
  Install <cpu-features.h> so that programmers can do

 #if __has_include(<cpu-features.h>)
 #include <cpu-features.h>
 #endif
 ...

   if (HAS_CPU_FEATURE (SSE3))
 ...
   if (CPU_FEATURE_USABLE (SSE3))
 ...

<cpu-features.h> exports only:

struct cpu_features
{
  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
  unsigned int feature[FEATURE_INDEX_MAX];
  struct cpu_features_basic basic;
};

/* Get a pointer to the CPU features structure.  */
extern const struct cpu_features *__get_cpu_features (void)
     __attribute__ ((const));

Since all feature checks are done through macros, programs compiled with
a newer <cpu-features.h> header are compatible with the older ones as
long as the layout of struct cpu_features is identical.

Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <cpu-features.h>.
---
 sysdeps/unix/sysv/linux/i386/ld.abilist       |  1 +
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |  1 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |  1 +
 sysdeps/x86/Makefile                          |  1 +
 sysdeps/x86/Versions                          |  2 +-
 sysdeps/x86/cpu-features.h                    | 58 ++---------
 sysdeps/x86/include/cpu-features.h            | 95 +++++++++++++++++++
 7 files changed, 106 insertions(+), 53 deletions(-)
 create mode 100644 sysdeps/x86/include/cpu-features.h
  

Comments

Joseph Myers June 17, 2020, 8:54 p.m. UTC | #1
On Wed, 17 Jun 2020, H.J. Lu via Libc-alpha wrote:

> Install <cpu-features.h> so that programmers can do

This appears to be x86-specific.  The convention for such 
architecture-specific headers is names such as sys/platform/x86.h (with 
corresponding naming conventions for individual symbols as documented in 
maint.texi).

This patch needs documentation in the glibc manual of the API provided by 
this header (which would also say that it's x86-specific, and go in 
platform.texi alongside other such documentation of architecture-specific 
interfaces).

New features should also have NEWS entries.
  

Patch

diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index 0478e22071..2f522173b4 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -3,3 +3,4 @@  GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index d3cdf7611e..5a6abd4da0 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -2,3 +2,4 @@  GLIBC_2.2.5 __libc_stack_end D 0x8
 GLIBC_2.2.5 _dl_mcount F
 GLIBC_2.2.5 _r_debug D 0x28
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index c70bccf782..1169d8135d 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -2,3 +2,4 @@  GLIBC_2.16 __libc_stack_end D 0x4
 GLIBC_2.16 __tls_get_addr F
 GLIBC_2.16 _dl_mcount F
 GLIBC_2.16 _r_debug D 0x14
+GLIBC_2.32 __get_cpu_features F
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index beab426f67..47051a3c82 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -4,6 +4,7 @@  endif
 
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-get-cpu-features
+sysdep_headers += cpu-features.h
 
 tests += tst-get-cpu-features tst-get-cpu-features-static
 tests-static += tst-get-cpu-features-static
diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions
index e02923708e..04596dd688 100644
--- a/sysdeps/x86/Versions
+++ b/sysdeps/x86/Versions
@@ -1,5 +1,5 @@ 
 ld {
-  GLIBC_PRIVATE {
+  GLIBC_2.32 {
     __get_cpu_features;
   }
 }
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
index de20044417..5c4e1a726a 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/cpu-features.h
@@ -1,4 +1,5 @@ 
-/* This file is part of the GNU C Library.
+/* Data structure for x86 CPU features.
+   This file is part of the GNU C Library.
    Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,8 +16,8 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef cpu_features_h
-#define cpu_features_h
+#ifndef _CPU_FEATURES_H
+#define _CPU_FEATURES_H
 
 enum
 {
@@ -72,34 +73,12 @@  struct cpu_features
   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
   unsigned int feature[FEATURE_INDEX_MAX];
   struct cpu_features_basic basic;
-  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
-     int so that we use
-
-	sub xsave_state_size_offset(%rip) %RSP_LP
-
-     in _dl_runtime_resolve.  */
-  unsigned long int xsave_state_size;
-  /* The full state size for XSAVE when XSAVEC is disabled by
-
-     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
-   */
-  unsigned int xsave_state_full_size;
-  /* Data cache size for use in memory and string routines, typically
-     L1 size.  */
-  unsigned long int data_cache_size;
-  /* Shared cache size for use in memory and string routines, typically
-     L2 or L3 size.  */
-  unsigned long int shared_cache_size;
-  /* Threshold to use non temporal store.  */
-  unsigned long int non_temporal_threshold;
 };
 
-/* Used from outside of glibc to get access to the CPU features
-   structure.  */
+/* Get a pointer to the CPU features structure.  */
 extern const struct cpu_features *__get_cpu_features (void)
      __attribute__ ((const));
 
-/* Only used directly in cpu-features.c.  */
 # define CPU_FEATURES_CPU_P(ptr, name) \
   ((ptr->cpuid[index_cpu_##name].reg_##name & (bit_cpu_##name)) != 0)
 # define CPU_FEATURES_ARCH_P(ptr, name) \
@@ -976,29 +955,4 @@  extern const struct cpu_features *__get_cpu_features (void)
 #define bit_ZMM0_15_state	(1u << 6)
 #define bit_ZMM16_31_state	(1u << 7)
 
-# if defined (_LIBC) && !IS_IN (nonlib)
-/* Unused for x86.  */
-#  define INIT_ARCH()
-#  define __get_cpu_features()	(&GLRO(dl_x86_cpu_features))
-#  define x86_get_cpuid_registers(i) \
-       (&(GLRO(dl_x86_cpu_features).cpuid[i]))
-# endif
-
-#ifdef __x86_64__
-# define HAS_CPUID 1
-#elif (defined __i586__ || defined __pentium__	\
-       || defined __geode__ || defined __k6__)
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#elif defined __i486__
-# define HAS_CPUID 0
-# define HAS_I586 HAS_ARCH_FEATURE (I586)
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#else
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 1
-#endif
-
-#endif  /* cpu_features_h */
+#endif  /* _CPU_FEATURES_H */
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
new file mode 100644
index 0000000000..e2a303dc1f
--- /dev/null
+++ b/sysdeps/x86/include/cpu-features.h
@@ -0,0 +1,95 @@ 
+/* Data structure for x86 CPU features.
+   Copyright (C) 2020 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	_PRIVATE_CPU_FEATURES_H
+#define	_PRIVATE_CPU_FEATURES_H	1
+
+#ifdef _CPU_FEATURES_H
+# error this should be impossible
+#endif
+
+#ifndef _ISOMAC
+/* Get most of the contents from the public header, but we define a
+   different `struct cpu_features' type for private use.  */
+# define cpu_features	cpu_features_public
+# define __get_cpu_features __get_cpu_features_public
+#endif
+
+#include <sysdeps/x86/cpu-features.h>
+
+#ifndef _ISOMAC
+
+# undef	cpu_features
+# undef __get_cpu_features
+
+/* Forward declaration.  */
+struct cpu_features
+{
+  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
+  unsigned int feature[FEATURE_INDEX_MAX];
+  struct cpu_features_basic basic;
+  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
+     int so that we use
+
+	sub xsave_state_size_offset(%rip) %RSP_LP
+
+     in _dl_runtime_resolve.  */
+  unsigned long int xsave_state_size;
+  /* The full state size for XSAVE when XSAVEC is disabled by
+
+     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
+   */
+  unsigned int xsave_state_full_size;
+  /* Data cache size for use in memory and string routines, typically
+     L1 size.  */
+  unsigned long int data_cache_size;
+  /* Shared cache size for use in memory and string routines, typically
+     L2 or L3 size.  */
+  unsigned long int shared_cache_size;
+  /* Threshold to use non temporal store.  */
+  unsigned long int non_temporal_threshold;
+};
+
+# if defined (_LIBC) && !IS_IN (nonlib)
+/* Unused for x86.  */
+#  define INIT_ARCH()
+#  define __get_cpu_features()	(&GLRO(dl_x86_cpu_features))
+#  define x86_get_cpuid_registers(i) \
+       (&(GLRO(dl_x86_cpu_features).cpuid[i]))
+# endif
+
+# ifdef __x86_64__
+#  define HAS_CPUID 1
+# elif (defined __i586__ || defined __pentium__	\
+	|| defined __geode__ || defined __k6__)
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# elif defined __i486__
+#  define HAS_CPUID 0
+#  define HAS_I586 HAS_ARCH_FEATURE (I586)
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# else
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 1
+# endif
+
+#endif /* !_ISOMAC */
+
+#endif /* include/link.h */