Blame sysdeps/x86/cpu-features.c

Packit 6c4009
/* Initialize CPU feature data.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Copyright (C) 2008-2018 Free Software Foundation, Inc.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <cpuid.h>
Packit Service 541783
#include <cpu-features.h>
Packit 6c4009
#include <dl-hwcap.h>
Packit 6c4009
#include <libc-pointer-arith.h>
Packit 6c4009
Packit 6c4009
#if HAVE_TUNABLES
Packit Service fc5bc2
# define TUNABLE_NAMESPACE cpu
Packit 6c4009
# include <unistd.h>		/* Get STDOUT_FILENO for _dl_printf.  */
Packit 6c4009
# include <elf/dl-tunables.h>
Packit 6c4009
Packit 6c4009
extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *)
Packit 6c4009
  attribute_hidden;
Packit 6c4009
Packit 6c4009
# if CET_ENABLED
Packit 6c4009
extern void TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *)
Packit 6c4009
  attribute_hidden;
Packit 6c4009
extern void TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *)
Packit 6c4009
  attribute_hidden;
Packit 6c4009
# endif
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#if CET_ENABLED
Packit 6c4009
# include <dl-cet.h>
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
static void
Packit Service 541783
get_extended_indices (struct cpu_features *cpu_features)
Packit 6c4009
{
Packit Service 541783
  unsigned int eax, ebx, ecx, edx;
Packit Service 541783
  __cpuid (0x80000000, eax, ebx, ecx, edx);
Packit Service 541783
  if (eax >= 0x80000001)
Packit Service 541783
    __cpuid (0x80000001,
Packit Service 541783
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].eax,
Packit Service 541783
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].ebx,
Packit Service 541783
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].ecx,
Packit Service 541783
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].edx);
Packit Service 881915
  if (eax >= 0x80000007)
Packit Service 881915
    __cpuid (0x80000007,
Packit Service 881915
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].eax,
Packit Service 881915
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].ebx,
Packit Service 881915
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].ecx,
Packit Service 881915
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].edx);
Packit Service 881915
  if (eax >= 0x80000008)
Packit Service 881915
    __cpuid (0x80000008,
Packit Service 881915
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].eax,
Packit Service 881915
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].ebx,
Packit Service 881915
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].ecx,
Packit Service 881915
	     cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].edx);
Packit Service 541783
}
Packit Service 541783
Packit Service 541783
static void
Packit Service 7be6e8
get_common_indices (struct cpu_features *cpu_features,
Packit Service 541783
		    unsigned int *family, unsigned int *model,
Packit Service 541783
		    unsigned int *extended_model, unsigned int *stepping)
Packit Service 541783
{
Packit Service 541783
  if (family)
Packit Service 541783
    {
Packit Service 541783
      unsigned int eax;
Packit Service 541783
      __cpuid (1, eax, cpu_features->cpuid[COMMON_CPUID_INDEX_1].ebx,
Packit Service 541783
	       cpu_features->cpuid[COMMON_CPUID_INDEX_1].ecx,
Packit Service 541783
	       cpu_features->cpuid[COMMON_CPUID_INDEX_1].edx);
Packit Service 541783
      cpu_features->cpuid[COMMON_CPUID_INDEX_1].eax = eax;
Packit Service 541783
      *family = (eax >> 8) & 0x0f;
Packit Service 541783
      *model = (eax >> 4) & 0x0f;
Packit Service 541783
      *extended_model = (eax >> 12) & 0xf0;
Packit Service 541783
      *stepping = eax & 0x0f;
Packit Service 541783
      if (*family == 0x0f)
Packit Service 541783
	{
Packit Service 541783
	  *family += (eax >> 20) & 0xff;
Packit Service 541783
	  *model += *extended_model;
Packit Service 541783
	}
Packit Service 541783
    }
Packit Service 541783
Packit Service 881915
  if (cpu_features->basic.max_cpuid >= 7)
Packit Service 541783
    __cpuid_count (7, 0,
Packit Service 541783
		   cpu_features->cpuid[COMMON_CPUID_INDEX_7].eax,
Packit Service 541783
		   cpu_features->cpuid[COMMON_CPUID_INDEX_7].ebx,
Packit Service 541783
		   cpu_features->cpuid[COMMON_CPUID_INDEX_7].ecx,
Packit Service 541783
		   cpu_features->cpuid[COMMON_CPUID_INDEX_7].edx);
Packit Service 6e118c
Packit Service 881915
  if (cpu_features->basic.max_cpuid >= 0xd)
Packit Service 881915
    __cpuid_count (0xd, 1,
Packit Service 881915
		   cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].eax,
Packit Service 881915
		   cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].ebx,
Packit Service 881915
		   cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].ecx,
Packit Service 881915
		   cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].edx);
Packit Service 881915
Packit 6c4009
  /* Can we call xgetbv?  */
Packit 6c4009
  if (CPU_FEATURES_CPU_P (cpu_features, OSXSAVE))
Packit 6c4009
    {
Packit 6c4009
      unsigned int xcrlow;
Packit 6c4009
      unsigned int xcrhigh;
Packit 6c4009
      asm ("xgetbv" : "=a" (xcrlow), "=d" (xcrhigh) : "c" (0));
Packit 6c4009
      /* Is YMM and XMM state usable?  */
Packit 6c4009
      if ((xcrlow & (bit_YMM_state | bit_XMM_state)) ==
Packit 6c4009
	  (bit_YMM_state | bit_XMM_state))
Packit 6c4009
	{
Packit 6c4009
	  /* Determine if AVX is usable.  */
Packit 6c4009
	  if (CPU_FEATURES_CPU_P (cpu_features, AVX))
Packit 6c4009
	    {
Packit Service 541783
	      cpu_features->feature[index_arch_AVX_Usable]
Packit Service 541783
		|= bit_arch_AVX_Usable;
Packit 6c4009
	      /* The following features depend on AVX being usable.  */
Packit 6c4009
	      /* Determine if AVX2 is usable.  */
Packit 6c4009
	      if (CPU_FEATURES_CPU_P (cpu_features, AVX2))
Packit Service 541783
	      {
Packit Service 541783
		cpu_features->feature[index_arch_AVX2_Usable]
Packit Service 541783
		  |= bit_arch_AVX2_Usable;
Packit Service 541783
Packit Service 541783
	        /* Unaligned load with 256-bit AVX registers are faster on
Packit Service 541783
	           Intel/AMD processors with AVX2.  */
Packit Service 541783
	        cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load]
Packit Service 541783
		  |= bit_arch_AVX_Fast_Unaligned_Load;
Packit Service 541783
	      }
Packit 6c4009
	      /* Determine if FMA is usable.  */
Packit Service 541783
	      if (CPU_FEATURES_CPU_P (cpu_features, FMA))
Packit Service 541783
		cpu_features->feature[index_arch_FMA_Usable]
Packit Service 541783
		  |= bit_arch_FMA_Usable;
Packit Service 881915
	      /* Determine if VAES is usable.  */
Packit Service 881915
	      if (CPU_FEATURES_CPU_P (cpu_features, VAES))
Packit Service 881915
		cpu_features->feature[index_arch_VAES_Usable]
Packit Service 881915
		  |= bit_arch_VAES_Usable;
Packit Service 881915
	      /* Determine if VPCLMULQDQ is usable.  */
Packit Service 881915
	      if (CPU_FEATURES_CPU_P (cpu_features, VPCLMULQDQ))
Packit Service 881915
		cpu_features->feature[index_arch_VPCLMULQDQ_Usable]
Packit Service 881915
		  |= bit_arch_VPCLMULQDQ_Usable;
Packit Service 881915
	      /* Determine if XOP is usable.  */
Packit Service 881915
	      if (CPU_FEATURES_CPU_P (cpu_features, XOP))
Packit Service 881915
		cpu_features->feature[index_arch_XOP_Usable]
Packit Service 881915
		  |= bit_arch_XOP_Usable;
Packit 6c4009
	    }
Packit 6c4009
Packit 6c4009
	  /* Check if OPMASK state, upper 256-bit of ZMM0-ZMM15 and
Packit 6c4009
	     ZMM16-ZMM31 state are enabled.  */
Packit 6c4009
	  if ((xcrlow & (bit_Opmask_state | bit_ZMM0_15_state
Packit 6c4009
			 | bit_ZMM16_31_state)) ==
Packit 6c4009
	      (bit_Opmask_state | bit_ZMM0_15_state | bit_ZMM16_31_state))
Packit 6c4009
	    {
Packit 6c4009
	      /* Determine if AVX512F is usable.  */
Packit 6c4009
	      if (CPU_FEATURES_CPU_P (cpu_features, AVX512F))
Packit 6c4009
		{
Packit Service 541783
		  cpu_features->feature[index_arch_AVX512F_Usable]
Packit Service 541783
		    |= bit_arch_AVX512F_Usable;
Packit Service 881915
		  /* Determine if AVX512CD is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512CD))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512CD_Usable]
Packit Service 881915
		      |= bit_arch_AVX512CD_Usable;
Packit Service 881915
		  /* Determine if AVX512ER is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512ER_Usable]
Packit Service 881915
		      |= bit_arch_AVX512ER_Usable;
Packit Service 881915
		  /* Determine if AVX512PF is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512PF))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512PF_Usable]
Packit Service 881915
		      |= bit_arch_AVX512PF_Usable;
Packit Service 881915
		  /* Determine if AVX512VL is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512VL))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512VL_Usable]
Packit Service 881915
		      |= bit_arch_AVX512VL_Usable;
Packit 6c4009
		  /* Determine if AVX512DQ is usable.  */
Packit Service 541783
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512DQ))
Packit Service 541783
		    cpu_features->feature[index_arch_AVX512DQ_Usable]
Packit Service 541783
		      |= bit_arch_AVX512DQ_Usable;
Packit Service 881915
		  /* Determine if AVX512BW is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512BW))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512BW_Usable]
Packit Service 881915
		      |= bit_arch_AVX512BW_Usable;
Packit Service 881915
		  /* Determine if AVX512_4FMAPS is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_4FMAPS))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512_4FMAPS_Usable]
Packit Service 881915
		      |= bit_arch_AVX512_4FMAPS_Usable;
Packit Service 881915
		  /* Determine if AVX512_4VNNIW is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_4VNNIW))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512_4VNNIW_Usable]
Packit Service 881915
		      |= bit_arch_AVX512_4VNNIW_Usable;
Packit Service 881915
		  /* Determine if AVX512_BITALG is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_BITALG))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512_BITALG_Usable]
Packit Service 881915
		      |= bit_arch_AVX512_BITALG_Usable;
Packit Service 881915
		  /* Determine if AVX512_IFMA is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_IFMA))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512_IFMA_Usable]
Packit Service 881915
		      |= bit_arch_AVX512_IFMA_Usable;
Packit Service 881915
		  /* Determine if AVX512_VBMI is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VBMI))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512_VBMI_Usable]
Packit Service 881915
		      |= bit_arch_AVX512_VBMI_Usable;
Packit Service 881915
		  /* Determine if AVX512_VBMI2 is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VBMI2))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512_VBMI2_Usable]
Packit Service 881915
		      |= bit_arch_AVX512_VBMI2_Usable;
Packit Service 881915
		  /* Determine if is AVX512_VNNI usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VNNI))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512_VNNI_Usable]
Packit Service 881915
		      |= bit_arch_AVX512_VNNI_Usable;
Packit Service 881915
		  /* Determine if AVX512_VPOPCNTDQ is usable.  */
Packit Service 881915
		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VPOPCNTDQ))
Packit Service 881915
		    cpu_features->feature[index_arch_AVX512_VPOPCNTDQ_Usable]
Packit Service 881915
		      |= bit_arch_AVX512_VPOPCNTDQ_Usable;
Packit 6c4009
		}
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      /* For _dl_runtime_resolve, set xsave_state_size to xsave area
Packit 6c4009
	 size + integer register save size and align it to 64 bytes.  */
Packit Service 881915
      if (cpu_features->basic.max_cpuid >= 0xd)
Packit 6c4009
	{
Packit 6c4009
	  unsigned int eax, ebx, ecx, edx;
Packit 6c4009
Packit 6c4009
	  __cpuid_count (0xd, 0, eax, ebx, ecx, edx);
Packit 6c4009
	  if (ebx != 0)
Packit 6c4009
	    {
Packit 6c4009
	      unsigned int xsave_state_full_size
Packit 6c4009
		= ALIGN_UP (ebx + STATE_SAVE_OFFSET, 64);
Packit 6c4009
Packit 6c4009
	      cpu_features->xsave_state_size
Packit 6c4009
		= xsave_state_full_size;
Packit 6c4009
	      cpu_features->xsave_state_full_size
Packit 6c4009
		= xsave_state_full_size;
Packit 6c4009
Packit 6c4009
	      /* Check if XSAVEC is available.  */
Packit Service 881915
	      if (CPU_FEATURES_CPU_P (cpu_features, XSAVEC))
Packit 6c4009
		{
Packit 6c4009
		  unsigned int xstate_comp_offsets[32];
Packit 6c4009
		  unsigned int xstate_comp_sizes[32];
Packit 6c4009
		  unsigned int i;
Packit 6c4009
Packit 6c4009
		  xstate_comp_offsets[0] = 0;
Packit 6c4009
		  xstate_comp_offsets[1] = 160;
Packit 6c4009
		  xstate_comp_offsets[2] = 576;
Packit 6c4009
		  xstate_comp_sizes[0] = 160;
Packit 6c4009
		  xstate_comp_sizes[1] = 256;
Packit 6c4009
Packit 6c4009
		  for (i = 2; i < 32; i++)
Packit 6c4009
		    {
Packit 6c4009
		      if ((STATE_SAVE_MASK & (1 << i)) != 0)
Packit 6c4009
			{
Packit 6c4009
			  __cpuid_count (0xd, i, eax, ebx, ecx, edx);
Packit 6c4009
			  xstate_comp_sizes[i] = eax;
Packit 6c4009
			}
Packit 6c4009
		      else
Packit 6c4009
			{
Packit 6c4009
			  ecx = 0;
Packit 6c4009
			  xstate_comp_sizes[i] = 0;
Packit 6c4009
			}
Packit 6c4009
Packit 6c4009
		      if (i > 2)
Packit 6c4009
			{
Packit 6c4009
			  xstate_comp_offsets[i]
Packit 6c4009
			    = (xstate_comp_offsets[i - 1]
Packit 6c4009
			       + xstate_comp_sizes[i -1]);
Packit 6c4009
			  if ((ecx & (1 << 1)) != 0)
Packit 6c4009
			    xstate_comp_offsets[i]
Packit 6c4009
			      = ALIGN_UP (xstate_comp_offsets[i], 64);
Packit 6c4009
			}
Packit 6c4009
		    }
Packit 6c4009
Packit 6c4009
		  /* Use XSAVEC.  */
Packit 6c4009
		  unsigned int size
Packit 6c4009
		    = xstate_comp_offsets[31] + xstate_comp_sizes[31];
Packit 6c4009
		  if (size)
Packit 6c4009
		    {
Packit 6c4009
		      cpu_features->xsave_state_size
Packit 6c4009
			= ALIGN_UP (size + STATE_SAVE_OFFSET, 64);
Packit Service 541783
		      cpu_features->feature[index_arch_XSAVEC_Usable]
Packit Service 541783
			|= bit_arch_XSAVEC_Usable;
Packit 6c4009
		    }
Packit 6c4009
		}
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
    }
Packit Service da784a
}
Packit Service da784a
Packit Service 881915
_Static_assert (((index_arch_Fast_Unaligned_Load
Packit Service 881915
		  == index_arch_Fast_Unaligned_Copy)
Packit Service 881915
		 && (index_arch_Fast_Unaligned_Load
Packit Service 881915
		     == index_arch_Prefer_PMINUB_for_stringop)
Packit Service 881915
		 && (index_arch_Fast_Unaligned_Load
Packit Service 881915
		     == index_arch_Slow_SSE4_2)
Packit Service 881915
		 && (index_arch_Fast_Unaligned_Load
Packit Service 881915
		     == index_arch_Fast_Rep_String)
Packit Service 881915
		 && (index_arch_Fast_Unaligned_Load
Packit Service 881915
		     == index_arch_Fast_Copy_Backward)),
Packit Service 881915
		"Incorrect index_arch_Fast_Unaligned_Load");
Packit Service 881915
Packit 6c4009
static inline void
Packit 6c4009
init_cpu_features (struct cpu_features *cpu_features)
Packit 6c4009
{
Packit 6c4009
  unsigned int ebx, ecx, edx;
Packit 6c4009
  unsigned int family = 0;
Packit 6c4009
  unsigned int model = 0;
Packit Service 881915
  unsigned int stepping = 0;
Packit 6c4009
  enum cpu_features_kind kind;
Packit 6c4009
Packit 6c4009
#if !HAS_CPUID
Packit 6c4009
  if (__get_cpuid_max (0, 0) == 0)
Packit 6c4009
    {
Packit 6c4009
      kind = arch_kind_other;
Packit 6c4009
      goto no_cpuid;
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
Packit Service 881915
  __cpuid (0, cpu_features->basic.max_cpuid, ebx, ecx, edx);
Packit 6c4009
Packit 6c4009
  /* This spells out "GenuineIntel".  */
Packit 6c4009
  if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
Packit 6c4009
    {
Packit Service 881915
      unsigned int extended_model;
Packit 6c4009
Packit 6c4009
      kind = arch_kind_intel;
Packit 6c4009
Packit Service 7be6e8
      get_common_indices (cpu_features, &family, &model, &extended_model,
Packit 6c4009
			  &stepping);
Packit 6c4009
Packit 6c4009
      get_extended_indices (cpu_features);
Packit 6c4009
Packit 6c4009
      if (family == 0x06)
Packit 6c4009
	{
Packit 6c4009
	  model += extended_model;
Packit 6c4009
	  switch (model)
Packit 6c4009
	    {
Packit 6c4009
	    case 0x1c:
Packit 6c4009
	    case 0x26:
Packit 6c4009
	      /* BSF is slow on Atom.  */
Packit Service 541783
	      cpu_features->feature[index_arch_Slow_BSF]
Packit 6c4009
		|= bit_arch_Slow_BSF;
Packit 6c4009
	      break;
Packit 6c4009
Packit 6c4009
	    case 0x57:
Packit 6c4009
	      /* Knights Landing.  Enable Silvermont optimizations.  */
Packit 6c4009
Packit 6c4009
	    case 0x5c:
Packit 6c4009
	    case 0x5f:
Packit 6c4009
	      /* Unaligned load versions are faster than SSSE3
Packit 6c4009
		 on Goldmont.  */
Packit 6c4009
Packit 6c4009
	    case 0x4c:
Packit 6c4009
	      /* Airmont is a die shrink of Silvermont.  */
Packit 6c4009
Packit 6c4009
	    case 0x37:
Packit 6c4009
	    case 0x4a:
Packit 6c4009
	    case 0x4d:
Packit Service 541783
	    case 0x5a:
Packit 6c4009
	    case 0x5d:
Packit 6c4009
	      /* Unaligned load versions are faster than SSSE3
Packit 6c4009
		 on Silvermont.  */
Packit Service 541783
	      cpu_features->feature[index_arch_Fast_Unaligned_Load]
Packit 6c4009
		|= (bit_arch_Fast_Unaligned_Load
Packit 6c4009
		    | bit_arch_Fast_Unaligned_Copy
Packit 6c4009
		    | bit_arch_Prefer_PMINUB_for_stringop
Packit 6c4009
		    | bit_arch_Slow_SSE4_2);
Packit 6c4009
	      break;
Packit 6c4009
Packit 6c4009
	    default:
Packit 6c4009
	      /* Unknown family 0x06 processors.  Assuming this is one
Packit 6c4009
		 of Core i3/i5/i7 processors if AVX is available.  */
Packit 6c4009
	      if (!CPU_FEATURES_CPU_P (cpu_features, AVX))
Packit 6c4009
		break;
Packit Service 81063c
	      /* Fall through.  */
Packit 6c4009
Packit 6c4009
	    case 0x1a:
Packit 6c4009
	    case 0x1e:
Packit 6c4009
	    case 0x1f:
Packit 6c4009
	    case 0x25:
Packit 6c4009
	    case 0x2c:
Packit 6c4009
	    case 0x2e:
Packit 6c4009
	    case 0x2f:
Packit 6c4009
	      /* Rep string instructions, unaligned load, unaligned copy,
Packit 6c4009
		 and pminub are fast on Intel Core i3, i5 and i7.  */
Packit Service 541783
	      cpu_features->feature[index_arch_Fast_Rep_String]
Packit 6c4009
		|= (bit_arch_Fast_Rep_String
Packit 6c4009
		    | bit_arch_Fast_Unaligned_Load
Packit 6c4009
		    | bit_arch_Fast_Unaligned_Copy
Packit 6c4009
		    | bit_arch_Prefer_PMINUB_for_stringop);
Packit 6c4009
	      break;
Packit Service 831369
	    }
Packit 6c4009
Packit Service 831369
	 /* Disable TSX on some Haswell processors to avoid TSX on kernels that
Packit Service 831369
	    weren't updated with the latest microcode package (which disables
Packit Service 831369
	    broken feature by default).  */
Packit Service 831369
	 switch (model)
Packit Service 831369
	    {
Packit 6c4009
	    case 0x3f:
Packit 6c4009
	      /* Xeon E7 v3 with stepping >= 4 has working TSX.  */
Packit 6c4009
	      if (stepping >= 4)
Packit 6c4009
		break;
Packit Service 81063c
	      /* Fall through.  */
Packit 6c4009
	    case 0x3c:
Packit 6c4009
	    case 0x45:
Packit 6c4009
	    case 0x46:
Packit 6c4009
	      /* Disable Intel TSX on Haswell processors (except Xeon E7 v3
Packit 6c4009
		 with stepping >= 4) to avoid TSX on kernels that weren't
Packit 6c4009
		 updated with the latest microcode package (which disables
Packit 6c4009
		 broken feature by default).  */
Packit Service 541783
	      cpu_features->cpuid[index_cpu_RTM].reg_RTM &= ~bit_cpu_RTM;
Packit 6c4009
	      break;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
Packit 6c4009
      /* Since AVX512ER is unique to Xeon Phi, set Prefer_No_VZEROUPPER
Packit 6c4009
         if AVX512ER is available.  Don't use AVX512 to avoid lower CPU
Packit 6c4009
	 frequency if AVX512ER isn't available.  */
Packit 6c4009
      if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER))
Packit Service 541783
	cpu_features->feature[index_arch_Prefer_No_VZEROUPPER]
Packit 6c4009
	  |= bit_arch_Prefer_No_VZEROUPPER;
Packit 6c4009
      else
Packit Service 541783
	cpu_features->feature[index_arch_Prefer_No_AVX512]
Packit 6c4009
	  |= bit_arch_Prefer_No_AVX512;
Packit 6c4009
    }
Packit 6c4009
  /* This spells out "AuthenticAMD".  */
Packit 6c4009
  else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
Packit 6c4009
    {
Packit Service 881915
      unsigned int extended_model;
Packit 6c4009
Packit 6c4009
      kind = arch_kind_amd;
Packit 6c4009
Packit Service 7be6e8
      get_common_indices (cpu_features, &family, &model, &extended_model,
Packit 6c4009
			  &stepping);
Packit 6c4009
Packit 6c4009
      get_extended_indices (cpu_features);
Packit 6c4009
Packit Service 541783
      ecx = cpu_features->cpuid[COMMON_CPUID_INDEX_1].ecx;
Packit 6c4009
Packit Service 541783
      if (HAS_ARCH_FEATURE (AVX_Usable))
Packit 6c4009
	{
Packit 6c4009
	  /* Since the FMA4 bit is in COMMON_CPUID_INDEX_80000001 and
Packit 6c4009
	     FMA4 requires AVX, determine if FMA4 is usable here.  */
Packit Service 541783
	  if (CPU_FEATURES_CPU_P (cpu_features, FMA4))
Packit Service 541783
	    cpu_features->feature[index_arch_FMA4_Usable]
Packit Service 541783
	      |= bit_arch_FMA4_Usable;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if (family == 0x15)
Packit 6c4009
	{
Packit 6c4009
	  /* "Excavator"   */
Packit 6c4009
	  if (model >= 0x60 && model <= 0x7f)
Packit 6c4009
	  {
Packit Service 541783
	    cpu_features->feature[index_arch_Fast_Unaligned_Load]
Packit 6c4009
	      |= (bit_arch_Fast_Unaligned_Load
Packit 6c4009
		  | bit_arch_Fast_Copy_Backward);
Packit 6c4009
Packit 6c4009
	    /* Unaligned AVX loads are slower.*/
Packit Service 541783
	    cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load]
Packit Service 541783
		  &= ~bit_arch_AVX_Fast_Unaligned_Load;
Packit 6c4009
	  }
Packit 6c4009
	}
Packit 6c4009
    }
Packit Service d59736
  /* This spells out "CentaurHauls" or " Shanghai ".  */
Packit Service d59736
  else if ((ebx == 0x746e6543 && ecx == 0x736c7561 && edx == 0x48727561)
Packit Service d59736
	   || (ebx == 0x68532020 && ecx == 0x20206961 && edx == 0x68676e61))
Packit Service d59736
    {
Packit Service d59736
      unsigned int extended_model, stepping;
Packit Service d59736
Packit Service d59736
      kind = arch_kind_zhaoxin;
Packit Service d59736
Packit Service d59736
      get_common_indices (cpu_features, &family, &model, &extended_model,
Packit Service d59736
			  &stepping);
Packit Service d59736
Packit Service d59736
      get_extended_indices (cpu_features);
Packit Service d59736
Packit Service d59736
      model += extended_model;
Packit Service d59736
      if (family == 0x6)
Packit Service d59736
        {
Packit Service d59736
          if (model == 0xf || model == 0x19)
Packit Service d59736
            {
Packit Service d59736
              cpu_features->feature[index_arch_AVX_Usable]
Packit Service d59736
                &= (~bit_arch_AVX_Usable
Packit Service d59736
                & ~bit_arch_AVX2_Usable);
Packit Service d59736
Packit Service d59736
              cpu_features->feature[index_arch_Slow_SSE4_2]
Packit Service d59736
                |= (bit_arch_Slow_SSE4_2);
Packit Service d59736
Packit Service d59736
              cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load]
Packit Service d59736
                &= ~bit_arch_AVX_Fast_Unaligned_Load;
Packit Service d59736
            }
Packit Service d59736
        }
Packit Service d59736
      else if (family == 0x7)
Packit Service d59736
        {
Packit Service d59736
          if (model == 0x1b)
Packit Service d59736
            {
Packit Service d59736
              cpu_features->feature[index_arch_AVX_Usable]
Packit Service d59736
                &= (~bit_arch_AVX_Usable
Packit Service d59736
                & ~bit_arch_AVX2_Usable);
Packit Service d59736
Packit Service d59736
              cpu_features->feature[index_arch_Slow_SSE4_2]
Packit Service d59736
                |= bit_arch_Slow_SSE4_2;
Packit Service d59736
Packit Service d59736
              cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load]
Packit Service d59736
                &= ~bit_arch_AVX_Fast_Unaligned_Load;
Packit Service d59736
           }
Packit Service d59736
         else if (model == 0x3b)
Packit Service d59736
           {
Packit Service d59736
             cpu_features->feature[index_arch_AVX_Usable]
Packit Service d59736
               &= (~bit_arch_AVX_Usable
Packit Service d59736
               & ~bit_arch_AVX2_Usable);
Packit Service d59736
Packit Service d59736
               cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load]
Packit Service d59736
               &= ~bit_arch_AVX_Fast_Unaligned_Load;
Packit Service d59736
           }
Packit Service d59736
       }
Packit Service d59736
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      kind = arch_kind_other;
Packit Service 7be6e8
      get_common_indices (cpu_features, NULL, NULL, NULL, NULL);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Support i586 if CX8 is available.  */
Packit 6c4009
  if (CPU_FEATURES_CPU_P (cpu_features, CX8))
Packit Service 541783
    cpu_features->feature[index_arch_I586] |= bit_arch_I586;
Packit 6c4009
Packit 6c4009
  /* Support i686 if CMOV is available.  */
Packit 6c4009
  if (CPU_FEATURES_CPU_P (cpu_features, CMOV))
Packit Service 541783
    cpu_features->feature[index_arch_I686] |= bit_arch_I686;
Packit 6c4009
Packit 6c4009
#if !HAS_CPUID
Packit 6c4009
no_cpuid:
Packit 6c4009
#endif
Packit 6c4009
Packit Service 881915
  cpu_features->basic.kind = kind;
Packit Service 881915
  cpu_features->basic.family = family;
Packit Service 881915
  cpu_features->basic.model = model;
Packit Service 881915
  cpu_features->basic.stepping = stepping;
Packit 6c4009
Packit 6c4009
#if HAVE_TUNABLES
Packit 6c4009
  TUNABLE_GET (hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
Packit 6c4009
  cpu_features->non_temporal_threshold
Packit 6c4009
    = TUNABLE_GET (x86_non_temporal_threshold, long int, NULL);
Packit 6c4009
  cpu_features->data_cache_size
Packit 6c4009
    = TUNABLE_GET (x86_data_cache_size, long int, NULL);
Packit 6c4009
  cpu_features->shared_cache_size
Packit 6c4009
    = TUNABLE_GET (x86_shared_cache_size, long int, NULL);
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  /* Reuse dl_platform, dl_hwcap and dl_hwcap_mask for x86.  */
Packit 6c4009
#if !HAVE_TUNABLES && defined SHARED
Packit Service fc5bc2
  /* The glibc.cpu.hwcap_mask tunable is initialized already, so no need to do
Packit 6c4009
     this.  */
Packit 6c4009
  GLRO(dl_hwcap_mask) = HWCAP_IMPORTANT;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifdef __x86_64__
Packit 6c4009
  GLRO(dl_hwcap) = HWCAP_X86_64;
Packit Service 881915
  if (cpu_features->basic.kind == arch_kind_intel)
Packit 6c4009
    {
Packit 6c4009
      const char *platform = NULL;
Packit 6c4009
Packit Service 541783
      if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable)
Packit Service 541783
	  && CPU_FEATURES_CPU_P (cpu_features, AVX512CD))
Packit 6c4009
	{
Packit Service 541783
	  if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER))
Packit 6c4009
	    {
Packit Service 541783
	      if (CPU_FEATURES_CPU_P (cpu_features, AVX512PF))
Packit 6c4009
		platform = "xeon_phi";
Packit 6c4009
	    }
Packit 6c4009
	  else
Packit 6c4009
	    {
Packit Service 541783
	      if (CPU_FEATURES_CPU_P (cpu_features, AVX512BW)
Packit Service 541783
		  && CPU_FEATURES_CPU_P (cpu_features, AVX512DQ)
Packit Service 541783
		  && CPU_FEATURES_CPU_P (cpu_features, AVX512VL))
Packit 6c4009
		GLRO(dl_hwcap) |= HWCAP_X86_AVX512_1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if (platform == NULL
Packit Service 541783
	  && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable)
Packit Service 541783
	  && CPU_FEATURES_ARCH_P (cpu_features, FMA_Usable)
Packit Service 541783
	  && CPU_FEATURES_CPU_P (cpu_features, BMI1)
Packit Service 541783
	  && CPU_FEATURES_CPU_P (cpu_features, BMI2)
Packit Service 541783
	  && CPU_FEATURES_CPU_P (cpu_features, LZCNT)
Packit Service 541783
	  && CPU_FEATURES_CPU_P (cpu_features, MOVBE)
Packit Service 541783
	  && CPU_FEATURES_CPU_P (cpu_features, POPCNT))
Packit 6c4009
	platform = "haswell";
Packit 6c4009
Packit 6c4009
      if (platform != NULL)
Packit 6c4009
	GLRO(dl_platform) = platform;
Packit 6c4009
    }
Packit 6c4009
#else
Packit 6c4009
  GLRO(dl_hwcap) = 0;
Packit Service 541783
  if (CPU_FEATURES_CPU_P (cpu_features, SSE2))
Packit 6c4009
    GLRO(dl_hwcap) |= HWCAP_X86_SSE2;
Packit 6c4009
Packit 6c4009
  if (CPU_FEATURES_ARCH_P (cpu_features, I686))
Packit 6c4009
    GLRO(dl_platform) = "i686";
Packit 6c4009
  else if (CPU_FEATURES_ARCH_P (cpu_features, I586))
Packit 6c4009
    GLRO(dl_platform) = "i586";
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#if CET_ENABLED
Packit 6c4009
# if HAVE_TUNABLES
Packit 6c4009
  TUNABLE_GET (x86_ibt, tunable_val_t *,
Packit 6c4009
	       TUNABLE_CALLBACK (set_x86_ibt));
Packit 6c4009
  TUNABLE_GET (x86_shstk, tunable_val_t *,
Packit 6c4009
	       TUNABLE_CALLBACK (set_x86_shstk));
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
  /* Check CET status.  */
Packit 6c4009
  unsigned int cet_status = get_cet_status ();
Packit 6c4009
Packit 6c4009
  if (cet_status)
Packit 6c4009
    {
Packit Service 78f55d
      GL(dl_x86_feature_1) = cet_status;
Packit 6c4009
Packit 6c4009
# ifndef SHARED
Packit 6c4009
      /* Check if IBT and SHSTK are enabled by kernel.  */
Packit 6c4009
      if ((cet_status & GNU_PROPERTY_X86_FEATURE_1_IBT)
Packit 6c4009
	  || (cet_status & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
Packit 6c4009
	{
Packit 6c4009
	  /* Disable IBT and/or SHSTK if they are enabled by kernel, but
Packit 6c4009
	     disabled by environment variable:
Packit 6c4009
Packit Service fc5bc2
	     GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
Packit 6c4009
	   */
Packit 6c4009
	  unsigned int cet_feature = 0;
Packit Service 8cace5
	  if (!HAS_CPU_FEATURE (IBT))
Packit 6c4009
	    cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
Packit Service 8cace5
	  if (!HAS_CPU_FEATURE (SHSTK))
Packit 6c4009
	    cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
Packit 6c4009
Packit 6c4009
	  if (cet_feature)
Packit 6c4009
	    {
Packit 6c4009
	      int res = dl_cet_disable_cet (cet_feature);
Packit 6c4009
Packit 6c4009
	      /* Clear the disabled bits in dl_x86_feature_1.  */
Packit 6c4009
	      if (res == 0)
Packit Service 78f55d
		GL(dl_x86_feature_1) &= ~cet_feature;
Packit 6c4009
	    }
Packit 6c4009
Packit 6c4009
	  /* Lock CET if IBT or SHSTK is enabled in executable.  Don't
Packit Service 78f55d
	     lock CET if IBT or SHSTK is enabled permissively.  */
Packit Service 78f55d
	  if (GL(dl_x86_feature_control).ibt != cet_permissive
Packit Service 78f55d
	      && GL(dl_x86_feature_control).shstk != cet_permissive)
Packit 6c4009
	    dl_cet_lock_cet ();
Packit 6c4009
	}
Packit 6c4009
# endif
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
}