1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* -*- mode: C; c-basic-offset: 3; -*- */ 2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/ 4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- Cache-related stuff. m_cache.c ---*/ 5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/ 6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* 8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov This file is part of Valgrind, a dynamic binary instrumentation 9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov framework. 10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2002-2013 Nicholas Nethercote 12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov njn@valgrind.org 13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov This program is free software; you can redistribute it and/or 15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov modify it under the terms of the GNU General Public License as 16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov published by the Free Software Foundation; either version 2 of the 17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov License, or (at your option) any later version. 18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov This program is distributed in the hope that it will be useful, but 20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov WITHOUT ANY WARRANTY; without even the implied warranty of 21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov General Public License for more details. 23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov You should have received a copy of the GNU General Public License 25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov along with this program; if not, write to the Free Software 26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 02111-1307, USA. 28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov The GNU General Public License is contained in the file COPYING. 30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/ 31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_basics.h" 33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcbase.h" 34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcassert.h" 35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcprint.h" 36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_mallocfree.h" 37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_machine.h" 38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_debuglog.h" 39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "libvex.h" 40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if defined(VGA_x86) || defined(VGA_amd64) 42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_cpuid.h" 44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// All CPUID info taken from sandpile.org/ia32/cpuid.htm */ 46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Probably only works for Intel and AMD chips, and probably only for some of 47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// them. 48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void 50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovadd_cache(VexCacheInfo *ci, VexCache cache) 51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static UInt num_allocated = 0; 53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (ci->num_caches == num_allocated) { 55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov num_allocated += 6; 56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches = VG_(realloc)("m_cache", ci->caches, 57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov num_allocated * sizeof *ci->caches); 58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (ci->num_levels < cache.level) ci->num_levels = cache.level; 61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[ci->num_caches++] = cache; 62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Convenience macros */ 65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_icache(level, size, assoc, linesize) \ 66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do { \ 67436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_cache(ci, \ 68436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VEX_CACHE_INIT(INSN_CACHE, level, size, linesize, assoc)); \ 69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } while (0) 70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_dcache(level, size, assoc, linesize) \ 72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do { \ 73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_cache(ci, \ 74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VEX_CACHE_INIT(DATA_CACHE, level, size, linesize, assoc)); \ 75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } while (0) 76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_ucache(level, size, assoc, linesize) \ 78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do { \ 79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_cache(ci, \ 80436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VEX_CACHE_INIT(UNIFIED_CACHE, level, size, linesize, assoc)); \ 81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } while (0) 82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_itcache(level, size, assoc) \ 84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do { \ 85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexCache c = \ 86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VEX_CACHE_INIT(INSN_CACHE, level, size, 0, assoc); \ 87436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov c.is_trace_cache = True; \ 88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_cache(ci, c); \ 89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } while (0) 90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_I1(size, assoc, linesize) add_icache(1, size, assoc, linesize) 92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_D1(size, assoc, linesize) add_dcache(1, size, assoc, linesize) 93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_U1(size, assoc, linesize) add_ucache(1, size, assoc, linesize) 94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_I2(size, assoc, linesize) add_icache(2, size, assoc, linesize) 95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_D2(size, assoc, linesize) add_dcache(2, size, assoc, linesize) 96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_U2(size, assoc, linesize) add_ucache(2, size, assoc, linesize) 97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_I3(size, assoc, linesize) add_icache(3, size, assoc, linesize) 98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_D3(size, assoc, linesize) add_dcache(3, size, assoc, linesize) 99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_U3(size, assoc, linesize) add_ucache(3, size, assoc, linesize) 100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define add_I1T(size, assoc) \ 102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_itcache(1, size, assoc) 103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Intel method is truly wretched. We have to do an insane indexing into an 105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * array of pre-defined configurations for various parts of the memory 106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * hierarchy. 107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * According to Intel Processor Identification, App Note 485. 108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * If a L3 cache is found, then data for it rather than the L2 110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * is returned via *LLc. 111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Int 113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIntel_cache_info(Int level, VexCacheInfo *ci) 114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt cpuid1_eax; 116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt cpuid1_ignore; 117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int family; 118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int model; 119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar info[16]; 120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int i, j, trials; 121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (level < 2) { 123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "warning: CPUID level < 2 for Intel " 124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "processor (%d)\n", level); 125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return -1; 126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* family/model needed to distinguish code reuse (currently 0x49) */ 129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(cpuid)(1, 0, &cpuid1_eax, &cpuid1_ignore, 130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov &cpuid1_ignore, &cpuid1_ignore); 131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov family = (((cpuid1_eax >> 20) & 0xff) << 4) + ((cpuid1_eax >> 8) & 0xf); 132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov model = (((cpuid1_eax >> 16) & 0xf) << 4) + ((cpuid1_eax >> 4) & 0xf); 133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(cpuid)(2, 0, (UInt*)&info[0], (UInt*)&info[4], 135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (UInt*)&info[8], (UInt*)&info[12]); 136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov trials = info[0] - 1; /* AL register - bits 0..7 of %eax */ 137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov info[0] = 0x0; /* reset AL */ 138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0 != trials) { 140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "warning: non-zero CPUID trials for Intel " 141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "processor (%d)\n", trials); 142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return -1; 143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_levels = 0; 146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_caches = 0; 147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->icaches_maintain_coherence = True; 148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches = NULL; 149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < 16; i++) { 151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (info[i]) { 153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x0: /* ignore zeros */ 155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* TLB info, ignore */ 158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: 159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x0b: 160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x4f: case 0x50: case 0x51: case 0x52: case 0x55: 161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x56: case 0x57: case 0x59: 162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x5a: case 0x5b: case 0x5c: case 0x5d: 163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x76: 164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xb0: case 0xb1: case 0xb2: 165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xb3: case 0xb4: case 0xba: case 0xc0: 166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xca: 167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x06: add_I1( 8, 4, 32); break; 170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x08: add_I1(16, 4, 32); break; 171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x09: add_I1(32, 4, 64); break; 172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x30: add_I1(32, 8, 64); break; 173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x0a: add_D1( 8, 2, 32); break; 175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x0c: add_D1(16, 4, 32); break; 176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x0d: add_D1(16, 4, 64); break; 177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x0e: add_D1(24, 6, 64); break; 178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x2c: add_D1(32, 8, 64); break; 179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* IA-64 info -- panic! */ 181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x10: case 0x15: case 0x1a: 182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x88: case 0x89: case 0x8a: case 0x8d: 183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x90: case 0x96: case 0x9b: 184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(core_panic)("IA-64 cache detected?!"); 185436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* L3 cache info. */ 187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x22: add_U3(512, 4, 64); break; 188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x23: add_U3(1024, 8, 64); break; 189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x25: add_U3(2048, 8, 64); break; 190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x29: add_U3(4096, 8, 64); break; 191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x46: add_U3(4096, 4, 64); break; 192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x47: add_U3(8192, 8, 64); break; 193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x4a: add_U3(6144, 12, 64); break; 194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x4b: add_U3(8192, 16, 64); break; 195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x4c: add_U3(12288, 12, 64); break; 196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x4d: add_U3(16384, 16, 64); break; 197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xd0: add_U3(512, 4, 64); break; 198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xd1: add_U3(1024, 4, 64); break; 199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xd2: add_U3(2048, 4, 64); break; 200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xd6: add_U3(1024, 8, 64); break; 201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xd7: add_U3(2048, 8, 64); break; 202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xd8: add_U3(4096, 8, 64); break; 203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xdc: add_U3(1536, 12, 64); break; 204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xdd: add_U3(3072, 12, 64); break; 205436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xde: add_U3(6144, 12, 64); break; 206436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xe2: add_U3(2048, 16, 64); break; 207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xe3: add_U3(4096, 16, 64); break; 208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xe4: add_U3(8192, 16, 64); break; 209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xea: add_U3(12288, 24, 64); break; 210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xeb: add_U3(18432, 24, 64); break; 211436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xec: add_U3(24576, 24, 64); break; 212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Described as "MLC" in Intel documentation */ 214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x21: add_U2(256, 8, 64); break; 215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* These are sectored, whatever that means */ 217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // FIXME: I did not find these in the Intel docs 218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x39: add_U2(128, 4, 64); break; 219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x3c: add_U2(256, 4, 64); break; 220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* If a P6 core, this means "no L2 cache". 222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov If a P4 core, this means "no L3 cache". 223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov We don't know what core it is, so don't issue a warning. To detect 224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov a missing L2 cache, we use 'L2_found'. */ 225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x40: 226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x41: add_U2( 128, 4, 32); break; 229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x42: add_U2( 256, 4, 32); break; 230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x43: add_U2( 512, 4, 32); break; 231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x44: add_U2( 1024, 4, 32); break; 232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x45: add_U2( 2048, 4, 32); break; 233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x48: add_U2( 3072, 12, 64); break; 234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x4e: add_U2( 6144, 24, 64); break; 235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x49: 236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (family == 15 && model == 6) { 237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* On Xeon MP (family F, model 6), this is for L3 */ 238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_U3(4096, 16, 64); 239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_U2(4096, 16, 64); 241436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* These are sectored, whatever that means */ 245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x60: add_D1(16, 8, 64); break; /* sectored */ 246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x66: add_D1( 8, 4, 64); break; /* sectored */ 247436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x67: add_D1(16, 4, 64); break; /* sectored */ 248436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x68: add_D1(32, 4, 64); break; /* sectored */ 249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 250436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* HACK ALERT: Instruction trace cache -- capacity is micro-ops based. 251436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * conversion to byte size is a total guess; treat the 12K and 16K 252436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * cases the same since the cache byte size must be a power of two for 253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * everything to work!. Also guessing 32 bytes for the line size... 254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x70: /* 12K micro-ops, 8-way */ 256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_I1T(12, 8); 257436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x71: /* 16K micro-ops, 8-way */ 259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_I1T(16, 8); 260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x72: /* 32K micro-ops, 8-way */ 262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_I1T(32, 8); 263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 264436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* not sectored, whatever that might mean */ 266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x78: add_U2(1024, 4, 64); break; 267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* These are sectored, whatever that means */ 269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x79: add_U2( 128, 8, 64); break; 270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x7a: add_U2( 256, 8, 64); break; 271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x7b: add_U2( 512, 8, 64); break; 272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x7c: add_U2(1024, 8, 64); break; 273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x7d: add_U2(2048, 8, 64); break; 274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x7e: add_U2( 256, 8, 128); break; 275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x7f: add_U2( 512, 2, 64); break; 276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x80: add_U2( 512, 8, 64); break; 277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x81: add_U2( 128, 8, 32); break; 278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x82: add_U2( 256, 8, 32); break; 279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x83: add_U2( 512, 8, 32); break; 280436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x84: add_U2(1024, 8, 32); break; 281436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x85: add_U2(2048, 8, 32); break; 282436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x86: add_U2( 512, 4, 64); break; 283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0x87: add_U2(1024, 8, 64); break; 284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 285436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Ignore prefetch information */ 286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xf0: case 0xf1: 287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xff: 290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov j = 0; 291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(cpuid)(4, j++, (UInt*)&info[0], (UInt*)&info[4], 292436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (UInt*)&info[8], (UInt*)&info[12]); 293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov while ((info[0] & 0x1f) != 0) { 295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt assoc = ((*(UInt *)&info[4] >> 22) & 0x3ff) + 1; 296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt parts = ((*(UInt *)&info[4] >> 12) & 0x3ff) + 1; 297436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt line_size = (*(UInt *)&info[4] & 0x7ff) + 1; 298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt sets = *(UInt *)&info[8] + 1; 299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 300436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt size = assoc * parts * line_size * sets / 1024; 301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch ((info[0] & 0xe0) >> 5) 303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { 304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 1: 305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (info[0] & 0x1f) 306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { 307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 1: add_D1(size, assoc, line_size); break; 308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 2: add_I1(size, assoc, line_size); break; 309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 3: add_U1(size, assoc, line_size); break; 310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", 312436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "warning: L1 cache of unknown type ignored\n"); 313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 2: 317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (info[0] & 0x1f) 318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { 319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 1: add_D2(size, assoc, line_size); break; 320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 2: add_I2(size, assoc, line_size); break; 321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 3: add_U2(size, assoc, line_size); break; 322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", 324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "warning: L2 cache of unknown type ignored\n"); 325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 3: 329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (info[0] & 0x1f) 330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { 331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 1: add_D3(size, assoc, line_size); break; 332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 2: add_I3(size, assoc, line_size); break; 333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 3: add_U3(size, assoc, line_size); break; 334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", 336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "warning: L3 cache of unknown type ignored\n"); 337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "warning: L%u cache ignored\n", 342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (info[0] & 0xe0) >> 5); 343436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 344436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 345436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(cpuid)(4, j++, (UInt*)&info[0], (UInt*)&info[4], 347436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (UInt*)&info[8], (UInt*)&info[12]); 348436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 350436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", 353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "warning: Unknown Intel cache config value (0x%x), " 354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "ignoring\n", info[i]); 355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 358436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 359436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return 0; 360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* AMD method is straightforward, just extract appropriate bits from the 363436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * result registers. 364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Bits, for D1 and I1: 366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 31..24 data L1 cache size in KBs 367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 23..16 data L1 cache associativity (FFh=full) 368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 15.. 8 data L1 cache lines per tag 369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 7.. 0 data L1 cache line size in bytes 370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Bits, for L2: 372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 31..16 unified L2 cache size in KBs 373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 15..12 unified L2 cache associativity (0=off, FFh=full) 374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 11.. 8 unified L2 cache lines per tag 375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 7.. 0 unified L2 cache line size in bytes 376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * #3 The AMD K7 processor's L2 cache must be configured prior to relying 378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * upon this information. (Whatever that means -- njn) 379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Also, according to Cyrille Chepelov, Duron stepping A0 processors (model 381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 0x630) have a bug and misreport their L2 size as 1KB (it's really 64KB), 382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * so we detect that. 383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Returns 0 on success, non-zero on failure. As with the Intel code 385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * above, if a L3 cache is found, then data for it rather than the L2 386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * is returned via *LLc. 387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* A small helper */ 390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Int 391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovdecode_AMD_cache_L2_L3_assoc ( Int bits_15_12 ) 392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Decode a L2/L3 associativity indication. It is encoded 394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov differently from the I1/D1 associativity. Returns 1 395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (direct-map) as a safe but suboptimal result for unknown 396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov encodings. */ 397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (bits_15_12 & 0xF) { 398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 1: return 1; case 2: return 2; 399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 4: return 4; case 6: return 8; 400436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 8: return 16; case 0xA: return 32; 401436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xB: return 48; case 0xC: return 64; 402436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xD: return 96; case 0xE: return 128; 403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0xF: /* fully associative */ 404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0: /* L2/L3 cache or TLB is disabled */ 405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 406436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return 1; 407436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 409436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 410436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Int 411436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovAMD_cache_info(VexCacheInfo *ci) 412436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 413436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt ext_level; 414436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt dummy, model; 415436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt I1i, D1i, L2i, L3i; 416436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt size, line_size, assoc; 417436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 418436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(cpuid)(0x80000000, 0, &ext_level, &dummy, &dummy, &dummy); 419436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 420436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0 == (ext_level & 0x80000000) || ext_level < 0x80000006) { 421436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "warning: ext_level < 0x80000006 for AMD " 422436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "processor (0x%x)\n", ext_level); 423436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return -1; 424436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 425436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 426436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(cpuid)(0x80000005, 0, &dummy, &dummy, &D1i, &I1i); 427436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(cpuid)(0x80000006, 0, &dummy, &dummy, &L2i, &L3i); 428436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 429436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(cpuid)(0x1, 0, &model, &dummy, &dummy, &dummy); 430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 431436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Check for Duron bug */ 432436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (model == 0x630) { 433436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "warning: Buggy Duron stepping A0. " 434436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "Assuming L2 size=65536 bytes\n"); 435436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov L2i = (64 << 16) | (L2i & 0xffff); 436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 438436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_levels = 2; 439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_caches = 3; 440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->icaches_maintain_coherence = True; 441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Check for L3 cache */ 443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (((L3i >> 18) & 0x3fff) > 0) { 444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_levels = 3; 445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_caches = 4; 446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches = VG_(malloc)("m_cache", ci->num_caches * sizeof *ci->caches); 449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // D1 451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov size = (D1i >> 24) & 0xff; 452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assoc = (D1i >> 16) & 0xff; 453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov line_size = (D1i >> 0) & 0xff; 454436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[0] = VEX_CACHE_INIT(DATA_CACHE, 1, size, line_size, assoc); 455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 456436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // I1 457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov size = (I1i >> 24) & 0xff; 458436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assoc = (I1i >> 16) & 0xff; 459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov line_size = (I1i >> 0) & 0xff; 460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[1] = VEX_CACHE_INIT(INSN_CACHE, 1, size, line_size, assoc); 461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // L2 Nb: different bits used for L2 463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov size = (L2i >> 16) & 0xffff; 464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assoc = decode_AMD_cache_L2_L3_assoc((L2i >> 12) & 0xf); 465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov line_size = (L2i >> 0) & 0xff; 466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[2] = VEX_CACHE_INIT(UNIFIED_CACHE, 2, size, line_size, assoc); 467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // L3, if any 469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (((L3i >> 18) & 0x3fff) > 0) { 470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* There's an L3 cache. */ 471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* NB: the test in the if is "if L3 size > 0 ". I don't know if 472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov this is the right way to test presence-vs-absence of L3. I 473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov can't see any guidance on this in the AMD documentation. */ 474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov size = ((L3i >> 18) & 0x3fff) * 512; 475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assoc = decode_AMD_cache_L2_L3_assoc((L3i >> 12) & 0xf); 476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov line_size = (L3i >> 0) & 0xff; 477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[3] = VEX_CACHE_INIT(UNIFIED_CACHE, 3, size, line_size, assoc); 478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 480436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return 0; 481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 483436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Int 484436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovget_caches_from_CPUID(VexCacheInfo *ci) 485436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int ret, i; 487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt level; 488436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar vendor_id[13]; 489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 490436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_(has_cpuid)()); 491436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 492436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(cpuid)(0, 0, &level, (UInt*)&vendor_id[0], 493436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (UInt*)&vendor_id[8], (UInt*)&vendor_id[4]); 494436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vendor_id[12] = '\0'; 495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 496436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0 == level) { // CPUID level is 0, early Pentium? 497436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return -1; 498436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Only handling Intel and AMD chips... no Cyrix, Transmeta, etc */ 501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0 == VG_(strcmp)(vendor_id, "GenuineIntel")) { 502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ret = Intel_cache_info(level, ci); 503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else if (0 == VG_(strcmp)(vendor_id, "AuthenticAMD")) { 505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ret = AMD_cache_info(ci); 506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else if (0 == VG_(strcmp)(vendor_id, "CentaurHauls")) { 508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Total kludge. Pretend to be a VIA Nehemiah. */ 509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_levels = 2; 510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_caches = 3; 511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->icaches_maintain_coherence = True; 512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches = VG_(malloc)("m_cache", ci->num_caches * sizeof *ci->caches); 513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[0] = VEX_CACHE_INIT(DATA_CACHE, 1, 64, 16, 16); 514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[1] = VEX_CACHE_INIT(INSN_CACHE, 1, 64, 16, 4); 515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[2] = VEX_CACHE_INIT(UNIFIED_CACHE, 2, 64, 16, 16); 516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ret = 0; 518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "CPU vendor ID not recognised (%s)\n", 521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vendor_id); 522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return -1; 523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Successful! Convert sizes from KB to bytes */ 526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < ci->num_caches; ++i) { 527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[i].sizeB *= 1024; 528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return ret; 531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool 534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovget_cache_info(VexArchInfo *vai) 535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int ret = get_caches_from_CPUID(&vai->hwcache_info); 537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return ret == 0 ? True : False; 539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGA_arm) || defined(VGA_ppc32) || defined(VGA_ppc64) || \ 542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_arm64) 543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool 545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovget_cache_info(VexArchInfo *vai) 546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vai->hwcache_info.icaches_maintain_coherence = False; 548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return False; // not yet 550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGA_s390x) 553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic ULong 555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovecag(UInt ai, UInt li, UInt ti) 556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov register ULong result asm("2") = 0; 558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov register ULong input asm("3") = (ai << 4) | (li << 1) | ti; 559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov asm volatile(".short 0xeb20\n\t" 561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ".long 0x3000004c\n\t" 562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : "=d" (result) : "d" (input)); 563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return result; 565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic UInt 568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovget_cache_info_for_level(ULong topology, UInt level) 569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return (topology >> (56 - level * 8)) & 0xff; 571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic ULong 574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovget_line_size(UInt level, Bool is_insn_cache) 575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return ecag(1, level, is_insn_cache); 577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic ULong 580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovget_total_size(UInt level, Bool is_insn_cache) 581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return ecag(2, level, is_insn_cache); 583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 584436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 585436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic ULong 586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovget_associativity(UInt level, Bool is_insn_cache) 587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return ecag(3, level, is_insn_cache); 589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic VexCache 592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovget_cache(UInt level, VexCacheKind kind) 593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool is_insn_cache = kind == INSN_CACHE; 595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt size = get_total_size(level, is_insn_cache); 596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt line_size = get_line_size(level, is_insn_cache); 597436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt assoc = get_associativity(level, is_insn_cache); 598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return VEX_CACHE_INIT(kind, level + 1, size, line_size, assoc); 600436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 601436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 602436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool 603436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovget_cache_info(VexArchInfo *vai) 604436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 605436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexCacheInfo *ci = &vai->hwcache_info; 606436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 607436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->icaches_maintain_coherence = True; 608436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 609436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (! (vai->hwcaps & VEX_HWCAPS_S390X_GIE)) { 610436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // ECAG is not available 611436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return False; 612436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 613436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 614436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt level, cache_kind, info, i; 615436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ULong topology = ecag(0, 0, 0); // get summary 616436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 617436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* ECAG supports at most 8 levels of cache. Find out how many levels 618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov of cache and how many caches there are. */ 619436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_levels = 0; 620436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_caches = 0; 621436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (level = 0; level < 8; level++) { 622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov info = get_cache_info_for_level(topology, level); 623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if ((info & 0xc) == 0) break; // cache does not exist at this level 625436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ++ci->num_levels; 626436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cache_kind = info & 0x3; 628436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (cache_kind) { 629436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0: ci->num_caches += 2; break; /* separate data and insn cache */ 630436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 1: ci->num_caches += 1; break; /* only insn cache */ 631436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 2: ci->num_caches += 1; break; /* only data cache */ 632436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 3: ci->num_caches += 1; break; /* unified data and insn cache */ 633436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 634436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 635436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 636436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches = VG_(malloc)("m_cache", ci->num_caches * sizeof *ci->caches); 637436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 638436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov i = 0; 639436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (level = 0; level < ci->num_levels; level++) { 640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov info = get_cache_info_for_level(topology, level); 641436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cache_kind = info & 0x3; 642436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (cache_kind) { 643436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0: /* separate data and insn cache */ 644436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[i++] = get_cache(level, INSN_CACHE); 645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[i++] = get_cache(level, DATA_CACHE); 646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 1: /* only insn cache */ 649436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[i++] = get_cache(level, INSN_CACHE); 650436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 2: /* only data cache */ 653436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[i++] = get_cache(level, DATA_CACHE); 654436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 655436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 3: /* unified data and insn cache */ 657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches[i++] = get_cache(level, UNIFIED_CACHE); 658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return True; 662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#else 665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#error "Unknown arch" 667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif 669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Debug information */ 671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void 672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovwrite_cache_info(const VexCacheInfo *ci) 673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt i; 675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "Cache info:\n"); 677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", " #levels = %u\n", ci->num_levels); 678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", " #caches = %u\n", ci->num_caches); 679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < ci->num_caches; ++i) { 680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexCache *c = ci->caches + i; 681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar *kind; 682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", " cache #%u:\n", i); 683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (c->kind) { 684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case INSN_CACHE: kind = "insn"; break; 685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case DATA_CACHE: kind = "data"; break; 686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case UNIFIED_CACHE: kind = "unified"; break; 687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: kind = "unknown"; break; 688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", " kind = %s\n", kind); 690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", " level = %u\n", c->level); 691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", " size = %u bytes\n", c->sizeB); 692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", " linesize = %u bytes\n", c->line_sizeB); 693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", " assoc = %u\n", c->assoc); 694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool 698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovcache_info_is_sensible(const VexCacheInfo *ci) 699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt level, i; 701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool sensible = True; 702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* There must be at most one cache of a given kind at the same level. 704436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov If there is a unified cache at a given level, no other cache may 705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov exist at that level. */ 706436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (level = 1; level <= ci->num_levels; ++level) { 707436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt num_icache, num_dcache, num_ucache; 708436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 709436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov num_icache = num_dcache = num_ucache = 0; 710436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < ci->num_caches; ++i) { 711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (ci->caches[i].level == level) { 712436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (ci->caches[i].kind) { 713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case INSN_CACHE: ++num_icache; break; 714436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case DATA_CACHE: ++num_dcache; break; 715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case UNIFIED_CACHE: ++num_ucache; break; 716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 719436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (num_icache == 0 && num_dcache == 0 && num_ucache == 0) { 720436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "warning: No caches at level %u\n", level); 721436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov sensible = False; 722436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 723436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (num_icache > 1 || num_dcache > 1 || num_ucache > 1) { 724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "warning: More than one cache of a given " 725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "kind at level %u\n", level); 726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov sensible = False; 727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (num_ucache != 0 && (num_icache > 0 || num_dcache > 0)) { 729436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "warning: Unified cache and I/D cache " 730436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "at level %u\n", level); 731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov sensible = False; 732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* If there is a cache at level N > 1 there must be a cache at level N-1 */ 736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (level = 2; level <= ci->num_levels; ++level) { 737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool found = False; 738436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < ci->num_caches; ++i) { 739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (ci->caches[i].level == level - 1) { 740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov found = True; 741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 743436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 744436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (! found) { 745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "warning: Cache at level %u but no cache " 746436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "at level %u\n", level, level - 1); 747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov sensible = False; 748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return sensible; 752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 754436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 755436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Autodetect the cache information for this host and stuff it into 756436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexArchInfo::hwcache_info. Return True if successful. */ 757436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovBool 758436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovVG_(machine_get_cache_info)(VexArchInfo *vai) 759436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 760436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool ok = get_cache_info(vai); 761436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexCacheInfo *ci = &vai->hwcache_info; 763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (! ok) { 765436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", "Could not autodetect cache info\n"); 766436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ok = cache_info_is_sensible(ci); 768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 769436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (! ok) { 770436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", 771436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "Autodetected cache info is not sensible\n"); 772436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 773436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(debugLog)(1, "cache", 774436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "Autodetected cache info is sensible\n"); 775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov write_cache_info(ci); /* write out for debugging */ 777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (! ok ) { 780436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Reset cache info */ 781436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_levels = 0; 782436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->num_caches = 0; 783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(free)(ci->caches); 784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ci->caches = NULL; 785436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return ok; 788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/ 791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- end ---*/ 792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/ 793