Blame sysdeps/x86/cacheinfo.c

Packit Bot 0c2104
/* x86_64 cache info.
Packit Bot 0c2104
   Copyright (C) 2003-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
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
#if IS_IN (libc)
Packit 6c4009
Packit 6c4009
#include <assert.h>
Packit Bot 0c2104
#include <stdbool.h>
Packit Bot 0c2104
#include <stdlib.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <cpuid.h>
Packit Bot 0c2104
#include <init-arch.h>
Packit Bot 0c2104
Packit Bot 0c2104
static const struct intel_02_cache_info
Packit Bot 0c2104
{
Packit Bot 0c2104
  unsigned char idx;
Packit Bot 0c2104
  unsigned char assoc;
Packit Bot 0c2104
  unsigned char linesize;
Packit Bot 0c2104
  unsigned char rel_name;
Packit Bot 0c2104
  unsigned int size;
Packit Bot 0c2104
} intel_02_known [] =
Packit Bot 0c2104
  {
Packit Bot 0c2104
#define M(sc) ((sc) - _SC_LEVEL1_ICACHE_SIZE)
Packit Bot 0c2104
    { 0x06,  4, 32, M(_SC_LEVEL1_ICACHE_SIZE),    8192 },
Packit Bot 0c2104
    { 0x08,  4, 32, M(_SC_LEVEL1_ICACHE_SIZE),   16384 },
Packit Bot 0c2104
    { 0x09,  4, 32, M(_SC_LEVEL1_ICACHE_SIZE),   32768 },
Packit Bot 0c2104
    { 0x0a,  2, 32, M(_SC_LEVEL1_DCACHE_SIZE),    8192 },
Packit Bot 0c2104
    { 0x0c,  4, 32, M(_SC_LEVEL1_DCACHE_SIZE),   16384 },
Packit Bot 0c2104
    { 0x0d,  4, 64, M(_SC_LEVEL1_DCACHE_SIZE),   16384 },
Packit Bot 0c2104
    { 0x0e,  6, 64, M(_SC_LEVEL1_DCACHE_SIZE),   24576 },
Packit Bot 0c2104
    { 0x21,  8, 64, M(_SC_LEVEL2_CACHE_SIZE),   262144 },
Packit Bot 0c2104
    { 0x22,  4, 64, M(_SC_LEVEL3_CACHE_SIZE),   524288 },
Packit Bot 0c2104
    { 0x23,  8, 64, M(_SC_LEVEL3_CACHE_SIZE),  1048576 },
Packit Bot 0c2104
    { 0x25,  8, 64, M(_SC_LEVEL3_CACHE_SIZE),  2097152 },
Packit Bot 0c2104
    { 0x29,  8, 64, M(_SC_LEVEL3_CACHE_SIZE),  4194304 },
Packit Bot 0c2104
    { 0x2c,  8, 64, M(_SC_LEVEL1_DCACHE_SIZE),   32768 },
Packit Bot 0c2104
    { 0x30,  8, 64, M(_SC_LEVEL1_ICACHE_SIZE),   32768 },
Packit Bot 0c2104
    { 0x39,  4, 64, M(_SC_LEVEL2_CACHE_SIZE),   131072 },
Packit Bot 0c2104
    { 0x3a,  6, 64, M(_SC_LEVEL2_CACHE_SIZE),   196608 },
Packit Bot 0c2104
    { 0x3b,  2, 64, M(_SC_LEVEL2_CACHE_SIZE),   131072 },
Packit Bot 0c2104
    { 0x3c,  4, 64, M(_SC_LEVEL2_CACHE_SIZE),   262144 },
Packit Bot 0c2104
    { 0x3d,  6, 64, M(_SC_LEVEL2_CACHE_SIZE),   393216 },
Packit Bot 0c2104
    { 0x3e,  4, 64, M(_SC_LEVEL2_CACHE_SIZE),   524288 },
Packit Bot 0c2104
    { 0x3f,  2, 64, M(_SC_LEVEL2_CACHE_SIZE),   262144 },
Packit Bot 0c2104
    { 0x41,  4, 32, M(_SC_LEVEL2_CACHE_SIZE),   131072 },
Packit Bot 0c2104
    { 0x42,  4, 32, M(_SC_LEVEL2_CACHE_SIZE),   262144 },
Packit Bot 0c2104
    { 0x43,  4, 32, M(_SC_LEVEL2_CACHE_SIZE),   524288 },
Packit Bot 0c2104
    { 0x44,  4, 32, M(_SC_LEVEL2_CACHE_SIZE),  1048576 },
Packit Bot 0c2104
    { 0x45,  4, 32, M(_SC_LEVEL2_CACHE_SIZE),  2097152 },
Packit Bot 0c2104
    { 0x46,  4, 64, M(_SC_LEVEL3_CACHE_SIZE),  4194304 },
Packit Bot 0c2104
    { 0x47,  8, 64, M(_SC_LEVEL3_CACHE_SIZE),  8388608 },
Packit Bot 0c2104
    { 0x48, 12, 64, M(_SC_LEVEL2_CACHE_SIZE),  3145728 },
Packit Bot 0c2104
    { 0x49, 16, 64, M(_SC_LEVEL2_CACHE_SIZE),  4194304 },
Packit Bot 0c2104
    { 0x4a, 12, 64, M(_SC_LEVEL3_CACHE_SIZE),  6291456 },
Packit Bot 0c2104
    { 0x4b, 16, 64, M(_SC_LEVEL3_CACHE_SIZE),  8388608 },
Packit Bot 0c2104
    { 0x4c, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 12582912 },
Packit Bot 0c2104
    { 0x4d, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 16777216 },
Packit Bot 0c2104
    { 0x4e, 24, 64, M(_SC_LEVEL2_CACHE_SIZE),  6291456 },
Packit Bot 0c2104
    { 0x60,  8, 64, M(_SC_LEVEL1_DCACHE_SIZE),   16384 },
Packit Bot 0c2104
    { 0x66,  4, 64, M(_SC_LEVEL1_DCACHE_SIZE),    8192 },
Packit Bot 0c2104
    { 0x67,  4, 64, M(_SC_LEVEL1_DCACHE_SIZE),   16384 },
Packit Bot 0c2104
    { 0x68,  4, 64, M(_SC_LEVEL1_DCACHE_SIZE),   32768 },
Packit Bot 0c2104
    { 0x78,  8, 64, M(_SC_LEVEL2_CACHE_SIZE),  1048576 },
Packit Bot 0c2104
    { 0x79,  8, 64, M(_SC_LEVEL2_CACHE_SIZE),   131072 },
Packit Bot 0c2104
    { 0x7a,  8, 64, M(_SC_LEVEL2_CACHE_SIZE),   262144 },
Packit Bot 0c2104
    { 0x7b,  8, 64, M(_SC_LEVEL2_CACHE_SIZE),   524288 },
Packit Bot 0c2104
    { 0x7c,  8, 64, M(_SC_LEVEL2_CACHE_SIZE),  1048576 },
Packit Bot 0c2104
    { 0x7d,  8, 64, M(_SC_LEVEL2_CACHE_SIZE),  2097152 },
Packit Bot 0c2104
    { 0x7f,  2, 64, M(_SC_LEVEL2_CACHE_SIZE),   524288 },
Packit Bot 0c2104
    { 0x80,  8, 64, M(_SC_LEVEL2_CACHE_SIZE),   524288 },
Packit Bot 0c2104
    { 0x82,  8, 32, M(_SC_LEVEL2_CACHE_SIZE),   262144 },
Packit Bot 0c2104
    { 0x83,  8, 32, M(_SC_LEVEL2_CACHE_SIZE),   524288 },
Packit Bot 0c2104
    { 0x84,  8, 32, M(_SC_LEVEL2_CACHE_SIZE),  1048576 },
Packit Bot 0c2104
    { 0x85,  8, 32, M(_SC_LEVEL2_CACHE_SIZE),  2097152 },
Packit Bot 0c2104
    { 0x86,  4, 64, M(_SC_LEVEL2_CACHE_SIZE),   524288 },
Packit Bot 0c2104
    { 0x87,  8, 64, M(_SC_LEVEL2_CACHE_SIZE),  1048576 },
Packit Bot 0c2104
    { 0xd0,  4, 64, M(_SC_LEVEL3_CACHE_SIZE),   524288 },
Packit Bot 0c2104
    { 0xd1,  4, 64, M(_SC_LEVEL3_CACHE_SIZE),  1048576 },
Packit Bot 0c2104
    { 0xd2,  4, 64, M(_SC_LEVEL3_CACHE_SIZE),  2097152 },
Packit Bot 0c2104
    { 0xd6,  8, 64, M(_SC_LEVEL3_CACHE_SIZE),  1048576 },
Packit Bot 0c2104
    { 0xd7,  8, 64, M(_SC_LEVEL3_CACHE_SIZE),  2097152 },
Packit Bot 0c2104
    { 0xd8,  8, 64, M(_SC_LEVEL3_CACHE_SIZE),  4194304 },
Packit Bot 0c2104
    { 0xdc, 12, 64, M(_SC_LEVEL3_CACHE_SIZE),  2097152 },
Packit Bot 0c2104
    { 0xdd, 12, 64, M(_SC_LEVEL3_CACHE_SIZE),  4194304 },
Packit Bot 0c2104
    { 0xde, 12, 64, M(_SC_LEVEL3_CACHE_SIZE),  8388608 },
Packit Bot 0c2104
    { 0xe2, 16, 64, M(_SC_LEVEL3_CACHE_SIZE),  2097152 },
Packit Bot 0c2104
    { 0xe3, 16, 64, M(_SC_LEVEL3_CACHE_SIZE),  4194304 },
Packit Bot 0c2104
    { 0xe4, 16, 64, M(_SC_LEVEL3_CACHE_SIZE),  8388608 },
Packit Bot 0c2104
    { 0xea, 24, 64, M(_SC_LEVEL3_CACHE_SIZE), 12582912 },
Packit Bot 0c2104
    { 0xeb, 24, 64, M(_SC_LEVEL3_CACHE_SIZE), 18874368 },
Packit Bot 0c2104
    { 0xec, 24, 64, M(_SC_LEVEL3_CACHE_SIZE), 25165824 },
Packit Bot 0c2104
  };
Packit Bot 0c2104
Packit Bot 0c2104
#define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known [0]))
Packit Bot 0c2104
Packit Bot 0c2104
static int
Packit Bot 0c2104
intel_02_known_compare (const void *p1, const void *p2)
Packit Bot 0c2104
{
Packit Bot 0c2104
  const struct intel_02_cache_info *i1;
Packit Bot 0c2104
  const struct intel_02_cache_info *i2;
Packit Bot 0c2104
Packit Bot 0c2104
  i1 = (const struct intel_02_cache_info *) p1;
Packit Bot 0c2104
  i2 = (const struct intel_02_cache_info *) p2;
Packit Bot 0c2104
Packit Bot 0c2104
  if (i1->idx == i2->idx)
Packit Bot 0c2104
    return 0;
Packit Bot 0c2104
Packit Bot 0c2104
  return i1->idx < i2->idx ? -1 : 1;
Packit Bot 0c2104
}
Packit Bot 0c2104
Packit Bot 0c2104
Packit Bot 0c2104
static long int
Packit Bot 0c2104
__attribute__ ((noinline))
Packit Bot 0c2104
intel_check_word (int name, unsigned int value, bool *has_level_2,
Packit Bot 0c2104
		  bool *no_level_2_or_3,
Packit Bot 0c2104
		  const struct cpu_features *cpu_features)
Packit Bot 0c2104
{
Packit Bot 0c2104
  if ((value & 0x80000000) != 0)
Packit Bot 0c2104
    /* The register value is reserved.  */
Packit Bot 0c2104
    return 0;
Packit Bot 0c2104
Packit Bot 0c2104
  /* Fold the name.  The _SC_ constants are always in the order SIZE,
Packit Bot 0c2104
     ASSOC, LINESIZE.  */
Packit Bot 0c2104
  int folded_rel_name = (M(name) / 3) * 3;
Packit Bot 0c2104
Packit Bot 0c2104
  while (value != 0)
Packit Bot 0c2104
    {
Packit Bot 0c2104
      unsigned int byte = value & 0xff;
Packit Bot 0c2104
Packit Bot 0c2104
      if (byte == 0x40)
Packit Bot 0c2104
	{
Packit Bot 0c2104
	  *no_level_2_or_3 = true;
Packit Bot 0c2104
Packit Bot 0c2104
	  if (folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))
Packit Bot 0c2104
	    /* No need to look further.  */
Packit Bot 0c2104
	    break;
Packit Bot 0c2104
	}
Packit Bot 0c2104
      else if (byte == 0xff)
Packit Bot 0c2104
	{
Packit Bot 0c2104
	  /* CPUID leaf 0x4 contains all the information.  We need to
Packit Bot 0c2104
	     iterate over it.  */
Packit Bot 0c2104
	  unsigned int eax;
Packit Bot 0c2104
	  unsigned int ebx;
Packit Bot 0c2104
	  unsigned int ecx;
Packit Bot 0c2104
	  unsigned int edx;
Packit Bot 0c2104
Packit Bot 0c2104
	  unsigned int round = 0;
Packit Bot 0c2104
	  while (1)
Packit Bot 0c2104
	    {
Packit Bot 0c2104
	      __cpuid_count (4, round, eax, ebx, ecx, edx);
Packit Bot 0c2104
Packit Bot 0c2104
	      enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f;
Packit Bot 0c2104
	      if (type == null)
Packit Bot 0c2104
		/* That was the end.  */
Packit Bot 0c2104
		break;
Packit Bot 0c2104
Packit Bot 0c2104
	      unsigned int level = (eax >> 5) & 0x7;
Packit Bot 0c2104
Packit Bot 0c2104
	      if ((level == 1 && type == data
Packit Bot 0c2104
		   && folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE))
Packit Bot 0c2104
		  || (level == 1 && type == inst
Packit Bot 0c2104
		      && folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE))
Packit Bot 0c2104
		  || (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE))
Packit Bot 0c2104
		  || (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))
Packit Bot 0c2104
		  || (level == 4 && folded_rel_name == M(_SC_LEVEL4_CACHE_SIZE)))
Packit Bot 0c2104
		{
Packit Bot 0c2104
		  unsigned int offset = M(name) - folded_rel_name;
Packit Bot 0c2104
Packit Bot 0c2104
		  if (offset == 0)
Packit Bot 0c2104
		    /* Cache size.  */
Packit Bot 0c2104
		    return (((ebx >> 22) + 1)
Packit Bot 0c2104
			    * (((ebx >> 12) & 0x3ff) + 1)
Packit Bot 0c2104
			    * ((ebx & 0xfff) + 1)
Packit Bot 0c2104
			    * (ecx + 1));
Packit Bot 0c2104
		  if (offset == 1)
Packit Bot 0c2104
		    return (ebx >> 22) + 1;
Packit Bot 0c2104
Packit Bot 0c2104
		  assert (offset == 2);
Packit Bot 0c2104
		  return (ebx & 0xfff) + 1;
Packit Bot 0c2104
		}
Packit Bot 0c2104
Packit Bot 0c2104
	      ++round;
Packit Bot 0c2104
	    }
Packit Bot 0c2104
	  /* There is no other cache information anywhere else.  */
Packit Bot 0c2104
	  break;
Packit Bot 0c2104
	}
Packit Bot 0c2104
      else
Packit Bot 0c2104
	{
Packit Bot 0c2104
	  if (byte == 0x49 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))
Packit Bot 0c2104
	    {
Packit Bot 0c2104
	      /* Intel reused this value.  For family 15, model 6 it
Packit Bot 0c2104
		 specifies the 3rd level cache.  Otherwise the 2nd
Packit Bot 0c2104
		 level cache.  */
Packit Bot f575c9
	      unsigned int family = cpu_features->basic.family;
Packit Bot f575c9
	      unsigned int model = cpu_features->basic.model;
Packit Bot 0c2104
Packit Bot 0c2104
	      if (family == 15 && model == 6)
Packit Bot 0c2104
		{
Packit Bot 0c2104
		  /* The level 3 cache is encoded for this model like
Packit Bot 0c2104
		     the level 2 cache is for other models.  Pretend
Packit Bot 0c2104
		     the caller asked for the level 2 cache.  */
Packit Bot 0c2104
		  name = (_SC_LEVEL2_CACHE_SIZE
Packit Bot 0c2104
			  + (name - _SC_LEVEL3_CACHE_SIZE));
Packit Bot 0c2104
		  folded_rel_name = M(_SC_LEVEL2_CACHE_SIZE);
Packit Bot 0c2104
		}
Packit Bot 0c2104
	    }
Packit Bot 0c2104
Packit Bot 0c2104
	  struct intel_02_cache_info *found;
Packit Bot 0c2104
	  struct intel_02_cache_info search;
Packit Bot 0c2104
Packit Bot 0c2104
	  search.idx = byte;
Packit Bot 0c2104
	  found = bsearch (&search, intel_02_known, nintel_02_known,
Packit Bot 0c2104
			   sizeof (intel_02_known[0]), intel_02_known_compare);
Packit Bot 0c2104
	  if (found != NULL)
Packit Bot 0c2104
	    {
Packit Bot 0c2104
	      if (found->rel_name == folded_rel_name)
Packit Bot 0c2104
		{
Packit Bot 0c2104
		  unsigned int offset = M(name) - folded_rel_name;
Packit Bot 0c2104
Packit Bot 0c2104
		  if (offset == 0)
Packit Bot 0c2104
		    /* Cache size.  */
Packit Bot 0c2104
		    return found->size;
Packit Bot 0c2104
		  if (offset == 1)
Packit Bot 0c2104
		    return found->assoc;
Packit Bot 0c2104
Packit Bot 0c2104
		  assert (offset == 2);
Packit Bot 0c2104
		  return found->linesize;
Packit Bot 0c2104
		}
Packit Bot 0c2104
Packit Bot 0c2104
	      if (found->rel_name == M(_SC_LEVEL2_CACHE_SIZE))
Packit Bot 0c2104
		*has_level_2 = true;
Packit Bot 0c2104
	    }
Packit Bot 0c2104
	}
Packit Bot 0c2104
Packit Bot 0c2104
      /* Next byte for the next round.  */
Packit Bot 0c2104
      value >>= 8;
Packit Bot 0c2104
    }
Packit Bot 0c2104
Packit Bot 0c2104
  /* Nothing found.  */
Packit Bot 0c2104
  return 0;
Packit Bot 0c2104
}
Packit Bot 0c2104
Packit Bot 0c2104
Packit Bot 0c2104
static long int __attribute__ ((noinline))
Packit Bot 0c2104
handle_intel (int name, const struct cpu_features *cpu_features)
Packit Bot 0c2104
{
Packit Bot f575c9
  unsigned int maxidx = cpu_features->basic.max_cpuid;
Packit Bot 0c2104
Packit Bot 0c2104
  /* Return -1 for older CPUs.  */
Packit Bot 0c2104
  if (maxidx < 2)
Packit Bot 0c2104
    return -1;
Packit Bot 0c2104
Packit Bot 0c2104
  /* OK, we can use the CPUID instruction to get all info about the
Packit Bot 0c2104
     caches.  */
Packit Bot 0c2104
  unsigned int cnt = 0;
Packit Bot 0c2104
  unsigned int max = 1;
Packit Bot 0c2104
  long int result = 0;
Packit Bot 0c2104
  bool no_level_2_or_3 = false;
Packit Bot 0c2104
  bool has_level_2 = false;
Packit Bot 0c2104
Packit Bot 0c2104
  while (cnt++ < max)
Packit Bot 0c2104
    {
Packit Bot 0c2104
      unsigned int eax;
Packit Bot 0c2104
      unsigned int ebx;
Packit Bot 0c2104
      unsigned int ecx;
Packit Bot 0c2104
      unsigned int edx;
Packit Bot 0c2104
      __cpuid (2, eax, ebx, ecx, edx);
Packit Bot 0c2104
Packit Bot 0c2104
      /* The low byte of EAX in the first round contain the number of
Packit Bot 0c2104
	 rounds we have to make.  At least one, the one we are already
Packit Bot 0c2104
	 doing.  */
Packit Bot 0c2104
      if (cnt == 1)
Packit Bot 0c2104
	{
Packit Bot 0c2104
	  max = eax & 0xff;
Packit Bot 0c2104
	  eax &= 0xffffff00;
Packit Bot 0c2104
	}
Packit Bot 0c2104
Packit Bot 0c2104
      /* Process the individual registers' value.  */
Packit Bot 0c2104
      result = intel_check_word (name, eax, &has_level_2,
Packit Bot 0c2104
				 &no_level_2_or_3, cpu_features);
Packit Bot 0c2104
      if (result != 0)
Packit Bot 0c2104
	return result;
Packit Bot 0c2104
Packit Bot 0c2104
      result = intel_check_word (name, ebx, &has_level_2,
Packit Bot 0c2104
				 &no_level_2_or_3, cpu_features);
Packit Bot 0c2104
      if (result != 0)
Packit Bot 0c2104
	return result;
Packit Bot 0c2104
Packit Bot 0c2104
      result = intel_check_word (name, ecx, &has_level_2,
Packit Bot 0c2104
				 &no_level_2_or_3, cpu_features);
Packit Bot 0c2104
      if (result != 0)
Packit Bot 0c2104
	return result;
Packit Bot 0c2104
Packit Bot 0c2104
      result = intel_check_word (name, edx, &has_level_2,
Packit Bot 0c2104
				 &no_level_2_or_3, cpu_features);
Packit Bot 0c2104
      if (result != 0)
Packit Bot 0c2104
	return result;
Packit Bot 0c2104
    }
Packit Bot 0c2104
Packit Bot 0c2104
  if (name >= _SC_LEVEL2_CACHE_SIZE && name <= _SC_LEVEL3_CACHE_LINESIZE
Packit Bot 0c2104
      && no_level_2_or_3)
Packit Bot 0c2104
    return -1;
Packit Bot 0c2104
Packit Bot 0c2104
  return 0;
Packit Bot 0c2104
}
Packit Bot 0c2104
Packit Bot 0c2104
Packit Bot 0c2104
static long int __attribute__ ((noinline))
Packit Bot 0c2104
handle_amd (int name)
Packit Bot 0c2104
{
Packit Bot 0c2104
  unsigned int eax;
Packit Bot 0c2104
  unsigned int ebx;
Packit Bot 0c2104
  unsigned int ecx;
Packit Bot 0c2104
  unsigned int edx;
Packit Bot 0c2104
  __cpuid (0x80000000, eax, ebx, ecx, edx);
Packit Bot 0c2104
Packit Bot 0c2104
  /* No level 4 cache (yet).  */
Packit Bot 0c2104
  if (name > _SC_LEVEL3_CACHE_LINESIZE)
Packit Bot 0c2104
    return 0;
Packit Bot 0c2104
Packit Bot 0c2104
  unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE);
Packit Bot 0c2104
  if (eax < fn)
Packit Bot 0c2104
    return 0;
Packit Bot 0c2104
Packit Bot 0c2104
  __cpuid (fn, eax, ebx, ecx, edx);
Packit Bot 0c2104
Packit Bot 0c2104
  if (name < _SC_LEVEL1_DCACHE_SIZE)
Packit Bot 0c2104
    {
Packit Bot 0c2104
      name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE;
Packit Bot 0c2104
      ecx = edx;
Packit Bot 0c2104
    }
Packit Bot 0c2104
Packit Bot 0c2104
  switch (name)
Packit Bot 0c2104
    {
Packit Bot 0c2104
    case _SC_LEVEL1_DCACHE_SIZE:
Packit Bot 0c2104
      return (ecx >> 14) & 0x3fc00;
Packit Bot 0c2104
Packit Bot 0c2104
    case _SC_LEVEL1_DCACHE_ASSOC:
Packit Bot 0c2104
      ecx >>= 16;
Packit Bot 0c2104
      if ((ecx & 0xff) == 0xff)
Packit Bot 0c2104
	/* Fully associative.  */
Packit Bot 0c2104
	return (ecx << 2) & 0x3fc00;
Packit Bot 0c2104
      return ecx & 0xff;
Packit Bot 0c2104
Packit Bot 0c2104
    case _SC_LEVEL1_DCACHE_LINESIZE:
Packit Bot 0c2104
      return ecx & 0xff;
Packit Bot 0c2104
Packit Bot 0c2104
    case _SC_LEVEL2_CACHE_SIZE:
Packit Bot 0c2104
      return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00;
Packit Bot 0c2104
Packit Bot 0c2104
    case _SC_LEVEL2_CACHE_ASSOC:
Packit Bot 0c2104
      switch ((ecx >> 12) & 0xf)
Packit Bot 0c2104
	{
Packit Bot 0c2104
	case 0:
Packit Bot 0c2104
	case 1:
Packit Bot 0c2104
	case 2:
Packit Bot 0c2104
	case 4:
Packit Bot 0c2104
	  return (ecx >> 12) & 0xf;
Packit Bot 0c2104
	case 6:
Packit Bot 0c2104
	  return 8;
Packit Bot 0c2104
	case 8:
Packit Bot 0c2104
	  return 16;
Packit Bot 0c2104
	case 10:
Packit Bot 0c2104
	  return 32;
Packit Bot 0c2104
	case 11:
Packit Bot 0c2104
	  return 48;
Packit Bot 0c2104
	case 12:
Packit Bot 0c2104
	  return 64;
Packit Bot 0c2104
	case 13:
Packit Bot 0c2104
	  return 96;
Packit Bot 0c2104
	case 14:
Packit Bot 0c2104
	  return 128;
Packit Bot 0c2104
	case 15:
Packit Bot 0c2104
	  return ((ecx >> 6) & 0x3fffc00) / (ecx & 0xff);
Packit Bot 0c2104
	default:
Packit Bot 0c2104
	  return 0;
Packit Bot 0c2104
	}
Packit Bot 0c2104
      /* NOTREACHED */
Packit Bot 0c2104
Packit Bot 0c2104
    case _SC_LEVEL2_CACHE_LINESIZE:
Packit Bot 0c2104
      return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
Packit Bot 0c2104
Packit Bot 0c2104
    case _SC_LEVEL3_CACHE_SIZE:
Packit Bot 0c2104
      return (edx & 0xf000) == 0 ? 0 : (edx & 0x3ffc0000) << 1;
Packit Bot 0c2104
Packit Bot 0c2104
    case _SC_LEVEL3_CACHE_ASSOC:
Packit Bot 0c2104
      switch ((edx >> 12) & 0xf)
Packit Bot 0c2104
	{
Packit Bot 0c2104
	case 0:
Packit Bot 0c2104
	case 1:
Packit Bot 0c2104
	case 2:
Packit Bot 0c2104
	case 4:
Packit Bot 0c2104
	  return (edx >> 12) & 0xf;
Packit Bot 0c2104
	case 6:
Packit Bot 0c2104
	  return 8;
Packit Bot 0c2104
	case 8:
Packit Bot 0c2104
	  return 16;
Packit Bot 0c2104
	case 10:
Packit Bot 0c2104
	  return 32;
Packit Bot 0c2104
	case 11:
Packit Bot 0c2104
	  return 48;
Packit Bot 0c2104
	case 12:
Packit Bot 0c2104
	  return 64;
Packit Bot 0c2104
	case 13:
Packit Bot 0c2104
	  return 96;
Packit Bot 0c2104
	case 14:
Packit Bot 0c2104
	  return 128;
Packit Bot 0c2104
	case 15:
Packit Bot 0c2104
	  return ((edx & 0x3ffc0000) << 1) / (edx & 0xff);
Packit Bot 0c2104
	default:
Packit Bot 0c2104
	  return 0;
Packit Bot 0c2104
	}
Packit Bot 0c2104
      /* NOTREACHED */
Packit Bot 0c2104
Packit Bot 0c2104
    case _SC_LEVEL3_CACHE_LINESIZE:
Packit Bot 0c2104
      return (edx & 0xf000) == 0 ? 0 : edx & 0xff;
Packit Bot 0c2104
Packit Bot 0c2104
    default:
Packit Bot 0c2104
      assert (! "cannot happen");
Packit Bot 0c2104
    }
Packit Bot 0c2104
  return -1;
Packit Bot 0c2104
}
Packit Bot 0c2104
Packit Service 633856
Packit Bot 3fa67e
static long int __attribute__ ((noinline))
Packit Bot 3fa67e
handle_zhaoxin (int name)
Packit Bot 3fa67e
{
Packit Bot 3fa67e
  unsigned int eax;
Packit Bot 3fa67e
  unsigned int ebx;
Packit Bot 3fa67e
  unsigned int ecx;
Packit Bot 3fa67e
  unsigned int edx;
Packit Bot 3fa67e
Packit Bot 3fa67e
  int folded_rel_name = (M(name) / 3) * 3;
Packit Bot 3fa67e
Packit Bot 3fa67e
  unsigned int round = 0;
Packit Bot 3fa67e
  while (1)
Packit Bot 3fa67e
    {
Packit Bot 3fa67e
      __cpuid_count (4, round, eax, ebx, ecx, edx);
Packit Bot 3fa67e
Packit Bot 3fa67e
      enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f;
Packit Bot 3fa67e
      if (type == null)
Packit Bot 3fa67e
        break;
Packit Bot 3fa67e
Packit Bot 3fa67e
      unsigned int level = (eax >> 5) & 0x7;
Packit Bot 3fa67e
Packit Bot 3fa67e
      if ((level == 1 && type == data
Packit Bot 3fa67e
        && folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE))
Packit Bot 3fa67e
        || (level == 1 && type == inst
Packit Bot 3fa67e
            && folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE))
Packit Bot 3fa67e
        || (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE))
Packit Bot 3fa67e
        || (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)))
Packit Bot 3fa67e
        {
Packit Bot 3fa67e
          unsigned int offset = M(name) - folded_rel_name;
Packit Bot 3fa67e
Packit Bot 3fa67e
          if (offset == 0)
Packit Bot 3fa67e
            /* Cache size.  */
Packit Bot 3fa67e
            return (((ebx >> 22) + 1)
Packit Bot 3fa67e
                * (((ebx >> 12) & 0x3ff) + 1)
Packit Bot 3fa67e
                * ((ebx & 0xfff) + 1)
Packit Bot 3fa67e
                * (ecx + 1));
Packit Bot 3fa67e
          if (offset == 1)
Packit Bot 3fa67e
            return (ebx >> 22) + 1;
Packit Bot 3fa67e
Packit Bot 3fa67e
          assert (offset == 2);
Packit Bot 3fa67e
          return (ebx & 0xfff) + 1;
Packit Bot 3fa67e
        }
Packit Bot 3fa67e
Packit Bot 3fa67e
      ++round;
Packit Bot 3fa67e
    }
Packit Bot 3fa67e
Packit Bot 3fa67e
  /* Nothing found.  */
Packit Bot 3fa67e
  return 0;
Packit Bot 3fa67e
}
Packit Bot 3fa67e
Packit Bot 3fa67e
Packit 6c4009
/* Get the value of the system variable NAME.  */
Packit 6c4009
long int
Packit 6c4009
attribute_hidden
Packit 6c4009
__cache_sysconf (int name)
Packit 6c4009
{
Packit 6c4009
  const struct cpu_features *cpu_features = __get_cpu_features ();
Packit 6c4009
Packit Bot f575c9
  if (cpu_features->basic.kind == arch_kind_intel)
Packit 6c4009
    return handle_intel (name, cpu_features);
Packit 6c4009
Packit Bot f575c9
  if (cpu_features->basic.kind == arch_kind_amd)
Packit 6c4009
    return handle_amd (name);
Packit 6c4009
Packit Bot 3fa67e
  if (cpu_features->basic.kind == arch_kind_zhaoxin)
Packit Bot 3fa67e
    return handle_zhaoxin (name);
Packit Bot 3fa67e
Packit 6c4009
  // XXX Fill in more vendors.
Packit 6c4009
Packit 6c4009
  /* CPU not known, we have no information.  */
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit Bot 0c2104
/* Data cache size for use in memory and string routines, typically
Packit Bot 0c2104
   L1 size, rounded to multiple of 256 bytes.  */
Packit Bot 0c2104
long int __x86_data_cache_size_half attribute_hidden = 32 * 1024 / 2;
Packit Bot 0c2104
long int __x86_data_cache_size attribute_hidden = 32 * 1024;
Packit Bot 0c2104
/* Similar to __x86_data_cache_size_half, but not rounded.  */
Packit Bot 0c2104
long int __x86_raw_data_cache_size_half attribute_hidden = 32 * 1024 / 2;
Packit Bot 0c2104
/* Similar to __x86_data_cache_size, but not rounded.  */
Packit Bot 0c2104
long int __x86_raw_data_cache_size attribute_hidden = 32 * 1024;
Packit Bot 0c2104
/* Shared cache size for use in memory and string routines, typically
Packit Bot 0c2104
   L2 or L3 size, rounded to multiple of 256 bytes.  */
Packit Bot 0c2104
long int __x86_shared_cache_size_half attribute_hidden = 1024 * 1024 / 2;
Packit Bot 0c2104
long int __x86_shared_cache_size attribute_hidden = 1024 * 1024;
Packit Bot 0c2104
/* Similar to __x86_shared_cache_size_half, but not rounded.  */
Packit Bot 0c2104
long int __x86_raw_shared_cache_size_half attribute_hidden = 1024 * 1024 / 2;
Packit Bot 0c2104
/* Similar to __x86_shared_cache_size, but not rounded.  */
Packit Bot 0c2104
long int __x86_raw_shared_cache_size attribute_hidden = 1024 * 1024;
Packit Bot 0c2104
Packit Bot 0c2104
/* Threshold to use non temporal store.  */
Packit Bot 0c2104
long int __x86_shared_non_temporal_threshold attribute_hidden;
Packit Bot 0c2104
Packit Bot 0c2104
#ifndef DISABLE_PREFETCHW
Packit Bot 0c2104
/* PREFETCHW support flag for use in memory and string routines.  */
Packit Bot 0c2104
int __x86_prefetchw attribute_hidden;
Packit Bot 0c2104
#endif
Packit Bot 0c2104
Packit Bot 0c2104
Packit Bot 0c2104
static void
Packit Bot 3fa67e
get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr,
Packit Bot 3fa67e
                long int core)
Packit Bot 3fa67e
{
Packit Bot 3fa67e
  unsigned int eax;
Packit Bot 3fa67e
  unsigned int ebx;
Packit Bot 3fa67e
  unsigned int ecx;
Packit Bot 3fa67e
  unsigned int edx;
Packit Bot 3fa67e
Packit Bot 3fa67e
  /* Number of logical processors sharing L2 cache.  */
Packit Bot 3fa67e
  int threads_l2;
Packit Bot 3fa67e
Packit Bot 3fa67e
  /* Number of logical processors sharing L3 cache.  */
Packit Bot 3fa67e
  int threads_l3;
Packit Bot 3fa67e
Packit Bot 3fa67e
  const struct cpu_features *cpu_features = __get_cpu_features ();
Packit Bot 3fa67e
  int max_cpuid = cpu_features->basic.max_cpuid;
Packit Bot 3fa67e
  unsigned int family = cpu_features->basic.family;
Packit Bot 3fa67e
  unsigned int model = cpu_features->basic.model;
Packit Bot 3fa67e
  long int shared = *shared_ptr;
Packit Bot 3fa67e
  unsigned int threads = *threads_ptr;
Packit Bot 3fa67e
  bool inclusive_cache = true;
Packit Bot 3fa67e
  bool support_count_mask = true;
Packit Bot 3fa67e
Packit Bot 3fa67e
  /* Try L3 first.  */
Packit Bot 3fa67e
  unsigned int level = 3;
Packit Bot 3fa67e
Packit Bot 3fa67e
  if (cpu_features->basic.kind == arch_kind_zhaoxin && family == 6)
Packit Bot 3fa67e
    support_count_mask = false;
Packit Bot 3fa67e
Packit Bot 3fa67e
  if (shared <= 0)
Packit Bot 3fa67e
    {
Packit Bot 3fa67e
      /* Try L2 otherwise.  */
Packit Bot 3fa67e
      level  = 2;
Packit Bot 3fa67e
      shared = core;
Packit Bot 3fa67e
      threads_l2 = 0;
Packit Bot 3fa67e
      threads_l3 = -1;
Packit Bot 3fa67e
    }
Packit Bot 3fa67e
  else
Packit Bot 3fa67e
    {
Packit Bot 3fa67e
      threads_l2 = 0;
Packit Bot 3fa67e
      threads_l3 = 0;
Packit Bot 3fa67e
    }
Packit Bot 3fa67e
Packit Bot 3fa67e
  /* A value of 0 for the HTT bit indicates there is only a single
Packit Bot 3fa67e
     logical processor.  */
Packit Bot 3fa67e
  if (HAS_CPU_FEATURE (HTT))
Packit Bot 3fa67e
    {
Packit Bot 3fa67e
      /* Figure out the number of logical threads that share the
Packit Bot 3fa67e
         highest cache level.  */
Packit Bot 3fa67e
      if (max_cpuid >= 4)
Packit Bot 3fa67e
        {
Packit Bot 3fa67e
          int i = 0;
Packit Bot 3fa67e
Packit Bot 3fa67e
          /* Query until cache level 2 and 3 are enumerated.  */
Packit Bot 3fa67e
          int check = 0x1 | (threads_l3 == 0) << 1;
Packit Bot 3fa67e
          do
Packit Bot 3fa67e
            {
Packit Bot 3fa67e
              __cpuid_count (4, i++, eax, ebx, ecx, edx);
Packit Bot 3fa67e
Packit Bot 3fa67e
              /* There seems to be a bug in at least some Pentium Ds
Packit Bot 3fa67e
                 which sometimes fail to iterate all cache parameters.
Packit Bot 3fa67e
                 Do not loop indefinitely here, stop in this case and
Packit Bot 3fa67e
                 assume there is no such information.  */
Packit Bot 3fa67e
              if (cpu_features->basic.kind == arch_kind_intel
Packit Bot 3fa67e
                  && (eax & 0x1f) == 0 )
Packit Bot 3fa67e
                goto intel_bug_no_cache_info;
Packit Bot 3fa67e
Packit Bot 3fa67e
              switch ((eax >> 5) & 0x7)
Packit Bot 3fa67e
                {
Packit Bot 3fa67e
                  default:
Packit Bot 3fa67e
                    break;
Packit Bot 3fa67e
                  case 2:
Packit Bot 3fa67e
                    if ((check & 0x1))
Packit Bot 3fa67e
                      {
Packit Bot 3fa67e
                        /* Get maximum number of logical processors
Packit Bot 3fa67e
                           sharing L2 cache.  */
Packit Bot 3fa67e
                        threads_l2 = (eax >> 14) & 0x3ff;
Packit Bot 3fa67e
                        check &= ~0x1;
Packit Bot 3fa67e
                      }
Packit Bot 3fa67e
                    break;
Packit Bot 3fa67e
                  case 3:
Packit Bot 3fa67e
                    if ((check & (0x1 << 1)))
Packit Bot 3fa67e
                      {
Packit Bot 3fa67e
                        /* Get maximum number of logical processors
Packit Bot 3fa67e
                           sharing L3 cache.  */
Packit Bot 3fa67e
                        threads_l3 = (eax >> 14) & 0x3ff;
Packit Bot 3fa67e
Packit Bot 3fa67e
                        /* Check if L2 and L3 caches are inclusive.  */
Packit Bot 3fa67e
                        inclusive_cache = (edx & 0x2) != 0;
Packit Bot 3fa67e
                        check &= ~(0x1 << 1);
Packit Bot 3fa67e
                      }
Packit Bot 3fa67e
                    break;
Packit Bot 3fa67e
                }
Packit Bot 3fa67e
            }
Packit Bot 3fa67e
          while (check);
Packit Bot 3fa67e
Packit Bot 3fa67e
          /* If max_cpuid >= 11, THREADS_L2/THREADS_L3 are the maximum
Packit Bot 3fa67e
             numbers of addressable IDs for logical processors sharing
Packit Bot 3fa67e
             the cache, instead of the maximum number of threads
Packit Bot 3fa67e
             sharing the cache.  */
Packit Bot 3fa67e
          if (max_cpuid >= 11 && support_count_mask)
Packit Bot 3fa67e
            {
Packit Bot 3fa67e
              /* Find the number of logical processors shipped in
Packit Bot 3fa67e
                 one core and apply count mask.  */
Packit Bot 3fa67e
              i = 0;
Packit Bot 3fa67e
Packit Bot 3fa67e
              /* Count SMT only if there is L3 cache.  Always count
Packit Bot 3fa67e
                 core if there is no L3 cache.  */
Packit Bot 3fa67e
              int count = ((threads_l2 > 0 && level == 3)
Packit Bot 3fa67e
                           | ((threads_l3 > 0
Packit Bot 3fa67e
                               || (threads_l2 > 0 && level == 2)) << 1));
Packit Bot 3fa67e
Packit Bot 3fa67e
              while (count)
Packit Bot 3fa67e
                {
Packit Bot 3fa67e
                  __cpuid_count (11, i++, eax, ebx, ecx, edx);
Packit Bot 3fa67e
Packit Bot 3fa67e
                  int shipped = ebx & 0xff;
Packit Bot 3fa67e
                  int type = ecx & 0xff00;
Packit Bot 3fa67e
                  if (shipped == 0 || type == 0)
Packit Bot 3fa67e
                    break;
Packit Bot 3fa67e
                  else if (type == 0x100)
Packit Bot 3fa67e
                    {
Packit Bot 3fa67e
                      /* Count SMT.  */
Packit Bot 3fa67e
                      if ((count & 0x1))
Packit Bot 3fa67e
                        {
Packit Bot 3fa67e
                          int count_mask;
Packit Bot 3fa67e
Packit Bot 3fa67e
                          /* Compute count mask.  */
Packit Bot 3fa67e
                          asm ("bsr %1, %0"
Packit Bot 3fa67e
                               : "=r" (count_mask) : "g" (threads_l2));
Packit Bot 3fa67e
                          count_mask = ~(-1 << (count_mask + 1));
Packit Bot 3fa67e
                          threads_l2 = (shipped - 1) & count_mask;
Packit Bot 3fa67e
                          count &= ~0x1;
Packit Bot 3fa67e
                        }
Packit Bot 3fa67e
                    }
Packit Bot 3fa67e
                  else if (type == 0x200)
Packit Bot 3fa67e
                    {
Packit Bot 3fa67e
                      /* Count core.  */
Packit Bot 3fa67e
                      if ((count & (0x1 << 1)))
Packit Bot 3fa67e
                        {
Packit Bot 3fa67e
                          int count_mask;
Packit Bot 3fa67e
                          int threads_core
Packit Bot 3fa67e
                            = (level == 2 ? threads_l2 : threads_l3);
Packit Bot 3fa67e
Packit Bot 3fa67e
                          /* Compute count mask.  */
Packit Bot 3fa67e
                          asm ("bsr %1, %0"
Packit Bot 3fa67e
                               : "=r" (count_mask) : "g" (threads_core));
Packit Bot 3fa67e
                          count_mask = ~(-1 << (count_mask + 1));
Packit Bot 3fa67e
                          threads_core = (shipped - 1) & count_mask;
Packit Bot 3fa67e
                          if (level == 2)
Packit Bot 3fa67e
                            threads_l2 = threads_core;
Packit Bot 3fa67e
                          else
Packit Bot 3fa67e
                            threads_l3 = threads_core;
Packit Bot 3fa67e
                          count &= ~(0x1 << 1);
Packit Bot 3fa67e
                        }
Packit Bot 3fa67e
                    }
Packit Bot 3fa67e
                }
Packit Bot 3fa67e
            }
Packit Bot 3fa67e
          if (threads_l2 > 0)
Packit Bot 3fa67e
            threads_l2 += 1;
Packit Bot 3fa67e
          if (threads_l3 > 0)
Packit Bot 3fa67e
            threads_l3 += 1;
Packit Bot 3fa67e
          if (level == 2)
Packit Bot 3fa67e
            {
Packit Bot 3fa67e
              if (threads_l2)
Packit Bot 3fa67e
                {
Packit Bot 3fa67e
                  threads = threads_l2;
Packit Bot 3fa67e
                  if (cpu_features->basic.kind == arch_kind_intel
Packit Bot 3fa67e
                      && threads > 2
Packit Bot 3fa67e
                      && family == 6)
Packit Bot 3fa67e
                    switch (model)
Packit Bot 3fa67e
                      {
Packit Bot 3fa67e
                        case 0x37:
Packit Bot 3fa67e
                        case 0x4a:
Packit Bot 3fa67e
                        case 0x4d:
Packit Bot 3fa67e
                        case 0x5a:
Packit Bot 3fa67e
                        case 0x5d:
Packit Bot 3fa67e
                          /* Silvermont has L2 cache shared by 2 cores.  */
Packit Bot 3fa67e
                          threads = 2;
Packit Bot 3fa67e
                          break;
Packit Bot 3fa67e
                        default:
Packit Bot 3fa67e
                          break;
Packit Bot 3fa67e
                      }
Packit Bot 3fa67e
                }
Packit Bot 3fa67e
            }
Packit Bot 3fa67e
          else if (threads_l3)
Packit Bot 3fa67e
            threads = threads_l3;
Packit Bot 3fa67e
        }
Packit Bot 3fa67e
      else
Packit Bot 3fa67e
        {
Packit Bot 3fa67e
intel_bug_no_cache_info:
Packit Bot 3fa67e
          /* Assume that all logical threads share the highest cache
Packit Bot 3fa67e
             level.  */
Packit Bot 3fa67e
          threads
Packit Bot 3fa67e
            = ((cpu_features->cpuid[COMMON_CPUID_INDEX_1].ebx
Packit Bot 3fa67e
                >> 16) & 0xff);
Packit Bot 3fa67e
        }
Packit Bot 3fa67e
Packit Bot 3fa67e
        /* Cap usage of highest cache level to the number of supported
Packit Bot 3fa67e
           threads.  */
Packit Bot 3fa67e
        if (shared > 0 && threads > 0)
Packit Bot 3fa67e
          shared /= threads;
Packit Bot 3fa67e
    }
Packit Bot 3fa67e
Packit Bot 3fa67e
  /* Account for non-inclusive L2 and L3 caches.  */
Packit Bot 3fa67e
  if (!inclusive_cache)
Packit Bot 3fa67e
    {
Packit Bot 3fa67e
      if (threads_l2 > 0)
Packit Bot 3fa67e
        core /= threads_l2;
Packit Bot 3fa67e
      shared += core;
Packit Bot 3fa67e
    }
Packit Bot 3fa67e
Packit Bot 3fa67e
  *shared_ptr = shared;
Packit Bot 3fa67e
  *threads_ptr = threads;
Packit Bot 3fa67e
}
Packit Bot 3fa67e
Packit Bot 3fa67e
Packit Bot 3fa67e
static void
Packit Bot 0c2104
__attribute__((constructor))
Packit Bot 0c2104
init_cacheinfo (void)
Packit Bot 0c2104
{
Packit Bot 0c2104
  /* Find out what brand of processor.  */
Packit Bot 0c2104
  unsigned int eax;
Packit Bot 0c2104
  unsigned int ebx;
Packit Bot 0c2104
  unsigned int ecx;
Packit Bot 0c2104
  unsigned int edx;
Packit Bot 0c2104
  int max_cpuid_ex;
Packit Bot 0c2104
  long int data = -1;
Packit Bot 0c2104
  long int shared = -1;
Packit Bot 3fa67e
  long int core;
Packit Bot 0c2104
  unsigned int threads = 0;
Packit Bot 0c2104
  const struct cpu_features *cpu_features = __get_cpu_features ();
Packit Bot 0c2104
Packit Bot f575c9
  if (cpu_features->basic.kind == arch_kind_intel)
Packit Bot 0c2104
    {
Packit Bot 0c2104
      data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
Packit Bot 3fa67e
      core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
Packit Bot 0c2104
      shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features);
Packit Bot 0c2104
Packit Bot 3fa67e
      get_common_cache_info (&shared, &threads, core);
Packit Bot 3fa67e
    }
Packit Bot 3fa67e
  else if (cpu_features->basic.kind == arch_kind_zhaoxin)
Packit Bot 3fa67e
    {
Packit Bot 3fa67e
      data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE);
Packit Bot 3fa67e
      core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE);
Packit Bot 3fa67e
      shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE);
Packit Bot 0c2104
Packit Bot 3fa67e
      get_common_cache_info (&shared, &threads, core);
Packit Bot 0c2104
    }
Packit Bot f575c9
  else if (cpu_features->basic.kind == arch_kind_amd)
Packit Bot 0c2104
    {
Packit Bot 0c2104
      data   = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
Packit Bot 0c2104
      long int core = handle_amd (_SC_LEVEL2_CACHE_SIZE);
Packit Bot 0c2104
      shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
Packit Bot 0c2104
Packit Bot 0c2104
      /* Get maximum extended function. */
Packit Bot 0c2104
      __cpuid (0x80000000, max_cpuid_ex, ebx, ecx, edx);
Packit Bot 0c2104
Packit Bot 0c2104
      if (shared <= 0)
Packit Bot 0c2104
	/* No shared L3 cache.  All we have is the L2 cache.  */
Packit Bot 0c2104
	shared = core;
Packit Bot 0c2104
      else
Packit Bot 0c2104
	{
Packit Bot 0c2104
	  /* Figure out the number of logical threads that share L3.  */
Packit Bot 0c2104
	  if (max_cpuid_ex >= 0x80000008)
Packit Bot 0c2104
	    {
Packit Bot 0c2104
	      /* Get width of APIC ID.  */
Packit Bot 0c2104
	      __cpuid (0x80000008, max_cpuid_ex, ebx, ecx, edx);
Packit Bot 0c2104
	      threads = 1 << ((ecx >> 12) & 0x0f);
Packit Bot 0c2104
	    }
Packit Bot 0c2104
Packit Bot f575c9
	  if (threads == 0 || cpu_features->basic.family >= 0x17)
Packit Bot 0c2104
	    {
Packit Bot 0c2104
	      /* If APIC ID width is not available, use logical
Packit Bot 0c2104
		 processor count.  */
Packit Bot 0c2104
	      __cpuid (0x00000001, max_cpuid_ex, ebx, ecx, edx);
Packit Bot 0c2104
Packit Bot 0c2104
	      if ((edx & (1 << 28)) != 0)
Packit Bot 0c2104
		threads = (ebx >> 16) & 0xff;
Packit Bot 0c2104
	    }
Packit Bot 0c2104
Packit Bot 0c2104
	  /* Cap usage of highest cache level to the number of
Packit Bot 0c2104
	     supported threads.  */
Packit Bot 0c2104
	  if (threads > 0)
Packit Bot 0c2104
	    shared /= threads;
Packit Bot 0c2104
Packit Bot f633bf
	  /* Get shared cache per ccx for Zen architectures.  */
Packit Bot f575c9
	  if (cpu_features->basic.family >= 0x17)
Packit Bot f633bf
	    {
Packit Bot f633bf
	      unsigned int eax;
Packit Bot f633bf
Packit Bot f633bf
	      /* Get number of threads share the L3 cache in CCX.  */
Packit Bot f633bf
	      __cpuid_count (0x8000001D, 0x3, eax, ebx, ecx, edx);
Packit Bot f633bf
Packit Bot f633bf
	      unsigned int threads_per_ccx = ((eax >> 14) & 0xfff) + 1;
Packit Bot f633bf
	      shared *= threads_per_ccx;
Packit Bot f633bf
	    }
Packit Bot f633bf
	  else
Packit Bot f633bf
	    {
Packit Bot f633bf
	      /* Account for exclusive L2 and L3 caches.  */
Packit Bot f633bf
	      shared += core;
Packit Bot f633bf
            }
Packit Bot 0c2104
	}
Packit Bot 0c2104
Packit Bot 0c2104
#ifndef DISABLE_PREFETCHW
Packit Bot 0c2104
      if (max_cpuid_ex >= 0x80000001)
Packit Bot 0c2104
	{
Packit Bot 0c2104
	  __cpuid (0x80000001, eax, ebx, ecx, edx);
Packit Bot 0c2104
	  /*  PREFETCHW     || 3DNow!  */
Packit Bot 0c2104
	  if ((ecx & 0x100) || (edx & 0x80000000))
Packit Bot 0c2104
	    __x86_prefetchw = -1;
Packit Bot 0c2104
	}
Packit Bot 0c2104
#endif
Packit Bot 0c2104
    }
Packit Bot 0c2104
Packit Bot 0c2104
  if (cpu_features->data_cache_size != 0)
Packit Bot 0c2104
    data = cpu_features->data_cache_size;
Packit Bot 0c2104
Packit Bot 0c2104
  if (data > 0)
Packit Bot 0c2104
    {
Packit Bot 0c2104
      __x86_raw_data_cache_size_half = data / 2;
Packit Bot 0c2104
      __x86_raw_data_cache_size = data;
Packit Bot 0c2104
      /* Round data cache size to multiple of 256 bytes.  */
Packit Bot 0c2104
      data = data & ~255L;
Packit Bot 0c2104
      __x86_data_cache_size_half = data / 2;
Packit Bot 0c2104
      __x86_data_cache_size = data;
Packit Bot 0c2104
    }
Packit Bot 0c2104
Packit Bot 0c2104
  if (cpu_features->shared_cache_size != 0)
Packit Bot 0c2104
    shared = cpu_features->shared_cache_size;
Packit Bot 0c2104
Packit Bot 0c2104
  if (shared > 0)
Packit Bot 0c2104
    {
Packit Bot 0c2104
      __x86_raw_shared_cache_size_half = shared / 2;
Packit Bot 0c2104
      __x86_raw_shared_cache_size = shared;
Packit Bot 0c2104
      /* Round shared cache size to multiple of 256 bytes.  */
Packit Bot 0c2104
      shared = shared & ~255L;
Packit Bot 0c2104
      __x86_shared_cache_size_half = shared / 2;
Packit Bot 0c2104
      __x86_shared_cache_size = shared;
Packit Bot 0c2104
    }
Packit Bot 0c2104
Packit Bot 4b7bb0
  /* The default setting for the non_temporal threshold is 3/4 of one
Packit Bot 4b7bb0
     thread's share of the chip's cache. For most Intel and AMD processors
Packit Bot 4b7bb0
     with an initial release date between 2017 and 2020, a thread's typical
Packit Bot 4b7bb0
     share of the cache is from 500 KBytes to 2 MBytes. Using the 3/4
Packit Bot 4b7bb0
     threshold leaves 125 KBytes to 500 KBytes of the thread's data
Packit Bot 4b7bb0
     in cache after a maximum temporal copy, which will maintain
Packit Bot 4b7bb0
     in cache a reasonable portion of the thread's stack and other
Packit Bot 4b7bb0
     active data. If the threshold is set higher than one thread's
Packit Bot 4b7bb0
     share of the cache, it has a substantial risk of negatively
Packit Bot 4b7bb0
     impacting the performance of other threads running on the chip. */
Packit Bot 0c2104
  __x86_shared_non_temporal_threshold
Packit Bot 0c2104
    = (cpu_features->non_temporal_threshold != 0
Packit Bot 0c2104
       ? cpu_features->non_temporal_threshold
Packit Bot 4b7bb0
       : __x86_shared_cache_size * 3 / 4);
Packit Bot 0c2104
}
Packit Service 3e830d
Packit 6c4009
#endif