17862701c0e3f556e4a0c7ec4074a40526c73a4efflorian/* -*- mode: C; c-basic-offset: 3; -*- */
2b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
3b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote/*--------------------------------------------------------------------*/
47862701c0e3f556e4a0c7ec4074a40526c73a4efflorian/*--- Cache-related stuff.                               m_cache.c ---*/
5b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote/*--------------------------------------------------------------------*/
6b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
7b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote/*
87862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   This file is part of Valgrind, a dynamic binary instrumentation
97862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   framework.
10b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
11b3a1e4bffbdbbf38304f216af405009868f43628sewardj   Copyright (C) 2002-2015 Nicholas Nethercote
122bc10126a94b421a490b2759dc50ab67ec4ee116njn      njn@valgrind.org
13b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
14b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   This program is free software; you can redistribute it and/or
15b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   modify it under the terms of the GNU General Public License as
16b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   published by the Free Software Foundation; either version 2 of the
17b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   License, or (at your option) any later version.
18b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
19b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   This program is distributed in the hope that it will be useful, but
20b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   WITHOUT ANY WARRANTY; without even the implied warranty of
21b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   General Public License for more details.
23b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
24b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   You should have received a copy of the GNU General Public License
25b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   along with this program; if not, write to the Free Software
26b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   02111-1307, USA.
28b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
29b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   The GNU General Public License is contained in the file COPYING.
30b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote*/
31b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
327862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#include "pub_core_basics.h"
337862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#include "pub_core_libcbase.h"
347862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#include "pub_core_libcassert.h"
357862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#include "pub_core_libcprint.h"
367862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#include "pub_core_mallocfree.h"
377862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#include "pub_core_machine.h"
3838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#include "pub_core_debuglog.h"
397862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#include "libvex.h"
408b68b64759254d514d98328c496cbd88cde4c9a5njn
417862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#if defined(VGA_x86) || defined(VGA_amd64)
42c7561b931e249acf3768ead77638545b0ccaa8f1njn
437862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#include "pub_core_cpuid.h"
44b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
45f91b0a372a0d0cb4030b096337d3c1ebe26d6b30sewardj// All CPUID info taken from sandpile.org/ia32/cpuid.htm */
46b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote// Probably only works for Intel and AMD chips, and probably only for some of
477862701c0e3f556e4a0c7ec4074a40526c73a4efflorian// them.
48b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
4938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianstatic void
5038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianadd_cache(VexCacheInfo *ci, VexCache cache)
51b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote{
5238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   static UInt num_allocated = 0;
5338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
5438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   if (ci->num_caches == num_allocated) {
5538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      num_allocated += 6;
5638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      ci->caches = VG_(realloc)("m_cache", ci->caches,
5738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                                num_allocated * sizeof *ci->caches);
5838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   }
5938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
6038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   if (ci->num_levels < cache.level) ci->num_levels = cache.level;
6138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   ci->caches[ci->num_caches++] = cache;
62b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote}
63b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
6438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian/* Convenience macros */
6538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_icache(level, size, assoc, linesize) \
6638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   do { \
6738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      add_cache(ci, \
6838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                VEX_CACHE_INIT(INSN_CACHE, level, size, linesize, assoc)); \
6938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   } while (0)
7038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
7138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_dcache(level, size, assoc, linesize) \
7238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   do { \
7338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      add_cache(ci, \
7438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                VEX_CACHE_INIT(DATA_CACHE, level, size, linesize, assoc)); \
7538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   } while (0)
7638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
7738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_ucache(level, size, assoc, linesize) \
7838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   do { \
7938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      add_cache(ci, \
8038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                VEX_CACHE_INIT(UNIFIED_CACHE, level, size, linesize, assoc)); \
8138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   } while (0)
8238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
8338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_itcache(level, size, assoc) \
8438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   do { \
8538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VexCache c = \
8638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian          VEX_CACHE_INIT(INSN_CACHE, level, size, 0, assoc); \
8738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      c.is_trace_cache = True; \
8838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      add_cache(ci, c); \
8938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   } while (0)
9038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
9138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_I1(size, assoc, linesize) add_icache(1, size, assoc, linesize)
9238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_D1(size, assoc, linesize) add_dcache(1, size, assoc, linesize)
9338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_U1(size, assoc, linesize) add_ucache(1, size, assoc, linesize)
9438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_I2(size, assoc, linesize) add_icache(2, size, assoc, linesize)
9538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_D2(size, assoc, linesize) add_dcache(2, size, assoc, linesize)
9638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_U2(size, assoc, linesize) add_ucache(2, size, assoc, linesize)
9738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_I3(size, assoc, linesize) add_icache(3, size, assoc, linesize)
9838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_D3(size, assoc, linesize) add_dcache(3, size, assoc, linesize)
9938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_U3(size, assoc, linesize) add_ucache(3, size, assoc, linesize)
10038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
10138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian#define add_I1T(size, assoc) \
10238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   add_itcache(1, size, assoc)
1037862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
104b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote/* Intel method is truly wretched.  We have to do an insane indexing into an
105b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote * array of pre-defined configurations for various parts of the memory
1061c3e3c5f51bfea566a55024fe2ef4c1eb3d47265weidendo * hierarchy.
1071c3e3c5f51bfea566a55024fe2ef4c1eb3d47265weidendo * According to Intel Processor Identification, App Note 485.
1087862701c0e3f556e4a0c7ec4074a40526c73a4efflorian *
1092d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn * If a L3 cache is found, then data for it rather than the L2
1102d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn * is returned via *LLc.
111b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote */
1127862701c0e3f556e4a0c7ec4074a40526c73a4efflorianstatic Int
11338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianIntel_cache_info(Int level, VexCacheInfo *ci)
114b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote{
11594830f470f13df0fcd92bc57bdf312b4716eca31florian   UInt cpuid1_eax;
11694830f470f13df0fcd92bc57bdf312b4716eca31florian   UInt cpuid1_ignore;
1171c3e3c5f51bfea566a55024fe2ef4c1eb3d47265weidendo   Int family;
1181c3e3c5f51bfea566a55024fe2ef4c1eb3d47265weidendo   Int model;
119b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   UChar info[16];
120ad8a591c92e1003de859735c77c9474a53b90e31tom   Int   i, j, trials;
121b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
122b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   if (level < 2) {
12338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "warning: CPUID level < 2 for Intel "
12438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                    "processor (%d)\n", level);
125b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      return -1;
126b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   }
127b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
1281c3e3c5f51bfea566a55024fe2ef4c1eb3d47265weidendo   /* family/model needed to distinguish code reuse (currently 0x49) */
129ad8a591c92e1003de859735c77c9474a53b90e31tom   VG_(cpuid)(1, 0, &cpuid1_eax, &cpuid1_ignore,
1301c3e3c5f51bfea566a55024fe2ef4c1eb3d47265weidendo	      &cpuid1_ignore, &cpuid1_ignore);
1311c3e3c5f51bfea566a55024fe2ef4c1eb3d47265weidendo   family = (((cpuid1_eax >> 20) & 0xff) << 4) + ((cpuid1_eax >> 8) & 0xf);
1321c3e3c5f51bfea566a55024fe2ef4c1eb3d47265weidendo   model =  (((cpuid1_eax >> 16) & 0xf) << 4) + ((cpuid1_eax >> 4) & 0xf);
1331c3e3c5f51bfea566a55024fe2ef4c1eb3d47265weidendo
13494830f470f13df0fcd92bc57bdf312b4716eca31florian   VG_(cpuid)(2, 0, (UInt*)&info[0], (UInt*)&info[4],
13594830f470f13df0fcd92bc57bdf312b4716eca31florian                    (UInt*)&info[8], (UInt*)&info[12]);
136b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   trials  = info[0] - 1;   /* AL register - bits 0..7 of %eax */
137b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   info[0] = 0x0;           /* reset AL */
138b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
139b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   if (0 != trials) {
14038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "warning: non-zero CPUID trials for Intel "
14138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                    "processor (%d)\n", trials);
142b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      return -1;
143b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   }
144b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
14538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   ci->num_levels = 0;
14638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   ci->num_caches = 0;
14738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   ci->icaches_maintain_coherence = True;
14838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   ci->caches = NULL;
14938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
150b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   for (i = 0; i < 16; i++) {
151b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
152b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      switch (info[i]) {
153b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
154b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      case 0x0:       /* ignore zeros */
155b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote          break;
1567862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
157b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      /* TLB info, ignore */
158966b5bdf999d797ccdf924f03923a9ddb6c8dcd4weidendo      case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
159ca7cf38b6e9742dccc286d4065a07ff7f588cd88weidendo      case 0x0b:
16055b3a81eb11694b1140cad698af66ee28e03db61tom      case 0x4f: case 0x50: case 0x51: case 0x52: case 0x55:
1611e76ff5eeeb2e918b3896c3aaab83ee141e30285tom      case 0x56: case 0x57: case 0x59:
16255b3a81eb11694b1140cad698af66ee28e03db61tom      case 0x5a: case 0x5b: case 0x5c: case 0x5d:
163ca7cf38b6e9742dccc286d4065a07ff7f588cd88weidendo      case 0x76:
16455b3a81eb11694b1140cad698af66ee28e03db61tom      case 0xb0: case 0xb1: case 0xb2:
1651e76ff5eeeb2e918b3896c3aaab83ee141e30285tom      case 0xb3: case 0xb4: case 0xba: case 0xc0:
16655b3a81eb11694b1140cad698af66ee28e03db61tom      case 0xca:
1677862701c0e3f556e4a0c7ec4074a40526c73a4efflorian          break;
168b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
16938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x06: add_I1( 8, 4, 32); break;
17038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x08: add_I1(16, 4, 32); break;
17138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x09: add_I1(32, 4, 64); break;
17238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x30: add_I1(32, 8, 64); break;
173b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
17438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x0a: add_D1( 8, 2, 32); break;
17538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x0c: add_D1(16, 4, 32); break;
17638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x0d: add_D1(16, 4, 64); break;
17738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x0e: add_D1(24, 6, 64); break;
17838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x2c: add_D1(32, 8, 64); break;
179b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
180b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      /* IA-64 info -- panic! */
1817862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      case 0x10: case 0x15: case 0x1a:
182b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      case 0x88: case 0x89: case 0x8a: case 0x8d:
183b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      case 0x90: case 0x96: case 0x9b:
1847862701c0e3f556e4a0c7ec4074a40526c73a4efflorian         VG_(core_panic)("IA-64 cache detected?!");
185b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
1862d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      /* L3 cache info. */
18738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x22: add_U3(512,    4, 64); break;
18838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x23: add_U3(1024,   8, 64); break;
18938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x25: add_U3(2048,   8, 64); break;
19038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x29: add_U3(4096,   8, 64); break;
19138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x46: add_U3(4096,   4, 64); break;
19238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x47: add_U3(8192,   8, 64); break;
19338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x4a: add_U3(6144,  12, 64); break;
19438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x4b: add_U3(8192,  16, 64); break;
19538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x4c: add_U3(12288, 12, 64); break;
19638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x4d: add_U3(16384, 16, 64); break;
19738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xd0: add_U3(512,    4, 64); break;
19838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xd1: add_U3(1024,   4, 64); break;
19938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xd2: add_U3(2048,   4, 64); break;
20038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xd6: add_U3(1024,   8, 64); break;
20138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xd7: add_U3(2048,   8, 64); break;
20238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xd8: add_U3(4096,   8, 64); break;
20338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xdc: add_U3(1536,  12, 64); break;
20438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xdd: add_U3(3072,  12, 64); break;
20538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xde: add_U3(6144,  12, 64); break;
20638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xe2: add_U3(2048,  16, 64); break;
20738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xe3: add_U3(4096,  16, 64); break;
20838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xe4: add_U3(8192,  16, 64); break;
20938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xea: add_U3(12288, 24, 64); break;
21038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xeb: add_U3(18432, 24, 64); break;
21138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0xec: add_U3(24576, 24, 64); break;
212b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
21355b3a81eb11694b1140cad698af66ee28e03db61tom      /* Described as "MLC" in Intel documentation */
21438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x21: add_U2(256, 8, 64); break;
21555b3a81eb11694b1140cad698af66ee28e03db61tom
216b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      /* These are sectored, whatever that means */
21738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         // FIXME: I did not find these in the Intel docs
21838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x39: add_U2(128, 4, 64); break;
21938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x3c: add_U2(256, 4, 64); break;
220b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
2217862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      /* If a P6 core, this means "no L2 cache".
222b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote         If a P4 core, this means "no L3 cache".
223b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote         We don't know what core it is, so don't issue a warning.  To detect
224b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote         a missing L2 cache, we use 'L2_found'. */
225b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      case 0x40:
226b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote          break;
227b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
22838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x41: add_U2(  128,  4, 32); break;
22938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x42: add_U2(  256,  4, 32); break;
23038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x43: add_U2(  512,  4, 32); break;
23138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x44: add_U2( 1024,  4, 32); break;
23238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x45: add_U2( 2048,  4, 32); break;
23338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x48: add_U2( 3072, 12, 64); break;
23438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x4e: add_U2( 6144, 24, 64); break;
2351c3e3c5f51bfea566a55024fe2ef4c1eb3d47265weidendo      case 0x49:
2362d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn         if (family == 15 && model == 6) {
2372d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn            /* On Xeon MP (family F, model 6), this is for L3 */
23838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian            add_U3(4096, 16, 64);
2392d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn         } else {
24038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian	    add_U2(4096, 16, 64);
2412d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn         }
2422d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn         break;
243b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
244b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      /* These are sectored, whatever that means */
24538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x60: add_D1(16, 8, 64);  break;      /* sectored */
24638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x66: add_D1( 8, 4, 64);  break;      /* sectored */
24738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x67: add_D1(16, 4, 64);  break;      /* sectored */
24838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x68: add_D1(32, 4, 64);  break;      /* sectored */
249b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
250b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      /* HACK ALERT: Instruction trace cache -- capacity is micro-ops based.
251b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote       * conversion to byte size is a total guess;  treat the 12K and 16K
252b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote       * cases the same since the cache byte size must be a power of two for
2537862701c0e3f556e4a0c7ec4074a40526c73a4efflorian       * everything to work!.  Also guessing 32 bytes for the line size...
254b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote       */
255b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      case 0x70:    /* 12K micro-ops, 8-way */
25638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         add_I1T(12, 8);
2577862701c0e3f556e4a0c7ec4074a40526c73a4efflorian         break;
258b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      case 0x71:    /* 16K micro-ops, 8-way */
25938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         add_I1T(16, 8);
2607862701c0e3f556e4a0c7ec4074a40526c73a4efflorian         break;
261b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      case 0x72:    /* 32K micro-ops, 8-way */
26238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         add_I1T(32, 8);
2637862701c0e3f556e4a0c7ec4074a40526c73a4efflorian         break;
264b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
265f91b0a372a0d0cb4030b096337d3c1ebe26d6b30sewardj      /* not sectored, whatever that might mean */
26638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x78: add_U2(1024, 4,  64);  break;
267f91b0a372a0d0cb4030b096337d3c1ebe26d6b30sewardj
268b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      /* These are sectored, whatever that means */
26938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x79: add_U2( 128, 8,  64);  break;
27038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x7a: add_U2( 256, 8,  64);  break;
27138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x7b: add_U2( 512, 8,  64);  break;
27238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x7c: add_U2(1024, 8,  64);  break;
27338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x7d: add_U2(2048, 8,  64);  break;
27438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x7e: add_U2( 256, 8, 128);  break;
27538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x7f: add_U2( 512, 2,  64);  break;
27638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x80: add_U2( 512, 8,  64);  break;
27738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x81: add_U2( 128, 8,  32);  break;
27838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x82: add_U2( 256, 8,  32);  break;
27938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x83: add_U2( 512, 8,  32);  break;
28038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x84: add_U2(1024, 8,  32);  break;
28138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x85: add_U2(2048, 8,  32);  break;
28238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x86: add_U2( 512, 4,  64);  break;
28338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case 0x87: add_U2(1024, 8,  64);  break;
284b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
285942d9efe96b793d25cc2a647e4a06eb496b6d120tom      /* Ignore prefetch information */
286942d9efe96b793d25cc2a647e4a06eb496b6d120tom      case 0xf0: case 0xf1:
2876f74a7ef1768dd3925cc22869b4e5e24e9338d08njn         break;
288942d9efe96b793d25cc2a647e4a06eb496b6d120tom
289ad8a591c92e1003de859735c77c9474a53b90e31tom      case 0xff:
290ad8a591c92e1003de859735c77c9474a53b90e31tom         j = 0;
29194830f470f13df0fcd92bc57bdf312b4716eca31florian         VG_(cpuid)(4, j++, (UInt*)&info[0], (UInt*)&info[4],
29294830f470f13df0fcd92bc57bdf312b4716eca31florian                            (UInt*)&info[8], (UInt*)&info[12]);
293ad8a591c92e1003de859735c77c9474a53b90e31tom
294ad8a591c92e1003de859735c77c9474a53b90e31tom         while ((info[0] & 0x1f) != 0) {
295ad8a591c92e1003de859735c77c9474a53b90e31tom            UInt assoc = ((*(UInt *)&info[4] >> 22) & 0x3ff) + 1;
296ad8a591c92e1003de859735c77c9474a53b90e31tom            UInt parts = ((*(UInt *)&info[4] >> 12) & 0x3ff) + 1;
297ad8a591c92e1003de859735c77c9474a53b90e31tom            UInt line_size = (*(UInt *)&info[4] & 0x7ff) + 1;
298ad8a591c92e1003de859735c77c9474a53b90e31tom            UInt sets = *(UInt *)&info[8] + 1;
299ad8a591c92e1003de859735c77c9474a53b90e31tom
30038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian            UInt size = assoc * parts * line_size * sets / 1024;
301ad8a591c92e1003de859735c77c9474a53b90e31tom
302ad8a591c92e1003de859735c77c9474a53b90e31tom            switch ((info[0] & 0xe0) >> 5)
303ad8a591c92e1003de859735c77c9474a53b90e31tom            {
304ad8a591c92e1003de859735c77c9474a53b90e31tom            case 1:
305ad8a591c92e1003de859735c77c9474a53b90e31tom               switch (info[0] & 0x1f)
306ad8a591c92e1003de859735c77c9474a53b90e31tom               {
30738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian               case 1: add_D1(size, assoc, line_size); break;
30838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian               case 2: add_I1(size, assoc, line_size); break;
30938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian               case 3: add_U1(size, assoc, line_size); break;
3107862701c0e3f556e4a0c7ec4074a40526c73a4efflorian               default:
31138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                  VG_(debugLog)(1, "cache",
31238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                                "warning: L1 cache of unknown type ignored\n");
3137862701c0e3f556e4a0c7ec4074a40526c73a4efflorian                  break;
314ad8a591c92e1003de859735c77c9474a53b90e31tom               }
315ad8a591c92e1003de859735c77c9474a53b90e31tom               break;
316ad8a591c92e1003de859735c77c9474a53b90e31tom            case 2:
317ad8a591c92e1003de859735c77c9474a53b90e31tom               switch (info[0] & 0x1f)
318ad8a591c92e1003de859735c77c9474a53b90e31tom               {
31938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian               case 1: add_D2(size, assoc, line_size); break;
32038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian               case 2: add_I2(size, assoc, line_size); break;
32138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian               case 3: add_U2(size, assoc, line_size); break;
3227862701c0e3f556e4a0c7ec4074a40526c73a4efflorian               default:
32338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                  VG_(debugLog)(1, "cache",
32438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                                "warning: L2 cache of unknown type ignored\n");
3257862701c0e3f556e4a0c7ec4074a40526c73a4efflorian                  break;
326ad8a591c92e1003de859735c77c9474a53b90e31tom               }
327ad8a591c92e1003de859735c77c9474a53b90e31tom               break;
328ad8a591c92e1003de859735c77c9474a53b90e31tom            case 3:
329ad8a591c92e1003de859735c77c9474a53b90e31tom               switch (info[0] & 0x1f)
330ad8a591c92e1003de859735c77c9474a53b90e31tom               {
33138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian               case 1: add_D3(size, assoc, line_size); break;
33238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian               case 2: add_I3(size, assoc, line_size); break;
33338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian               case 3: add_U3(size, assoc, line_size); break;
3347862701c0e3f556e4a0c7ec4074a40526c73a4efflorian               default:
33538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                  VG_(debugLog)(1, "cache",
33638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                                "warning: L3 cache of unknown type ignored\n");
3377862701c0e3f556e4a0c7ec4074a40526c73a4efflorian                  break;
338ad8a591c92e1003de859735c77c9474a53b90e31tom               }
339ad8a591c92e1003de859735c77c9474a53b90e31tom               break;
340ad8a591c92e1003de859735c77c9474a53b90e31tom            default:
34138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian               VG_(debugLog)(1, "cache", "warning: L%u cache ignored\n",
34238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                             (info[0] & 0xe0) >> 5);
343ad8a591c92e1003de859735c77c9474a53b90e31tom               break;
344ad8a591c92e1003de859735c77c9474a53b90e31tom            }
345ad8a591c92e1003de859735c77c9474a53b90e31tom
34694830f470f13df0fcd92bc57bdf312b4716eca31florian            VG_(cpuid)(4, j++, (UInt*)&info[0], (UInt*)&info[4],
34794830f470f13df0fcd92bc57bdf312b4716eca31florian                               (UInt*)&info[8], (UInt*)&info[12]);
348ad8a591c92e1003de859735c77c9474a53b90e31tom         }
349ad8a591c92e1003de859735c77c9474a53b90e31tom         break;
350ad8a591c92e1003de859735c77c9474a53b90e31tom
351b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      default:
35238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         VG_(debugLog)(1, "cache",
35338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                       "warning: Unknown Intel cache config value (0x%x), "
35438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                       "ignoring\n", info[i]);
3556f74a7ef1768dd3925cc22869b4e5e24e9338d08njn         break;
356b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      }
357b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   }
358b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
359b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   return 0;
360b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote}
361b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
362b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote/* AMD method is straightforward, just extract appropriate bits from the
363b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote * result registers.
364b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote *
365b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote * Bits, for D1 and I1:
3667862701c0e3f556e4a0c7ec4074a40526c73a4efflorian *  31..24  data L1 cache size in KBs
3677862701c0e3f556e4a0c7ec4074a40526c73a4efflorian *  23..16  data L1 cache associativity (FFh=full)
3687862701c0e3f556e4a0c7ec4074a40526c73a4efflorian *  15.. 8  data L1 cache lines per tag
369b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote *   7.. 0  data L1 cache line size in bytes
370b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote *
371b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote * Bits, for L2:
372b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote *  31..16  unified L2 cache size in KBs
373b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote *  15..12  unified L2 cache associativity (0=off, FFh=full)
3747862701c0e3f556e4a0c7ec4074a40526c73a4efflorian *  11.. 8  unified L2 cache lines per tag
375b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote *   7.. 0  unified L2 cache line size in bytes
376b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote *
3777862701c0e3f556e4a0c7ec4074a40526c73a4efflorian * #3  The AMD K7 processor's L2 cache must be configured prior to relying
378b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote *     upon this information. (Whatever that means -- njn)
379b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote *
380b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote * Also, according to Cyrille Chepelov, Duron stepping A0 processors (model
381b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote * 0x630) have a bug and misreport their L2 size as 1KB (it's really 64KB),
382b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote * so we detect that.
3837862701c0e3f556e4a0c7ec4074a40526c73a4efflorian *
3842d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn * Returns 0 on success, non-zero on failure.  As with the Intel code
3852d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn * above, if a L3 cache is found, then data for it rather than the L2
3862d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn * is returned via *LLc.
387b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote */
3882d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn
3892d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn/* A small helper */
3907862701c0e3f556e4a0c7ec4074a40526c73a4efflorianstatic Int
3917862701c0e3f556e4a0c7ec4074a40526c73a4effloriandecode_AMD_cache_L2_L3_assoc ( Int bits_15_12 )
3922d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn{
3932d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn   /* Decode a L2/L3 associativity indication.  It is encoded
3942d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      differently from the I1/D1 associativity.  Returns 1
3952d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      (direct-map) as a safe but suboptimal result for unknown
3962d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      encodings. */
3972d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn   switch (bits_15_12 & 0xF) {
3982d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      case 1: return 1;    case 2: return 2;
3992d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      case 4: return 4;    case 6: return 8;
4002d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      case 8: return 16;   case 0xA: return 32;
4012d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      case 0xB: return 48; case 0xC: return 64;
4022d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      case 0xD: return 96; case 0xE: return 128;
4032d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      case 0xF: /* fully associative */
4042d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      case 0: /* L2/L3 cache or TLB is disabled */
4052d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      default:
4062d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn        return 1;
4072d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn   }
4082d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn}
4092d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn
4107862701c0e3f556e4a0c7ec4074a40526c73a4efflorianstatic Int
4117862701c0e3f556e4a0c7ec4074a40526c73a4efflorianAMD_cache_info(VexCacheInfo *ci)
412b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote{
413b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   UInt ext_level;
414b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   UInt dummy, model;
4152d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn   UInt I1i, D1i, L2i, L3i;
4167862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   UInt size, line_size, assoc;
4177862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
418ad8a591c92e1003de859735c77c9474a53b90e31tom   VG_(cpuid)(0x80000000, 0, &ext_level, &dummy, &dummy, &dummy);
419b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
420b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   if (0 == (ext_level & 0x80000000) || ext_level < 0x80000006) {
42138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "warning: ext_level < 0x80000006 for AMD "
42238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                    "processor (0x%x)\n", ext_level);
423b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      return -1;
424b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   }
425b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
426ad8a591c92e1003de859735c77c9474a53b90e31tom   VG_(cpuid)(0x80000005, 0, &dummy, &dummy, &D1i, &I1i);
427ad8a591c92e1003de859735c77c9474a53b90e31tom   VG_(cpuid)(0x80000006, 0, &dummy, &dummy, &L2i, &L3i);
428b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
429ad8a591c92e1003de859735c77c9474a53b90e31tom   VG_(cpuid)(0x1, 0, &model, &dummy, &dummy, &dummy);
430b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
431b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   /* Check for Duron bug */
432b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   if (model == 0x630) {
43338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "warning: Buggy Duron stepping A0. "
43438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                    "Assuming L2 size=65536 bytes\n");
435b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      L2i = (64 << 16) | (L2i & 0xffff);
436b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   }
437b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
4387862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   ci->num_levels = 2;
4397862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   ci->num_caches = 3;
4407862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   ci->icaches_maintain_coherence = True;
4417862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
4427862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   /* Check for L3 cache */
4437862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   if (((L3i >> 18) & 0x3fff) > 0) {
4447862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ci->num_levels = 3;
4457862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ci->num_caches = 4;
4467862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   }
4477862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
4487862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   ci->caches = VG_(malloc)("m_cache", ci->num_caches * sizeof *ci->caches);
4497862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
4507862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   // D1
4517862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   size      = (D1i >> 24) & 0xff;
4527862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   assoc     = (D1i >> 16) & 0xff;
4537862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   line_size = (D1i >>  0) & 0xff;
4547862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   ci->caches[0] = VEX_CACHE_INIT(DATA_CACHE, 1, size, line_size, assoc);
455b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
4567862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   // I1
4577862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   size      = (I1i >> 24) & 0xff;
4587862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   assoc     = (I1i >> 16) & 0xff;
4597862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   line_size = (I1i >>  0) & 0xff;
4607862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   ci->caches[1] = VEX_CACHE_INIT(INSN_CACHE, 1, size, line_size, assoc);
461b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
4627862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   // L2    Nb: different bits used for L2
4637862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   size      = (L2i >> 16) & 0xffff;
4647862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   assoc     = decode_AMD_cache_L2_L3_assoc((L2i >> 12) & 0xf);
4657862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   line_size = (L2i >>  0) & 0xff;
46638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   ci->caches[2] = VEX_CACHE_INIT(UNIFIED_CACHE, 2, size, line_size, assoc);
4672d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn
4687862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   // L3, if any
4692d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn   if (((L3i >> 18) & 0x3fff) > 0) {
4707862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      /* There's an L3 cache. */
4712d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn      /* NB: the test in the if is "if L3 size > 0 ".  I don't know if
4722d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn         this is the right way to test presence-vs-absence of L3.  I
4732d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn         can't see any guidance on this in the AMD documentation. */
4747862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      size      = ((L3i >> 18) & 0x3fff) * 512;
4757862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      assoc     = decode_AMD_cache_L2_L3_assoc((L3i >> 12) & 0xf);
4767862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      line_size = (L3i >>  0) & 0xff;
47738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      ci->caches[3] = VEX_CACHE_INIT(UNIFIED_CACHE, 3, size, line_size, assoc);
4782d853a1f8a153ee1ed99c5e1166d69dd4c6574d8njn   }
479b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
480b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   return 0;
481b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote}
482b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
4837862701c0e3f556e4a0c7ec4074a40526c73a4efflorianstatic Int
4847862701c0e3f556e4a0c7ec4074a40526c73a4efflorianget_caches_from_CPUID(VexCacheInfo *ci)
485b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote{
48694830f470f13df0fcd92bc57bdf312b4716eca31florian   Int  ret, i;
48794830f470f13df0fcd92bc57bdf312b4716eca31florian   UInt level;
48819f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   HChar vendor_id[13];
489b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
49038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   vg_assert(VG_(has_cpuid)());
491f4ed059f77bb9788633e02f3151335e64994ebe3tom
49294830f470f13df0fcd92bc57bdf312b4716eca31florian   VG_(cpuid)(0, 0, &level, (UInt*)&vendor_id[0],
49394830f470f13df0fcd92bc57bdf312b4716eca31florian	      (UInt*)&vendor_id[8], (UInt*)&vendor_id[4]);
494b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj   vendor_id[12] = '\0';
495b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
49638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   if (0 == level) {    // CPUID level is 0, early Pentium?
497b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      return -1;
498b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   }
499b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
500b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   /* Only handling Intel and AMD chips... no Cyrix, Transmeta, etc */
501b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   if (0 == VG_(strcmp)(vendor_id, "GenuineIntel")) {
5027862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ret = Intel_cache_info(level, ci);
503b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
504b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   } else if (0 == VG_(strcmp)(vendor_id, "AuthenticAMD")) {
5057862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ret = AMD_cache_info(ci);
506b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
507b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   } else if (0 == VG_(strcmp)(vendor_id, "CentaurHauls")) {
508b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      /* Total kludge.  Pretend to be a VIA Nehemiah. */
5097862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ci->num_levels = 2;
5107862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ci->num_caches = 3;
5117862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ci->icaches_maintain_coherence = True;
5127862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ci->caches = VG_(malloc)("m_cache", ci->num_caches * sizeof *ci->caches);
5137862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ci->caches[0] = VEX_CACHE_INIT(DATA_CACHE,    1, 64, 16, 16);
5147862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ci->caches[1] = VEX_CACHE_INIT(INSN_CACHE,    1, 64, 16,  4);
5157862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ci->caches[2] = VEX_CACHE_INIT(UNIFIED_CACHE, 2, 64, 16, 16);
5167862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
517b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      ret = 0;
518b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
519b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   } else {
52038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "CPU vendor ID not recognised (%s)\n",
52138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                    vendor_id);
522b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote      return -1;
523b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   }
524b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
525b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   /* Successful!  Convert sizes from KB to bytes */
5267862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   for (i = 0; i < ci->num_caches; ++i) {
5277862701c0e3f556e4a0c7ec4074a40526c73a4efflorian      ci->caches[i].sizeB *= 1024;
528aebbf1c8483de7ef7e5496f96ba4cb868342f439sewardj   }
529aebbf1c8483de7ef7e5496f96ba4cb868342f439sewardj
530b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote   return ret;
531b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote}
532b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
53338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianstatic Bool
53438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianget_cache_info(VexArchInfo *vai)
5357862701c0e3f556e4a0c7ec4074a40526c73a4efflorian{
5367862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   Int ret = get_caches_from_CPUID(&vai->hwcache_info);
5377862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
5387862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   return ret == 0 ? True : False;
5397862701c0e3f556e4a0c7ec4074a40526c73a4efflorian}
5407862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
541cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#elif defined(VGA_arm) || defined(VGA_ppc32)    || \
542cae0cc22b83ffb260ee8379e92099c5a701944cbcarll   defined(VGA_ppc64be) || defined(VGA_ppc64le) || \
543112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_arm64) || \
544112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   defined(VGA_tilegx)
54538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianstatic Bool
54638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianget_cache_info(VexArchInfo *vai)
547b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote{
5487862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   vai->hwcache_info.icaches_maintain_coherence = False;
5497862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
5507862701c0e3f556e4a0c7ec4074a40526c73a4efflorian   return False;   // not yet
551b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote}
552b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote
5537862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#elif defined(VGA_s390x)
5547862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
555fb11d9736384835f3dfe0e627810048c22c5776dflorianstatic ULong
556fb11d9736384835f3dfe0e627810048c22c5776dflorianecag(UInt ai, UInt li, UInt ti)
557fb11d9736384835f3dfe0e627810048c22c5776dflorian{
558fb11d9736384835f3dfe0e627810048c22c5776dflorian   register ULong result asm("2") = 0;
559fb11d9736384835f3dfe0e627810048c22c5776dflorian   register ULong input  asm("3") = (ai << 4) | (li << 1) | ti;
560fb11d9736384835f3dfe0e627810048c22c5776dflorian
561fb11d9736384835f3dfe0e627810048c22c5776dflorian   asm volatile(".short 0xeb20\n\t"
562fb11d9736384835f3dfe0e627810048c22c5776dflorian                ".long  0x3000004c\n\t"
563fb11d9736384835f3dfe0e627810048c22c5776dflorian                 : "=d" (result) : "d" (input));
564fb11d9736384835f3dfe0e627810048c22c5776dflorian
565fb11d9736384835f3dfe0e627810048c22c5776dflorian   return result;
566fb11d9736384835f3dfe0e627810048c22c5776dflorian}
567fb11d9736384835f3dfe0e627810048c22c5776dflorian
568fb11d9736384835f3dfe0e627810048c22c5776dflorianstatic UInt
569fb11d9736384835f3dfe0e627810048c22c5776dflorianget_cache_info_for_level(ULong topology, UInt level)
570fb11d9736384835f3dfe0e627810048c22c5776dflorian{
571fb11d9736384835f3dfe0e627810048c22c5776dflorian   return (topology >> (56 - level * 8)) & 0xff;
572fb11d9736384835f3dfe0e627810048c22c5776dflorian}
573fb11d9736384835f3dfe0e627810048c22c5776dflorian
574fb11d9736384835f3dfe0e627810048c22c5776dflorianstatic ULong
575fb11d9736384835f3dfe0e627810048c22c5776dflorianget_line_size(UInt level, Bool is_insn_cache)
576fb11d9736384835f3dfe0e627810048c22c5776dflorian{
577fb11d9736384835f3dfe0e627810048c22c5776dflorian   return ecag(1, level, is_insn_cache);
578fb11d9736384835f3dfe0e627810048c22c5776dflorian}
579fb11d9736384835f3dfe0e627810048c22c5776dflorian
580fb11d9736384835f3dfe0e627810048c22c5776dflorianstatic ULong
581fb11d9736384835f3dfe0e627810048c22c5776dflorianget_total_size(UInt level, Bool is_insn_cache)
582fb11d9736384835f3dfe0e627810048c22c5776dflorian{
583fb11d9736384835f3dfe0e627810048c22c5776dflorian   return ecag(2, level, is_insn_cache);
584fb11d9736384835f3dfe0e627810048c22c5776dflorian}
585fb11d9736384835f3dfe0e627810048c22c5776dflorian
586fb11d9736384835f3dfe0e627810048c22c5776dflorianstatic ULong
587fb11d9736384835f3dfe0e627810048c22c5776dflorianget_associativity(UInt level, Bool is_insn_cache)
588fb11d9736384835f3dfe0e627810048c22c5776dflorian{
589fb11d9736384835f3dfe0e627810048c22c5776dflorian   return ecag(3, level, is_insn_cache);
590fb11d9736384835f3dfe0e627810048c22c5776dflorian}
591fb11d9736384835f3dfe0e627810048c22c5776dflorian
592fb11d9736384835f3dfe0e627810048c22c5776dflorianstatic VexCache
593fb11d9736384835f3dfe0e627810048c22c5776dflorianget_cache(UInt level, VexCacheKind kind)
594fb11d9736384835f3dfe0e627810048c22c5776dflorian{
595fb11d9736384835f3dfe0e627810048c22c5776dflorian   Bool is_insn_cache = kind == INSN_CACHE;
596fb11d9736384835f3dfe0e627810048c22c5776dflorian   UInt size = get_total_size(level, is_insn_cache);
597fb11d9736384835f3dfe0e627810048c22c5776dflorian   UInt line_size = get_line_size(level, is_insn_cache);
598fb11d9736384835f3dfe0e627810048c22c5776dflorian   UInt assoc = get_associativity(level, is_insn_cache);
599fb11d9736384835f3dfe0e627810048c22c5776dflorian
600fb11d9736384835f3dfe0e627810048c22c5776dflorian   return VEX_CACHE_INIT(kind, level + 1, size, line_size, assoc);
601fb11d9736384835f3dfe0e627810048c22c5776dflorian}
602fb11d9736384835f3dfe0e627810048c22c5776dflorian
60338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianstatic Bool
60438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianget_cache_info(VexArchInfo *vai)
6057862701c0e3f556e4a0c7ec4074a40526c73a4efflorian{
606fb11d9736384835f3dfe0e627810048c22c5776dflorian   VexCacheInfo *ci = &vai->hwcache_info;
6077862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
608fb11d9736384835f3dfe0e627810048c22c5776dflorian   ci->icaches_maintain_coherence = True;
609fb11d9736384835f3dfe0e627810048c22c5776dflorian
61033332a36b6eba9494a7e8ce7837883379bfb5e53florian   if (! (vai->hwcaps & VEX_HWCAPS_S390X_GIE)) {
611fb11d9736384835f3dfe0e627810048c22c5776dflorian      // ECAG is not available
612fb11d9736384835f3dfe0e627810048c22c5776dflorian      return False;
613fb11d9736384835f3dfe0e627810048c22c5776dflorian   }
614fb11d9736384835f3dfe0e627810048c22c5776dflorian
615fb11d9736384835f3dfe0e627810048c22c5776dflorian   UInt level, cache_kind, info, i;
616fb11d9736384835f3dfe0e627810048c22c5776dflorian   ULong topology = ecag(0, 0, 0);   // get summary
617fb11d9736384835f3dfe0e627810048c22c5776dflorian
618fb11d9736384835f3dfe0e627810048c22c5776dflorian   /* ECAG supports at most 8 levels of cache. Find out how many levels
619fb11d9736384835f3dfe0e627810048c22c5776dflorian      of cache and how many caches there are. */
620fb11d9736384835f3dfe0e627810048c22c5776dflorian   ci->num_levels = 0;
621fb11d9736384835f3dfe0e627810048c22c5776dflorian   ci->num_caches = 0;
622fb11d9736384835f3dfe0e627810048c22c5776dflorian   for (level = 0; level < 8; level++) {
623fb11d9736384835f3dfe0e627810048c22c5776dflorian      info = get_cache_info_for_level(topology, level);
624fb11d9736384835f3dfe0e627810048c22c5776dflorian
625fb11d9736384835f3dfe0e627810048c22c5776dflorian      if ((info & 0xc) == 0) break;  // cache does not exist at this level
626fb11d9736384835f3dfe0e627810048c22c5776dflorian      ++ci->num_levels;
627fb11d9736384835f3dfe0e627810048c22c5776dflorian
628fb11d9736384835f3dfe0e627810048c22c5776dflorian      cache_kind = info & 0x3;
629fb11d9736384835f3dfe0e627810048c22c5776dflorian      switch (cache_kind) {
630fb11d9736384835f3dfe0e627810048c22c5776dflorian      case 0:  ci->num_caches += 2; break; /* separate data and insn cache */
631fb11d9736384835f3dfe0e627810048c22c5776dflorian      case 1:  ci->num_caches += 1; break; /* only insn cache */
632fb11d9736384835f3dfe0e627810048c22c5776dflorian      case 2:  ci->num_caches += 1; break; /* only data cache */
633fb11d9736384835f3dfe0e627810048c22c5776dflorian      case 3:  ci->num_caches += 1; break; /* unified data and insn cache */
634fb11d9736384835f3dfe0e627810048c22c5776dflorian      }
635fb11d9736384835f3dfe0e627810048c22c5776dflorian   }
636fb11d9736384835f3dfe0e627810048c22c5776dflorian
637fb11d9736384835f3dfe0e627810048c22c5776dflorian   ci->caches = VG_(malloc)("m_cache", ci->num_caches * sizeof *ci->caches);
638fb11d9736384835f3dfe0e627810048c22c5776dflorian
639fb11d9736384835f3dfe0e627810048c22c5776dflorian   i = 0;
640fb11d9736384835f3dfe0e627810048c22c5776dflorian   for (level = 0; level < ci->num_levels; level++) {
641fb11d9736384835f3dfe0e627810048c22c5776dflorian      info = get_cache_info_for_level(topology, level);
642fb11d9736384835f3dfe0e627810048c22c5776dflorian      cache_kind = info & 0x3;
643fb11d9736384835f3dfe0e627810048c22c5776dflorian      switch (cache_kind) {
644fb11d9736384835f3dfe0e627810048c22c5776dflorian      case 0:   /* separate data and insn cache */
645fb11d9736384835f3dfe0e627810048c22c5776dflorian         ci->caches[i++] = get_cache(level, INSN_CACHE);
646fb11d9736384835f3dfe0e627810048c22c5776dflorian         ci->caches[i++] = get_cache(level, DATA_CACHE);
647fb11d9736384835f3dfe0e627810048c22c5776dflorian         break;
648fb11d9736384835f3dfe0e627810048c22c5776dflorian
649fb11d9736384835f3dfe0e627810048c22c5776dflorian      case 1:   /* only insn cache */
650fb11d9736384835f3dfe0e627810048c22c5776dflorian         ci->caches[i++] = get_cache(level, INSN_CACHE);
651fb11d9736384835f3dfe0e627810048c22c5776dflorian         break;
652fb11d9736384835f3dfe0e627810048c22c5776dflorian
653fb11d9736384835f3dfe0e627810048c22c5776dflorian      case 2:   /* only data cache */
654fb11d9736384835f3dfe0e627810048c22c5776dflorian         ci->caches[i++] = get_cache(level, DATA_CACHE);
655fb11d9736384835f3dfe0e627810048c22c5776dflorian         break;
656fb11d9736384835f3dfe0e627810048c22c5776dflorian
657fb11d9736384835f3dfe0e627810048c22c5776dflorian      case 3:   /* unified data and insn cache */
658fb11d9736384835f3dfe0e627810048c22c5776dflorian         ci->caches[i++] = get_cache(level, UNIFIED_CACHE);
659fb11d9736384835f3dfe0e627810048c22c5776dflorian         break;
660fb11d9736384835f3dfe0e627810048c22c5776dflorian      }
661fb11d9736384835f3dfe0e627810048c22c5776dflorian   }
662fb11d9736384835f3dfe0e627810048c22c5776dflorian   return True;
6637862701c0e3f556e4a0c7ec4074a40526c73a4efflorian}
6647862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
6657862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#else
6667862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
6677862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#error "Unknown arch"
6687862701c0e3f556e4a0c7ec4074a40526c73a4efflorian
6697862701c0e3f556e4a0c7ec4074a40526c73a4efflorian#endif
6708b68b64759254d514d98328c496cbd88cde4c9a5njn
67138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian/* Debug information */
67238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianstatic void
67338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianwrite_cache_info(const VexCacheInfo *ci)
67438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian{
67538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   UInt i;
67638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
67738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   VG_(debugLog)(1, "cache", "Cache info:\n");
67838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   VG_(debugLog)(1, "cache", "  #levels = %u\n", ci->num_levels);
67938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   VG_(debugLog)(1, "cache", "  #caches = %u\n", ci->num_caches);
68038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   for (i = 0; i < ci->num_caches; ++i) {
68138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VexCache *c = ci->caches + i;
68238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      const HChar *kind;
68338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "     cache #%u:\n", i);
68438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      switch (c->kind) {
68538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case INSN_CACHE:    kind = "insn";    break;
68638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case DATA_CACHE:    kind = "data";    break;
68738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      case UNIFIED_CACHE: kind = "unified"; break;
68838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      default: kind = "unknown"; break;
68938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      }
69038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "        kind = %s\n", kind);
69138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "        level = %u\n", c->level);
69238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "        size = %u bytes\n", c->sizeB);
69338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "        linesize = %u bytes\n", c->line_sizeB);
69438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(debugLog)(1, "cache", "        assoc = %u\n", c->assoc);
69538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   }
69638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian}
69738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
69838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianstatic Bool
69938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90floriancache_info_is_sensible(const VexCacheInfo *ci)
70038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian{
70138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   UInt level, i;
70238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   Bool sensible = True;
70338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
70438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   /* There must be at most one cache of a given kind at the same level.
70538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      If there is a unified cache at a given level, no other cache may
70638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      exist at that level. */
70738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   for (level = 1; level <= ci->num_levels; ++level) {
70838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      UInt num_icache, num_dcache, num_ucache;
70938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
71038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      num_icache = num_dcache = num_ucache = 0;
71138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      for (i = 0; i < ci->num_caches; ++i) {
71238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         if (ci->caches[i].level == level) {
71338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian            switch (ci->caches[i].kind) {
71438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian            case INSN_CACHE:    ++num_icache; break;
71538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian            case DATA_CACHE:    ++num_dcache; break;
71638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian            case UNIFIED_CACHE: ++num_ucache; break;
71738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian            }
71838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         }
71938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      }
72038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      if (num_icache == 0 && num_dcache == 0 && num_ucache == 0) {
72138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         VG_(debugLog)(1, "cache", "warning: No caches at level %u\n", level);
72238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         sensible = False;
72338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      }
72438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      if (num_icache > 1 || num_dcache > 1 || num_ucache > 1) {
72538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         VG_(debugLog)(1, "cache", "warning: More than one cache of a given "
72638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                       "kind at level %u\n", level);
72738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         sensible = False;
72838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      }
72938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      if (num_ucache != 0 && (num_icache > 0 || num_dcache > 0)) {
73038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         VG_(debugLog)(1, "cache", "warning: Unified cache and I/D cache "
73138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                       "at level %u\n", level);
73238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         sensible = False;
73338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      }
73438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   }
73538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
73638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   /* If there is a cache at level N > 1 there must be a cache at level N-1 */
73738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   for (level = 2; level <= ci->num_levels; ++level) {
73838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      Bool found = False;
73938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      for (i = 0; i < ci->num_caches; ++i) {
74038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         if (ci->caches[i].level == level - 1) {
74138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian            found = True;
74238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian            break;
74338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         }
74438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      }
74538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      if (! found) {
74638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         VG_(debugLog)(1, "cache", "warning: Cache at level %u but no cache "
74738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian                       "at level %u\n", level, level - 1);
74838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian         sensible = False;
74938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      }
75038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   }
75138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
75238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   return sensible;
75338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian}
75438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
75538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
75638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian/* Autodetect the cache information for this host and stuff it into
75738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   VexArchInfo::hwcache_info. Return True if successful. */
75838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianBool
75938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florianVG_(machine_get_cache_info)(VexArchInfo *vai)
76038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian{
76138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   Bool ok = get_cache_info(vai);
76238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
763b7058da8e033c572a5043c66660a98e0c6fec7bbflorian   VexCacheInfo *ci = &vai->hwcache_info;
76494830f470f13df0fcd92bc57bdf312b4716eca31florian
76538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   if (! ok) {
766b7058da8e033c572a5043c66660a98e0c6fec7bbflorian      VG_(debugLog)(1, "cache", "Could not autodetect cache info\n");
767b7058da8e033c572a5043c66660a98e0c6fec7bbflorian   } else {
768b7058da8e033c572a5043c66660a98e0c6fec7bbflorian      ok = cache_info_is_sensible(ci);
76938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
770b7058da8e033c572a5043c66660a98e0c6fec7bbflorian      if (! ok) {
771b7058da8e033c572a5043c66660a98e0c6fec7bbflorian         VG_(debugLog)(1, "cache",
772b7058da8e033c572a5043c66660a98e0c6fec7bbflorian                       "Autodetected cache info is not sensible\n");
773b7058da8e033c572a5043c66660a98e0c6fec7bbflorian      } else {
774b7058da8e033c572a5043c66660a98e0c6fec7bbflorian         VG_(debugLog)(1, "cache",
775b7058da8e033c572a5043c66660a98e0c6fec7bbflorian                       "Autodetected cache info is sensible\n");
776b7058da8e033c572a5043c66660a98e0c6fec7bbflorian      }
77738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      write_cache_info(ci);  /* write out for debugging */
778b7058da8e033c572a5043c66660a98e0c6fec7bbflorian   }
77938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
780b7058da8e033c572a5043c66660a98e0c6fec7bbflorian   if (! ok ) {
78138aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      /* Reset cache info */
78238aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      ci->num_levels = 0;
78338aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      ci->num_caches = 0;
78438aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      VG_(free)(ci->caches);
78538aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian      ci->caches = NULL;
78638aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   }
78738aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
78838aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian   return ok;
78938aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian}
79038aeb9ff6ef22dbfd2fe3040c80de932c9a31b90florian
791b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote/*--------------------------------------------------------------------*/
792b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote/*--- end                                                          ---*/
793b35a8b9024e9bfb4166bc01698710e0af1a0bad9nethercote/*--------------------------------------------------------------------*/
794