Blame sysdeps/x86/cacheinfo.c

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