m_transtab.c revision 59570ffbe31930ab4d678754daaeec0715117a3d
1de4a1d01951937632098a6cda45859afa587a06fsewardj 2de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 3de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- Management of the translation table and cache. ---*/ 48bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- m_transtab.c ---*/ 5de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 6de4a1d01951937632098a6cda45859afa587a06fsewardj 7de4a1d01951937632098a6cda45859afa587a06fsewardj/* 8b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn This file is part of Valgrind, a dynamic binary instrumentation 9b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn framework. 10de4a1d01951937632098a6cda45859afa587a06fsewardj 119f207460d70d38c46c9e81996a3dcdf90961c6dbnjn Copyright (C) 2000-2009 Julian Seward 12de4a1d01951937632098a6cda45859afa587a06fsewardj jseward@acm.org 13de4a1d01951937632098a6cda45859afa587a06fsewardj 14de4a1d01951937632098a6cda45859afa587a06fsewardj This program is free software; you can redistribute it and/or 15de4a1d01951937632098a6cda45859afa587a06fsewardj modify it under the terms of the GNU General Public License as 16de4a1d01951937632098a6cda45859afa587a06fsewardj published by the Free Software Foundation; either version 2 of the 17de4a1d01951937632098a6cda45859afa587a06fsewardj License, or (at your option) any later version. 18de4a1d01951937632098a6cda45859afa587a06fsewardj 19de4a1d01951937632098a6cda45859afa587a06fsewardj This program is distributed in the hope that it will be useful, but 20de4a1d01951937632098a6cda45859afa587a06fsewardj WITHOUT ANY WARRANTY; without even the implied warranty of 21de4a1d01951937632098a6cda45859afa587a06fsewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22de4a1d01951937632098a6cda45859afa587a06fsewardj General Public License for more details. 23de4a1d01951937632098a6cda45859afa587a06fsewardj 24de4a1d01951937632098a6cda45859afa587a06fsewardj You should have received a copy of the GNU General Public License 25de4a1d01951937632098a6cda45859afa587a06fsewardj along with this program; if not, write to the Free Software 26de4a1d01951937632098a6cda45859afa587a06fsewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27de4a1d01951937632098a6cda45859afa587a06fsewardj 02111-1307, USA. 28de4a1d01951937632098a6cda45859afa587a06fsewardj 29e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn The GNU General Public License is contained in the file COPYING. 30de4a1d01951937632098a6cda45859afa587a06fsewardj*/ 31de4a1d01951937632098a6cda45859afa587a06fsewardj 32c7561b931e249acf3768ead77638545b0ccaa8f1njn#include "pub_core_basics.h" 3345f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_debuglog.h" 341f0d814045aba94e01e62e04e968ca8b970b3d44cerion#include "pub_core_machine.h" // For VG(machine_get_VexArchInfo) 3597405b2d134b52880d6dbec3eb2929e2002c2542njn#include "pub_core_libcbase.h" 36132bfccd21960e462352175f8553a5bdce8a210cnjn#include "pub_core_libcassert.h" 3736a20fa5f779a0a6fb7b4a90dcaa6376481f1faanjn#include "pub_core_libcprint.h" 382024234c590f408994b373abfb00bc2cd2a90c48njn#include "pub_core_options.h" 3910f08cf5b84882eebbb6712a7be890577650e8adsewardj#include "pub_core_tooliface.h" // For VG_(details).avg_translation_sizeB 408bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn#include "pub_core_transtab.h" 4145f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_aspacemgr.h" 4245f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_mallocfree.h" // VG_(out_of_memory_NORETURN) 43de4a1d01951937632098a6cda45859afa587a06fsewardj 4459570ffbe31930ab4d678754daaeec0715117a3dsewardj// JRS FIXME get rid of this somehow 4559570ffbe31930ab4d678754daaeec0715117a3dsewardj#if defined(VGP_arm_linux) 4659570ffbe31930ab4d678754daaeec0715117a3dsewardj# include "pub_core_vkiscnums.h" // __ARM_NR_cacheflush 4759570ffbe31930ab4d678754daaeec0715117a3dsewardj# include "pub_core_syscall.h" // VG_(do_syscallN) 4859570ffbe31930ab4d678754daaeec0715117a3dsewardj#endif 4959570ffbe31930ab4d678754daaeec0715117a3dsewardj 5059570ffbe31930ab4d678754daaeec0715117a3dsewardj 5118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* #define DEBUG_TRANSTAB */ 5218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj 53de4a1d01951937632098a6cda45859afa587a06fsewardj 546c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/ 556c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*--- Management of the FIFO-based translation table+cache. ---*/ 566c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/ 57de4a1d01951937632098a6cda45859afa587a06fsewardj 586c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ CONSTANTS ------------------*/ 59de4a1d01951937632098a6cda45859afa587a06fsewardj 60fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of sectors the TC is divided into. If you need a larger 61fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj overall translation cache, increase this value. */ 62fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_SECTORS 8 63de4a1d01951937632098a6cda45859afa587a06fsewardj 64fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of TC entries in each sector. This needs to be a prime 656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj number to work properly, it must be <= 65535 (so that a TT index 666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj fits in a UShort, leaving room for 0xFFFF(EC2TTE_DELETED) to denote 676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 'deleted') and it is strongly recommended not to change this. 686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 65521 is the largest prime <= 65535. */ 696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define N_TTES_PER_SECTOR /*30011*/ /*40009*/ 65521 70de4a1d01951937632098a6cda45859afa587a06fsewardj 71fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to 72fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj specify the maximum allowable loading, after which the sector is 73fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj deemed full. */ 746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define SECTOR_TT_LIMIT_PERCENT 80 75de4a1d01951937632098a6cda45859afa587a06fsewardj 76fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */ 77fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_TTES_PER_SECTOR_USABLE \ 78fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ((N_TTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100) 796c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Equivalence classes for fast address range deletion. There are 1 + 816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 2^ECLASS_WIDTH bins. The highest one, ECLASS_MISC, describes an 826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range which does not fall cleanly within any specific bin. 836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Note that ECLASS_SHIFT + ECLASS_WIDTH must be < 32. */ 846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_SHIFT 11 856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_WIDTH 8 866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_MISC (1 << ECLASS_WIDTH) 876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_N (1 + ECLASS_MISC) 886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define EC2TTE_DELETED 0xFFFF /* 16-bit special value */ 906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 91de4a1d01951937632098a6cda45859afa587a06fsewardj 926c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/ 93de4a1d01951937632098a6cda45859afa587a06fsewardj 94fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry. This indicates precisely which areas of 95fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj guest code are included in the translation, and contains all other 96fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj auxiliary info too. */ 976c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef 986c3769f487145a08c01b58d6e5db3ba274062ad4sewardj struct { 99fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Profiling only: the count and weight (arbitrary meaning) for 100fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj this translation. Weight is a property of the translation 101fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj itself and computed once when the translation is created. 102fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Count is an entry count for the translation and is 103fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj incremented by 1 every time the translation is used, if we 104fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj are profiling. */ 105fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt count; 106fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UShort weight; 107fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 108fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Status of the slot. Note, we need to be able to do lazy 109fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj deletion, hence the Deleted state. */ 110fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj enum { InUse, Deleted, Empty } status; 111fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1125f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* 64-bit aligned pointer to one or more 64-bit words containing 1135f76de086a6d643db51e50a4e623df7dfc9b6161sewardj the corresponding host code (must be in the same sector!) 1145f76de086a6d643db51e50a4e623df7dfc9b6161sewardj This is a pointer into the sector's tc (code) area. */ 1155f76de086a6d643db51e50a4e623df7dfc9b6161sewardj ULong* tcptr; 116fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 117fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This is the original guest address that purportedly is the 118fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj entry point of the translation. You might think that .entry 119fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj should be the same as .vge->base[0], and most of the time it 120fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj is. However, when doing redirections, that is not the case. 121fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj .vge must always correctly describe the guest code sections 122fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj from which this translation was made. However, .entry may or 123fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj may not be a lie, depending on whether or not we're doing 124fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj redirection. */ 125fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Addr64 entry; 126fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 127fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This structure describes precisely what ranges of guest code 128fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj the translation covers, so we can decide whether or not to 129fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj delete it when translations of a given address range are 130fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidated. */ 131fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VexGuestExtents vge; 1326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Address range summary info: these are pointers back to 1346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclass[] entries in the containing Sector. Those entries in 1356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj turn point back here -- the two structures are mutually 1366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj redundant but both necessary to make fast deletions work. 1376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj The eclass info is similar to, and derived from, this entry's 1386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 'vge' field, but it is not the same */ 1396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort n_tte2ec; // # tte2ec pointers (1 to 3) 1406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort tte2ec_ec[3]; // for each, the eclass # 1416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt tte2ec_ix[3]; // and the index within the eclass. 1426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // for i in 0 .. n_tte2ec-1 1436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // sec->ec2tte[ tte2ec_ec[i] ][ tte2ec_ix[i] ] 1446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // should be the index 1456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // of this TTEntry in the containing Sector's tt array. 1466c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 1476c3769f487145a08c01b58d6e5db3ba274062ad4sewardj TTEntry; 1486c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 1494ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 150fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself. Each sector contains an array of 151fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TCEntries, which hold code, and an array of TTEntries, containing 152fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj all required administrative info. Profiling is supported using the 153fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TTEntry .count and .weight fields, if required. Each sector is 154fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj independent in that no cross-sector references are allowed. 1554ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 156fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj If the sector is not in use, all three pointers are NULL and 157fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tt_n_inuse is zero. 158fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 159fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef 160fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj struct { 161fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The TCEntry area. Size of this depends on the average 162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj translation size. We try and size it so it becomes full 163fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj precisely when this sector's translation table (tt) reaches 164fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj its load limit (SECTOR_TT_LIMIT_PERCENT). */ 165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tc; 1664ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The TTEntry array. This is a fixed size, always containing 168fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj exactly N_TTES_PER_SECTOR entries. */ 169fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TTEntry* tt; 1706c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 171fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This points to the current allocation point in tc. */ 172fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tc_next; 173de4a1d01951937632098a6cda45859afa587a06fsewardj 174fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The count of tt entries with state InUse. */ 175fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int tt_n_inuse; 1766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Expandable arrays of tt indices for each of the ECLASS_N 1786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range equivalence classes. These hold indices into 1796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj the containing sector's tt array, which in turn should point 1806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj back here. */ 1816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int ec2tte_size[ECLASS_N]; 1826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int ec2tte_used[ECLASS_N]; 1836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort* ec2tte[ECLASS_N]; 184fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 185fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Sector; 186de4a1d01951937632098a6cda45859afa587a06fsewardj 187de4a1d01951937632098a6cda45859afa587a06fsewardj 1886c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/ 1896c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 190fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors. The index of the 191fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest sector is recorded, and new translations are put into that 192fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. When it fills up, we move along to the next sector and 193fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj start to fill that up, wrapping around at the end of the array. 194fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj That way, once all N_TC_SECTORS have been bought into use for the 195fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj first time, and are full, we then re-use the oldest sector, 196fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj endlessly. 197fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 198fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj When running, youngest sector should be between >= 0 and < 199fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_TC_SECTORS. The initial -1 value indicates the TT/TC system is 200fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj not yet initialised. 201fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 202fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Sector sectors[N_SECTORS]; 203fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int youngest_sector = -1; 2046c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 205fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area. This is computed once 206fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj at startup and does not change. */ 207fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int tc_sector_szQ; 2086c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 2096c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 2105f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Fast helper for the TC. A direct-mapped cache which holds a set of 2115f76de086a6d643db51e50a4e623df7dfc9b6161sewardj recently used (guest address, host address) pairs. This array is 2125f76de086a6d643db51e50a4e623df7dfc9b6161sewardj referred to directly from m_dispatch/dispatch-<platform>.S. 2136c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 2145f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Entries in tt_fast may refer to any valid TC entry, regardless of 215fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj which sector it's in. Consequently we must be very careful to 216fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidate this cache when TC entries are changed or disappear. 217c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 2185f76de086a6d643db51e50a4e623df7dfc9b6161sewardj A special .guest address - TRANSTAB_BOGUS_GUEST_ADDR -- must be 2195f76de086a6d643db51e50a4e623df7dfc9b6161sewardj pointed at to cause that cache entry to miss. This relies on the 2205f76de086a6d643db51e50a4e623df7dfc9b6161sewardj assumption that no guest code actually has that address, hence a 2215f76de086a6d643db51e50a4e623df7dfc9b6161sewardj value 0x1 seems good. m_translate gives the client a synthetic 2225f76de086a6d643db51e50a4e623df7dfc9b6161sewardj segfault if it tries to execute at this address. 2235f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/ 2245f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* 2255f76de086a6d643db51e50a4e623df7dfc9b6161sewardjtypedef 2265f76de086a6d643db51e50a4e623df7dfc9b6161sewardj struct { 2275f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Addr guest; 2285f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Addr host; 2295f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 2305f76de086a6d643db51e50a4e623df7dfc9b6161sewardj FastCacheEntry; 2315f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/ 2325f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*global*/ __attribute__((aligned(16))) 2335f76de086a6d643db51e50a4e623df7dfc9b6161sewardj FastCacheEntry VG_(tt_fast)[VG_TT_FAST_SIZE]; 2345f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* 2355f76de086a6d643db51e50a4e623df7dfc9b6161sewardj#define TRANSTAB_BOGUS_GUEST_ADDR ((Addr)1) 236fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 23792e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote 238fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* For profiling, we have a parallel array of pointers to .count 239fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj fields in TT entries. Again, these pointers must be invalidated 240fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj when translations disappear. A NULL pointer suffices to indicate 241fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj an unused slot. 2426c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 2435f76de086a6d643db51e50a4e623df7dfc9b6161sewardj When not profiling (the normal case, VG_(clo_profile_flags) == 0), 2445f76de086a6d643db51e50a4e623df7dfc9b6161sewardj all tt_fastN entries are set to NULL at startup and never read nor 2455f76de086a6d643db51e50a4e623df7dfc9b6161sewardj written after that. 2465f76de086a6d643db51e50a4e623df7dfc9b6161sewardj 2475f76de086a6d643db51e50a4e623df7dfc9b6161sewardj When profiling (VG_(clo_profile_flags) > 0), tt_fast and tt_fastN 2485f76de086a6d643db51e50a4e623df7dfc9b6161sewardj change together: if tt_fast[i].guest is TRANSTAB_BOGUS_GUEST_ADDR 2495f76de086a6d643db51e50a4e623df7dfc9b6161sewardj then the corresponding tt_fastN[i] must be null. If 2505f76de086a6d643db51e50a4e623df7dfc9b6161sewardj tt_fast[i].guest is any other value, then tt_fastN[i] *must* point 2515f76de086a6d643db51e50a4e623df7dfc9b6161sewardj to the .count field of the corresponding TT entry. 2526c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 253fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tt_fast and tt_fastN are referred to from assembly code 254fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj (dispatch.S). 255fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 256fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*global*/ UInt* VG_(tt_fastN)[VG_TT_FAST_SIZE]; 257de4a1d01951937632098a6cda45859afa587a06fsewardj 258de4a1d01951937632098a6cda45859afa587a06fsewardj 259663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */ 260663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False; 261663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 262663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 263fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/ 264de4a1d01951937632098a6cda45859afa587a06fsewardj 265fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */ 266fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_fast_flushes = 0; 267fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_fast_updates = 0; 26822854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 269fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */ 270fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_full_lookups = 0; 271fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_lookup_probes = 0; 27222854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 27326412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj/* Number/osize/tsize of translations entered; also the number of 27426412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj those for which self-checking was requested. */ 27526412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_count = 0; 27626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_osize = 0; 27726412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_tsize = 0; 27826412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_sc_count = 0; 279de4a1d01951937632098a6cda45859afa587a06fsewardj 280fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */ 281fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_dump_count = 0; 282fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_dump_osize = 0; 283fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 284fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */ 285fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_disc_count = 0; 286fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_disc_osize = 0; 287fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 288fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 2906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Address-range equivalence class stuff ---*/ 2916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 2926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 2936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Return equivalence class number for a range. */ 2946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 2956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Int range_to_eclass ( Addr64 start, UInt len ) 2966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 2976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt mask = (1 << ECLASS_WIDTH) - 1; 2986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt lo = (UInt)start; 2996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt hi = lo + len - 1; 3006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt loBits = (lo >> ECLASS_SHIFT) & mask; 3016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt hiBits = (hi >> ECLASS_SHIFT) & mask; 3026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (loBits == hiBits) { 3036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(loBits < ECLASS_N-1); 3046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return loBits; 3056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 3066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return ECLASS_MISC; 3076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 3086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 3096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Calculates the equivalence class numbers for any VexGuestExtent. 3126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj These are written in *eclasses, which must be big enough to hold 3 3136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Ints. The number written, between 1 and 3, is returned. The 3146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses are presented in order, and any duplicates are removed. 3156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj*/ 3166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 3186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjInt vexGuestExtents_to_eclasses ( /*OUT*/Int* eclasses, 3196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VexGuestExtents* vge ) 3206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 3216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# define SWAP(_lv1,_lv2) \ 3226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj do { Int t = _lv1; _lv1 = _lv2; _lv2 = t; } while (0) 3236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, j, n_ec, r; 3256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(vge->n_used >= 1 && vge->n_used <= 3); 3276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_ec = 0; 3296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < vge->n_used; i++) { 3306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj r = range_to_eclass( vge->base[i], (UInt)vge->len[i] ); 3316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (r == ECLASS_MISC) 3326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj goto bad; 3336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* only add if we haven't already seen it */ 3346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < n_ec; j++) 3356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[j] == r) 3366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj break; 3376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (j == n_ec) 3386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses[n_ec++] = r; 3396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 3406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 1) 3426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 1; 3436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 2) { 3456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* sort */ 3466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[1]) 3476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[1]); 3486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 2; 3496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 3506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 3) { 3526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* sort */ 3536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[2]) 3546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[2]); 3556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[1]) 3566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[1]); 3576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[1] > eclasses[2]) 3586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[1], eclasses[2]); 3596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 3; 3606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 3616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* NOTREACHED */ 3636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(0); 3646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bad: 3666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses[0] = ECLASS_MISC; 3676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 1; 3686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# undef SWAP 3706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 3716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Add tteno to the set of entries listed for equivalence class ec in 3746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj this sector. Returns used location in eclass array. */ 3756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 3776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjUInt addEClassNo ( /*MOD*/Sector* sec, Int ec, UShort tteno ) 3786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 3796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int old_sz, new_sz, i, r; 3806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort *old_ar, *new_ar; 3816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_N); 3836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno < N_TTES_PER_SECTOR); 3846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (0) VG_(printf)("ec %d gets %d\n", ec, (Int)tteno); 3866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[ec] >= sec->ec2tte_size[ec]) { 3886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_used[ec] == sec->ec2tte_size[ec]); 3906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj old_sz = sec->ec2tte_size[ec]; 3926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj old_ar = sec->ec2tte[ec]; 3936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj new_sz = old_sz==0 ? 8 : old_sz<64 ? 2*old_sz : (3*old_sz)/2; 3949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj new_ar = VG_(arena_malloc)(VG_AR_TTAUX, "transtab.aECN.1", 3959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj new_sz * sizeof(UShort)); 3966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < old_sz; i++) 3976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj new_ar[i] = old_ar[i]; 3986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (old_ar) 3996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(arena_free)(VG_AR_TTAUX, old_ar); 4006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte_size[ec] = new_sz; 4016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec] = new_ar; 4026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (0) VG_(printf)("expand ec %d to %d\n", ec, new_sz); 4046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 4056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Common case */ 4076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj r = sec->ec2tte_used[ec]++; 4086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(r >= 0 && r < sec->ec2tte_size[ec]); 4096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec][r] = tteno; 4106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return (UInt)r; 4116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 4126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* 'vge' is being added to 'sec' at TT entry 'tteno'. Add appropriate 4156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclass entries to 'sec'. */ 4166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 4186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjvoid upd_eclasses_after_add ( /*MOD*/Sector* sec, Int tteno ) 4196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 4206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, r, eclasses[3]; 4216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 4226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR); 4236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 4256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj r = vexGuestExtents_to_eclasses( eclasses, &tte->vge ); 4266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(r >= 1 && r <= 3); 4286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->n_tte2ec = r; 4296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < r; i++) { 4316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->tte2ec_ec[i] = eclasses[i]; 4326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->tte2ec_ix[i] = addEClassNo( sec, eclasses[i], (UShort)tteno ); 4336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 4346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 4356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Check the eclass info in 'sec' to ensure it is consistent. Returns 4386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj True if OK, False if something's not right. Expensive. */ 4396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_eclasses_in_sector ( Sector* sec ) 4416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 4426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# define BAD(_str) do { whassup = (_str); goto bad; } while (0) 4436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj HChar* whassup = NULL; 4456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, j, k, n, ec_num, ec_idx; 4466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 4476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort tteno; 4486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ULong* tce; 4496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Basic checks on this sector */ 4516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tt_n_inuse < 0 || sec->tt_n_inuse > N_TTES_PER_SECTOR_USABLE) 4526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("invalid sec->tt_n_inuse"); 4536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tce = sec->tc_next; 4546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tce < &sec->tc[0] || tce > &sec->tc[tc_sector_szQ]) 4556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("sec->tc_next points outside tc"); 4566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* For each eclass ... */ 4586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 4596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] == 0 && sec->ec2tte[i] != NULL) 4606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte_size/ec2tte mismatch(1)"); 4616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] != 0 && sec->ec2tte[i] == NULL) 4626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte_size/ec2tte mismatch(2)"); 4636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[i] < 0 4646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj || sec->ec2tte_used[i] > sec->ec2tte_size[i]) 4656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("implausible ec2tte_used"); 4666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[i] == 0) 4676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 4686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* For each tt reference in each eclass .. ensure the reference 4706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj is to a valid tt entry, and that the entry's address ranges 4716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj really include this eclass. */ 4726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 4736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < sec->ec2tte_used[i]; j++) { 4746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tteno = sec->ec2tte[i][j]; 4756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno == EC2TTE_DELETED) 4766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 4776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno >= N_TTES_PER_SECTOR) 4786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("implausible tteno"); 4796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 4806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != InUse) 4816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tteno points to non-inuse tte"); 4826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3) 4836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_tte2ec out of range"); 4846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Exactly least one of tte->eclasses[0 .. tte->n_eclasses-1] 4856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj must equal i. Inspect tte's eclass info. */ 4866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n = 0; 4876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (k = 0; k < tte->n_tte2ec; k++) { 4886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (k < tte->n_tte2ec-1 4896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj && tte->tte2ec_ec[k] >= tte->tte2ec_ec[k+1]) 4906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ec[..] out of order"); 4916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = tte->tte2ec_ec[k]; 4926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num < 0 || ec_num >= ECLASS_N) 4936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ec[..] out of range"); 4946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num != i) 4956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 4966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[k]; 4976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[i]) 4986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ix[..] out of range"); 4996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx == j) 5006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n++; 5016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 5026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n != 1) 5036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tteno does not point back at eclass"); 5046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 5056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 5066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* That establishes that for each forward pointer from TTEntrys 5086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj there is a corresponding backward pointer from the eclass[] 5096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj arrays. However, it doesn't rule out the possibility of other, 5106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bogus pointers in the eclass[] arrays. So do those similarly: 5116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj scan through them and check the TTEntryies they point at point 5126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj back. */ 5136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR_USABLE; i++) { 5156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[i]; 5176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status == Empty || tte->status == Deleted) { 5186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec != 0) 5196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_eclasses nonzero for unused tte"); 5206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 5216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 5226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 5246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3) 5266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_eclasses out of range(2)"); 5276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < tte->n_tte2ec; j++) { 5296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = tte->tte2ec_ec[j]; 5306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num < 0 || ec_num >= ECLASS_N) 5316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->eclass[..] out of range"); 5326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[j]; 5336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[ec_num]) 5346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->ec_idx[..] out of range(2)"); 5356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte[ec_num][ec_idx] != i) 5366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte does not point back to tte"); 5376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 5386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 5396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return True; 5416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bad: 5436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (whassup) 5446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(0, "transtab", "eclass sanity fail: %s\n", whassup); 5456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# if 0 5476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("eclass = %d\n", i); 5486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("tteno = %d\n", (Int)tteno); 5496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj switch (tte->status) { 5506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case InUse: VG_(printf)("InUse\n"); break; 5516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case Deleted: VG_(printf)("Deleted\n"); break; 5526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case Empty: VG_(printf)("Empty\n"); break; 5536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 5546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != Empty) { 5556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (k = 0; k < tte->vge.n_used; k++) 5566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("0x%llx %d\n", tte->vge.base[k], 5576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj (Int)tte->vge.len[k]); 5586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 5596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# endif 5606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return False; 5626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# undef BAD 5646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 5656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Sanity check absolutely everything. True == check passed. */ 5686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 5695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* forwards */ 5700ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void ); 5715f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic Bool sanity_check_fastcache ( void ); 5720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 5736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_all_sectors ( void ) 5746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 5756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int sno; 5766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane; 5776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 5786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (sno = 0; sno < N_SECTORS; sno++) { 5796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 5806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 5816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 5826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sane = sanity_check_eclasses_in_sector( sec ); 5836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (!sane) 5846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return False; 5856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 5865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if ( !sanity_check_redir_tt_tc() ) 5875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj return False; 5885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if ( !sanity_check_fastcache() ) 5890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return False; 5906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return True; 5916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 5926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 593fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/ 5956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Add/find translations ---*/ 596fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/ 597fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 598fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic UInt vge_osize ( VexGuestExtents* vge ) 599c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{ 600fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt i, n = 0; 601fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < vge->n_used; i++) 602fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n += (UInt)vge->len[i]; 603fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return n; 604c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj} 605c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 606fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Bool isValidSector ( Int sector ) 6076c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 608fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sector < 0 || sector >= N_SECTORS) 609fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 610fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 6116c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 612de4a1d01951937632098a6cda45859afa587a06fsewardj 613fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline UInt HASH_TT ( Addr64 key ) 614de4a1d01951937632098a6cda45859afa587a06fsewardj{ 615fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt kHi = (UInt)(key >> 32); 616fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt kLo = (UInt)key; 6176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt k32 = kHi ^ kLo; 6186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt ror = 7; 6196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ror > 0) 6206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj k32 = (k32 >> ror) | (k32 << (32-ror)); 6216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return k32 % N_TTES_PER_SECTOR; 622de4a1d01951937632098a6cda45859afa587a06fsewardj} 623de4a1d01951937632098a6cda45859afa587a06fsewardj 6245f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void setFastCacheEntry ( Addr64 key, ULong* tcptr, UInt* count ) 625de4a1d01951937632098a6cda45859afa587a06fsewardj{ 6263387dda4479102751d544c176a7bfc24f3766669sewardj UInt cno = (UInt)VG_TT_FAST_HASH(key); 6275f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[cno].guest = (Addr)key; 6285f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[cno].host = (Addr)tcptr; 6295f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if (VG_(clo_profile_flags) > 0) 6305f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fastN)[cno] = count; 631fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_updates++; 6325f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* This shouldn't fail. It should be assured by m_translate 6335f76de086a6d643db51e50a4e623df7dfc9b6161sewardj which should reject any attempt to make translation of code 6345f76de086a6d643db51e50a4e623df7dfc9b6161sewardj starting at TRANSTAB_BOGUS_GUEST_ADDR. */ 6355f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_(tt_fast)[cno].guest != TRANSTAB_BOGUS_GUEST_ADDR); 6366c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 637de4a1d01951937632098a6cda45859afa587a06fsewardj 6385f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Invalidate the fast cache's counter array, VG_(tt_fastN). */ 6395f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastNCache ( void ) 6406c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 641fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt j; 64265e193939481231a8f6699201258e0a2828357e8sewardj vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0); 64365e193939481231a8f6699201258e0a2828357e8sewardj for (j = 0; j < VG_TT_FAST_SIZE; j += 4) { 64465e193939481231a8f6699201258e0a2828357e8sewardj VG_(tt_fastN)[j+0] = NULL; 64565e193939481231a8f6699201258e0a2828357e8sewardj VG_(tt_fastN)[j+1] = NULL; 64665e193939481231a8f6699201258e0a2828357e8sewardj VG_(tt_fastN)[j+2] = NULL; 64765e193939481231a8f6699201258e0a2828357e8sewardj VG_(tt_fastN)[j+3] = NULL; 6486c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 64965e193939481231a8f6699201258e0a2828357e8sewardj vg_assert(j == VG_TT_FAST_SIZE); 6505f76de086a6d643db51e50a4e623df7dfc9b6161sewardj} 6515f76de086a6d643db51e50a4e623df7dfc9b6161sewardj 6525f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Invalidate the fast cache VG_(tt_fast). If profiling, also 6535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj invalidate the fast cache's counter array VG_(tt_fastN), otherwise 6545f76de086a6d643db51e50a4e623df7dfc9b6161sewardj don't touch it. */ 6555f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastCache ( void ) 6565f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{ 6575f76de086a6d643db51e50a4e623df7dfc9b6161sewardj UInt j; 6585f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* This loop is popular enough to make it worth unrolling a 6595f76de086a6d643db51e50a4e623df7dfc9b6161sewardj bit, at least on ppc32. */ 6605f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0); 6615f76de086a6d643db51e50a4e623df7dfc9b6161sewardj for (j = 0; j < VG_TT_FAST_SIZE; j += 4) { 6625f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+0].guest = TRANSTAB_BOGUS_GUEST_ADDR; 6635f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+1].guest = TRANSTAB_BOGUS_GUEST_ADDR; 6645f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+2].guest = TRANSTAB_BOGUS_GUEST_ADDR; 6655f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+3].guest = TRANSTAB_BOGUS_GUEST_ADDR; 6665f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 6675f76de086a6d643db51e50a4e623df7dfc9b6161sewardj 6685f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if (VG_(clo_profile_flags) > 0) 6695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj invalidateFastNCache(); 6705f76de086a6d643db51e50a4e623df7dfc9b6161sewardj 6715f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(j == VG_TT_FAST_SIZE); 672fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_flushes++; 6736c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 674de4a1d01951937632098a6cda45859afa587a06fsewardj 6755f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic Bool sanity_check_fastcache ( void ) 6765f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{ 6775f76de086a6d643db51e50a4e623df7dfc9b6161sewardj UInt j; 6785f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if (0) VG_(printf)("sanity check fastcache\n"); 6795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if (VG_(clo_profile_flags) > 0) { 6805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* profiling */ 6815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj for (j = 0; j < VG_TT_FAST_SIZE; j++) { 6825f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if (VG_(tt_fastN)[j] == NULL 6835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj && VG_(tt_fast)[j].guest != TRANSTAB_BOGUS_GUEST_ADDR) 6845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj return False; 6855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if (VG_(tt_fastN)[j] != NULL 6865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj && VG_(tt_fast)[j].guest == TRANSTAB_BOGUS_GUEST_ADDR) 6875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj return False; 6885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 6895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } else { 6905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* not profiling */ 6915f76de086a6d643db51e50a4e623df7dfc9b6161sewardj for (j = 0; j < VG_TT_FAST_SIZE; j++) { 6925f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if (VG_(tt_fastN)[j] != NULL) 6935f76de086a6d643db51e50a4e623df7dfc9b6161sewardj return False; 6945f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 6955f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 6965f76de086a6d643db51e50a4e623df7dfc9b6161sewardj return True; 6975f76de086a6d643db51e50a4e623df7dfc9b6161sewardj} 6985f76de086a6d643db51e50a4e623df7dfc9b6161sewardj 699fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void initialiseSector ( Int sno ) 7006c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 70145f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int i; 70245f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres; 7036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 704fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(isValidSector(sno)); 705fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 7066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 7076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 7086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) { 7096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 710fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Sector has never been used before. Need to allocate tt and 711fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tc. */ 7126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt == NULL); 7136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tc_next == NULL); 7146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt_n_inuse == 0); 7156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 7166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_size[i] == 0); 7176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_used[i] == 0); 7186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[i] == NULL); 7196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 72045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 72145f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(1,"transtab", "allocate sector %d\n", sno); 72245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 72345f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ ); 724cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 72545f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(out_of_memory_NORETURN)("initialiseSector(TC)", 72645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 8 * tc_sector_szQ ); 72745f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*NOTREACHED*/ 72845f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 729cda2f0fbda4c4b2644babc830244be8aed95de1dnjn sec->tc = (ULong*)(AddrH)sr_Res(sres); 73045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 73145f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_mmap_anon_float_valgrind) 73245f4e7c91119c7d01a59f5e827c67841632c9314sewardj ( N_TTES_PER_SECTOR * sizeof(TTEntry) ); 733cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 73445f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(out_of_memory_NORETURN)("initialiseSector(TT)", 73545f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_TTES_PER_SECTOR * sizeof(TTEntry) ); 73645f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*NOTREACHED*/ 73745f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 738cda2f0fbda4c4b2644babc830244be8aed95de1dnjn sec->tt = (TTEntry*)(AddrH)sr_Res(sres); 7396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 7406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 7416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].status = Empty; 7426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].n_tte2ec = 0; 7436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 74445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 745fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 746738856f99eea33d86ce91dcb1d6cd5b151e307casewardj VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d\n", sno); 7476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 748fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } else { 7496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 7506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Sector has been used before. Dump the old contents. */ 75145f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(1,"transtab", "recycle sector %d\n", sno); 7526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt != NULL); 7536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tc_next != NULL); 7546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_dump_count += sec->tt_n_inuse; 7556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 7566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Visit each just-about-to-be-abandoned translation. */ 757fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 7586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tt[i].status == InUse) { 7596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt[i].n_tte2ec >= 1); 7606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt[i].n_tte2ec <= 3); 7616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_dump_osize += vge_osize(&sec->tt[i].vge); 7623786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj /* Tell the tool too. */ 7630b9d74abd0a663b530d290b2b788ddeda46e5400sewardj if (VG_(needs).superblock_discards) { 7640b9d74abd0a663b530d290b2b788ddeda46e5400sewardj VG_TDICT_CALL( tool_discard_superblock_info, 7654ba057cce1d81a949f5a899b5abb99e90a731bccsewardj sec->tt[i].entry, 7666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].vge ); 7673786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj } 7686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 7696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt[i].n_tte2ec == 0); 7706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 7716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].status = Empty; 7726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].n_tte2ec = 0; 7736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 7746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 7756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Free up the eclass structures. */ 7766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 7776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] == 0) { 7786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_used[i] == 0); 7796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[i] == NULL); 7806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 7816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[i] != NULL); 7826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(arena_free)(VG_AR_TTAUX, sec->ec2tte[i]); 7836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[i] = NULL; 7846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte_size[i] = 0; 7856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte_used[i] = 0; 786fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 787fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 7886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 789fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 790738856f99eea33d86ce91dcb1d6cd5b151e307casewardj VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d\n", sno); 7916c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 7924ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 7936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tc_next = sec->tc; 7946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt_n_inuse = 0; 795fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 796fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 7976c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 798de4a1d01951937632098a6cda45859afa587a06fsewardj 79910f08cf5b84882eebbb6712a7be890577650e8adsewardjstatic void invalidate_icache ( void *ptr, Int nbytes ) 80085665ca6fa29dd64754dabe50eb98f25896e752acerion{ 8012c48c7b0a453d32375a4df17e153011b797ef28csewardj# if defined(VGA_ppc32) || defined(VGA_ppc64) 80210f08cf5b84882eebbb6712a7be890577650e8adsewardj Addr startaddr = (Addr) ptr; 80310f08cf5b84882eebbb6712a7be890577650e8adsewardj Addr endaddr = startaddr + nbytes; 804e3826cfe34ec9a0caa570a0d15647b28711584a0sewardj Addr cls; 80510f08cf5b84882eebbb6712a7be890577650e8adsewardj Addr addr; 806e3826cfe34ec9a0caa570a0d15647b28711584a0sewardj VexArchInfo vai; 807e3826cfe34ec9a0caa570a0d15647b28711584a0sewardj 8085f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if (nbytes == 0) return; 8095f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(nbytes > 0); 8105f76de086a6d643db51e50a4e623df7dfc9b6161sewardj 811e3826cfe34ec9a0caa570a0d15647b28711584a0sewardj VG_(machine_get_VexArchInfo)( NULL, &vai ); 8121f0d814045aba94e01e62e04e968ca8b970b3d44cerion cls = vai.ppc_cache_line_szB; 81310f08cf5b84882eebbb6712a7be890577650e8adsewardj 8142bf6ba55b04ea9a58098f041c5ee149539c0f081sewardj /* Stay sane .. */ 81589230cace4f5acad8037e4cb4b3e49e83d3a275bsewardj vg_assert(cls == 32 || cls == 64 || cls == 128); 81685665ca6fa29dd64754dabe50eb98f25896e752acerion 81785665ca6fa29dd64754dabe50eb98f25896e752acerion startaddr &= ~(cls - 1); 81859570ffbe31930ab4d678754daaeec0715117a3dsewardj for (addr = startaddr; addr < endaddr; addr += cls) { 81959570ffbe31930ab4d678754daaeec0715117a3dsewardj __asm__ __volatile__("dcbst 0,%0" : : "r" (addr)); 82059570ffbe31930ab4d678754daaeec0715117a3dsewardj } 82159570ffbe31930ab4d678754daaeec0715117a3dsewardj __asm__ __volatile__("sync"); 82259570ffbe31930ab4d678754daaeec0715117a3dsewardj for (addr = startaddr; addr < endaddr; addr += cls) { 82359570ffbe31930ab4d678754daaeec0715117a3dsewardj __asm__ __volatile__("icbi 0,%0" : : "r" (addr)); 82459570ffbe31930ab4d678754daaeec0715117a3dsewardj } 82559570ffbe31930ab4d678754daaeec0715117a3dsewardj __asm__ __volatile__("sync; isync"); 82610f08cf5b84882eebbb6712a7be890577650e8adsewardj 82710f08cf5b84882eebbb6712a7be890577650e8adsewardj# elif defined(VGA_x86) 82810f08cf5b84882eebbb6712a7be890577650e8adsewardj /* no need to do anything, hardware provides coherence */ 82910f08cf5b84882eebbb6712a7be890577650e8adsewardj 83010f08cf5b84882eebbb6712a7be890577650e8adsewardj# elif defined(VGA_amd64) 83110f08cf5b84882eebbb6712a7be890577650e8adsewardj /* no need to do anything, hardware provides coherence */ 83210f08cf5b84882eebbb6712a7be890577650e8adsewardj 83359570ffbe31930ab4d678754daaeec0715117a3dsewardj# elif defined(VGP_arm_linux) 83459570ffbe31930ab4d678754daaeec0715117a3dsewardj /* ARM cache flushes are privileged, so we must defer to the kernel. */ 83559570ffbe31930ab4d678754daaeec0715117a3dsewardj Addr startaddr = (Addr) ptr; 83659570ffbe31930ab4d678754daaeec0715117a3dsewardj Addr endaddr = startaddr + nbytes; 83759570ffbe31930ab4d678754daaeec0715117a3dsewardj VG_(do_syscall2)(__NR_ARM_cacheflush, startaddr, endaddr); 83859570ffbe31930ab4d678754daaeec0715117a3dsewardj 83910f08cf5b84882eebbb6712a7be890577650e8adsewardj# else 84010f08cf5b84882eebbb6712a7be890577650e8adsewardj# error "Unknown ARCH" 84110f08cf5b84882eebbb6712a7be890577650e8adsewardj# endif 84285665ca6fa29dd64754dabe50eb98f25896e752acerion} 84385665ca6fa29dd64754dabe50eb98f25896e752acerion 844de4a1d01951937632098a6cda45859afa587a06fsewardj 845fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC. The translation is temporarily 846fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj in code[0 .. code_len-1]. 847de4a1d01951937632098a6cda45859afa587a06fsewardj 848fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj pre: youngest_sector points to a valid (although possibly full) 849fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. 850fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 8518bddf58af8cc7342d4bde6712c5a6a33bf2850d4njnvoid VG_(add_to_transtab)( VexGuestExtents* vge, 8528bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn Addr64 entry, 8538bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn AddrH code, 85426412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj UInt code_len, 85526412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj Bool is_self_checking ) 85622854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{ 857fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int tcAvailQ, reqdQ, y, i; 8585f76de086a6d643db51e50a4e623df7dfc9b6161sewardj ULong *tcptr, *tcptr2; 859fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UChar* srcP; 860fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UChar* dstP; 861fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 862663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 863fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(vge->n_used >= 1 && vge->n_used <= 3); 864e808930793aeddc4cfd3e7a94b665913bec2566csewardj 865e808930793aeddc4cfd3e7a94b665913bec2566csewardj /* 60000: should agree with N_TMPBUF in m_translate.c. */ 866e808930793aeddc4cfd3e7a94b665913bec2566csewardj vg_assert(code_len > 0 && code_len < 60000); 867fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 868fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (0) 8698bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn VG_(printf)("add_to_transtab(entry = 0x%llx, len = %d)\n", 870fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj entry, code_len); 871fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 872fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_count++; 873fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_tsize += code_len; 874fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_osize += vge_osize(vge); 87526412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj if (is_self_checking) 87626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj n_in_sc_count++; 877fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 878fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj y = youngest_sector; 879fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(isValidSector(y)); 880fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 881fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[y].tc == NULL) 882fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj initialiseSector(y); 883fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 884fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Try putting the translation in this sector. */ 8855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj reqdQ = (code_len + 7) >> 3; 886fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 887fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Will it fit in tc? */ 888fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tcAvailQ = ((ULong*)(§ors[y].tc[tc_sector_szQ])) 889fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - ((ULong*)(sectors[y].tc_next)); 890fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= 0); 891fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ <= tc_sector_szQ); 892fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 893fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (tcAvailQ < reqdQ 894fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR_USABLE) { 895fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* No. So move on to the next sector. Either it's never been 896fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj used before, in which case it will get its tt/tc allocated 897fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj now, or it has been used before, in which case it is set to be 898fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj empty, hence throwing out the oldest sector. */ 899a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj vg_assert(tc_sector_szQ > 0); 900a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj VG_(debugLog)(1,"transtab", 901a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj "declare sector %d full " 902a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj "(TT loading %2d%%, TC loading %2d%%)\n", 903a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj y, 904a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj (100 * sectors[y].tt_n_inuse) 905a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj / N_TTES_PER_SECTOR, 906a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj (100 * (tc_sector_szQ - tcAvailQ)) 907a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj / tc_sector_szQ); 908fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector++; 909fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (youngest_sector >= N_SECTORS) 910fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector = 0; 911fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj y = youngest_sector; 912fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj initialiseSector(y); 913fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 91422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 915fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Be sure ... */ 916fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tcAvailQ = ((ULong*)(§ors[y].tc[tc_sector_szQ])) 917fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - ((ULong*)(sectors[y].tc_next)); 918fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= 0); 919fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ <= tc_sector_szQ); 920fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= reqdQ); 921fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR_USABLE); 922fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[y].tt_n_inuse >= 0); 923fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 924fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Copy into tc. */ 9255f76de086a6d643db51e50a4e623df7dfc9b6161sewardj tcptr = sectors[y].tc_next; 9265f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr >= §ors[y].tc[0]); 9275f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr <= §ors[y].tc[tc_sector_szQ]); 928fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 9295f76de086a6d643db51e50a4e623df7dfc9b6161sewardj dstP = (UChar*)tcptr; 930fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj srcP = (UChar*)code; 931fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < code_len; i++) 932fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj dstP[i] = srcP[i]; 933fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tc_next += reqdQ; 934fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt_n_inuse++; 935fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 93685665ca6fa29dd64754dabe50eb98f25896e752acerion invalidate_icache( dstP, code_len ); 93785665ca6fa29dd64754dabe50eb98f25896e752acerion 938fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* more paranoia */ 9395f76de086a6d643db51e50a4e623df7dfc9b6161sewardj tcptr2 = sectors[y].tc_next; 9405f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr2 >= §ors[y].tc[0]); 9415f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr2 <= §ors[y].tc[tc_sector_szQ]); 942fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 943fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find an empty tt slot, and use it. There must be such a slot 944fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj since tt is never allowed to get completely full. */ 945fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i = HASH_TT(entry); 946fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(i >= 0 && i < N_TTES_PER_SECTOR); 94722854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj while (True) { 948fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[y].tt[i].status == Empty 949fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj || sectors[y].tt[i].status == Deleted) 950fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 951fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i++; 952fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (i >= N_TTES_PER_SECTOR) 953fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i = 0; 95422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj } 955fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 956fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].status = InUse; 9575f76de086a6d643db51e50a4e623df7dfc9b6161sewardj sectors[y].tt[i].tcptr = tcptr; 958fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].count = 0; 959fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].weight = 1; 960fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].vge = *vge; 961fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].entry = entry; 962fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 9636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Update the fast-cache. */ 9645f76de086a6d643db51e50a4e623df7dfc9b6161sewardj setFastCacheEntry( entry, tcptr, §ors[y].tt[i].count ); 9656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Note the eclass numbers for this translation. */ 9676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj upd_eclasses_after_add( §ors[y], i ); 96822854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj} 96922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 970fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 971fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address. If 972fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj requested, a successful search can also cause the fast-caches to be 973fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj updated. 974fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 975fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjBool VG_(search_transtab) ( /*OUT*/AddrH* result, 976fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Addr64 guest_addr, 977fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Bool upd_cache ) 9786c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 979fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int i, j, k, kstart, sno; 980663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 981663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 982fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find the initial probe point just once. It will be the same in 983fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj all sectors and avoids multiple expensive % operations. */ 984fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_full_lookups++; 985fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = -1; 986fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj kstart = HASH_TT(guest_addr); 987fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(kstart >= 0 && kstart < N_TTES_PER_SECTOR); 988fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 989fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Search in all the sectors. Although the order should not matter, 990fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj it might be most efficient to search in the order youngest to 991fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj oldest. */ 992fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sno = youngest_sector; 993fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_SECTORS; i++) { 994fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 995fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tc == NULL) 996fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj goto notfound; /* sector not in use. */ 997fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 998fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = kstart; 999fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (j = 0; j < N_TTES_PER_SECTOR; j++) { 1000fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_lookup_probes++; 1001fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[k].status == InUse 1002fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj && sectors[sno].tt[k].entry == guest_addr) { 1003fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* found it */ 1004fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (upd_cache) 1005fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj setFastCacheEntry( 10065f76de086a6d643db51e50a4e623df7dfc9b6161sewardj guest_addr, sectors[sno].tt[k].tcptr, 1007fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj §ors[sno].tt[k].count ); 1008fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (result) 10095f76de086a6d643db51e50a4e623df7dfc9b6161sewardj *result = (AddrH)sectors[sno].tt[k].tcptr; 1010fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1011fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 1012fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[k].status == Empty) 1013fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; /* not found in this sector */ 1014fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k++; 1015fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (k == N_TTES_PER_SECTOR) 1016fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = 0; 10176c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 1018fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1019fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* If we fall off the end, all entries are InUse and not 1020fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj matching, or Deleted. In any case we did not find it in this 1021fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. */ 1022fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1023fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj notfound: 1024fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* move to the next oldest sector */ 1025fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sno = sno==0 ? (N_SECTORS-1) : (sno-1); 10266c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 1027fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1028fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Not found in any sector. */ 1029fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 10306c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1031de4a1d01951937632098a6cda45859afa587a06fsewardj 1032de4a1d01951937632098a6cda45859afa587a06fsewardj 10336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 10346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Delete translations. ---*/ 10356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 10366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* forward */ 10380ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void unredir_discard_translations( Addr64, ULong ); 10390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 10406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Stuff for deleting translations which intersect with a given 10416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range. Unfortunately, to make this run at a reasonable 10426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj speed, it is complex. */ 1043fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1044fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline 1045a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlap1 ( Addr64 s1, ULong r1, Addr64 s2, ULong r2 ) 10466c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1047a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj Addr64 e1 = s1 + r1 - 1ULL; 1048a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj Addr64 e2 = s2 + r2 - 1ULL; 1049fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (e1 < s2 || e2 < s1) 1050fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1051fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 10526c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1053de4a1d01951937632098a6cda45859afa587a06fsewardj 1054fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline 1055a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlaps ( Addr64 start, ULong range, VexGuestExtents* vge ) 10566c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1057fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (overlap1(start, range, vge->base[0], (UInt)vge->len[0])) 1058fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1059fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (vge->n_used < 2) 1060fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1061fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (overlap1(start, range, vge->base[1], (UInt)vge->len[1])) 1062fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1063fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (vge->n_used < 3) 1064fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1065fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (overlap1(start, range, vge->base[2], (UInt)vge->len[2])) 1066fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1067fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 10686c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1069de4a1d01951937632098a6cda45859afa587a06fsewardj 1070de4a1d01951937632098a6cda45859afa587a06fsewardj 10716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete a tt entry, and update all the eclass data accordingly. */ 10726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic void delete_tte ( /*MOD*/Sector* sec, Int tteno ) 10746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 10756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, ec_num, ec_idx; 10766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 10776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR); 10796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 10806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 10816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->n_tte2ec >= 1 && tte->n_tte2ec <= 3); 10826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Deal with the ec-to-tte links first. */ 10846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < tte->n_tte2ec; i++) { 10856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = (Int)tte->tte2ec_ec[i]; 10866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[i]; 10876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_num >= 0 && ec_num < ECLASS_N); 10886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_idx >= 0); 10896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_idx < sec->ec2tte_used[ec_num]); 10906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Assert that the two links point at each other. */ 10916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[ec_num][ec_idx] == (UShort)tteno); 10926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* "delete" the pointer back to here. */ 10936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec_num][ec_idx] = EC2TTE_DELETED; 10946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Now fix up this TTEntry. */ 10976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->status = Deleted; 10986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->n_tte2ec = 0; 10996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Stats .. */ 11016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt_n_inuse--; 11026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_disc_count++; 11036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_disc_osize += vge_osize(&tte->vge); 11046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Tell the tool too. */ 11060b9d74abd0a663b530d290b2b788ddeda46e5400sewardj if (VG_(needs).superblock_discards) { 11070b9d74abd0a663b530d290b2b788ddeda46e5400sewardj VG_TDICT_CALL( tool_discard_superblock_info, 11084ba057cce1d81a949f5a899b5abb99e90a731bccsewardj tte->entry, 11096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->vge ); 11106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 11126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, but 11156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj only consider translations in the specified eclass. */ 11166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 11186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjBool delete_translations_in_sector_eclass ( /*MOD*/Sector* sec, 11196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Addr64 guest_start, ULong range, 11206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int ec ) 11216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 11226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 11236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort tteno; 11246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeld = False; 11256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 11266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_N); 11286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < sec->ec2tte_used[ec]; i++) { 11306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tteno = sec->ec2tte[ec][i]; 11326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno == EC2TTE_DELETED) { 11336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* already deleted */ 11346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno < N_TTES_PER_SECTOR); 11386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 11406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 11416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (overlaps( guest_start, range, &tte->vge )) { 11436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeld = True; 11446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj delete_tte( sec, (Int)tteno ); 11456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return anyDeld; 11506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 11516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, the 11546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj slow way, by inspecting all translations in sec. */ 11556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 11576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjBool delete_translations_in_sector ( /*MOD*/Sector* sec, 11586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Addr64 guest_start, ULong range ) 11596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 11606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 11616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeld = False; 11626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 11646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tt[i].status == InUse 11656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj && overlaps( guest_start, range, &sec->tt[i].vge )) { 11666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeld = True; 11676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj delete_tte( sec, i ); 11686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return anyDeld; 11726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 11736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 117545f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid VG_(discard_translations) ( Addr64 guest_start, ULong range, 117645f4e7c91119c7d01a59f5e827c67841632c9314sewardj HChar* who ) 11776c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 11786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 11796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int sno, ec; 11806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeleted = False; 11816c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 1182663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 1183663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 1184a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj VG_(debugLog)(2, "transtab", 118545f4e7c91119c7d01a59f5e827c67841632c9314sewardj "discard_translations(0x%llx, %lld) req by %s\n", 118645f4e7c91119c7d01a59f5e827c67841632c9314sewardj guest_start, range, who ); 118745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 11886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Pre-deletion sanity check */ 11896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (VG_(clo_sanity_level >= 4)) { 11906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane = sanity_check_all_sectors(); 11916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sane); 11926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (range == 0) 11956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return; 11966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* There are two different ways to do this. 11986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj If the range fits within a single address-range equivalence 12006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class, as will be the case for a cache line sized invalidation, 12016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj then we only have to inspect the set of translations listed in 12026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj that equivalence class, and also in the "sin-bin" equivalence 12036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class ECLASS_MISC. 12046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Otherwise, the invalidation is of a larger range and probably 12066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj results from munmap. In this case it's (probably!) faster just 12076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj to inspect all translations, dump those we don't want, and 12086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj regenerate the equivalence class information (since modifying it 12096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj in-situ is even more expensive). 12106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj */ 12116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* First off, figure out if the range falls within a single class, 12136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj and if so which one. */ 12146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec = ECLASS_MISC; 12166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (range < (1ULL << ECLASS_SHIFT)) 12176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec = range_to_eclass( guest_start, (UInt)range ); 12186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* if ec is ECLASS_MISC then we aren't looking at just a single 12206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class, so use the slow scheme. Else use the fast scheme, 12216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj examining 'ec' and ECLASS_MISC. */ 12226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec != ECLASS_MISC) { 12246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(2, "transtab", 12266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj " FAST, ec = %d\n", ec); 12276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Fast scheme */ 12296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_MISC); 12306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (sno = 0; sno < N_SECTORS; sno++) { 12326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 12336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 12346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 12356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector_eclass( 12366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec, guest_start, range, ec ); 12376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector_eclass( 12386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec, guest_start, range, ECLASS_MISC ); 12396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 12426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* slow scheme */ 12446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(2, "transtab", 12466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj " SLOW, ec = %d\n", ec); 12476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (sno = 0; sno < N_SECTORS; sno++) { 12496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 12506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 12516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 12526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector( 12536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec, guest_start, range ); 12546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1256de4a1d01951937632098a6cda45859afa587a06fsewardj } 1257de4a1d01951937632098a6cda45859afa587a06fsewardj 1258fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (anyDeleted) 1259fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 12606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* don't forget the no-redir cache */ 12620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_discard_translations( guest_start, range ); 12630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 12646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Post-deletion sanity check */ 12656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (VG_(clo_sanity_level >= 4)) { 12666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 12676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 12686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane = sanity_check_all_sectors(); 12696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sane); 12706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* But now, also check the requested address range isn't 12716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj present anywhere. */ 12726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (sno = 0; sno < N_SECTORS; sno++) { 12736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 12746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 12756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 12766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 12776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[i]; 12786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != InUse) 12796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 12806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(!overlaps( guest_start, range, &tte->vge )); 12816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 1284fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 12856c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 12866c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 1287fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 12880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*--- AUXILIARY: the unredirected TT/TC ---*/ 12890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/ 12900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 12910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* A very simple translation cache which holds a small number of 12920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredirected translations. This is completely independent of the 12930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj main tt/tc structures. When unredir_tc or unredir_tt becomes full, 12940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj both structures are simply dumped and we start over. 12950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 12960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Since these translations are unredirected, the search key is (by 12970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj definition) the first address entry in the .vge field. */ 12980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 12990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Sized to hold 500 translations of average size 1000 bytes. */ 13000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define UNREDIR_SZB 1000 13020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TT 500 13040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TCQ (N_UNREDIR_TT * UNREDIR_SZB / sizeof(ULong)) 13050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13060ec07f32bbbb209d749b9974408e6f025ad40b31sewardjtypedef 13070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj struct { 13080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj VexGuestExtents vge; 13090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Addr hcode; 13100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Bool inUse; 13110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 13120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj UTCEntry; 13130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13140ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* We just allocate forwards in _tc, never deleting. */ 131578c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic ULong *unredir_tc; 131678c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic Int unredir_tc_used = N_UNREDIR_TCQ; 13170ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Slots in _tt can come into use and out again (.inUse). 13190ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Nevertheless _tt_highwater is maintained so that invalidations 13200ec07f32bbbb209d749b9974408e6f025ad40b31sewardj don't have to scan all the slots when only a few are in use. 13210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj _tt_highwater holds the index of the highest ever allocated 13220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj slot. */ 13230ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic UTCEntry unredir_tt[N_UNREDIR_TT]; 13240ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Int unredir_tt_highwater; 13250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13270ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void init_unredir_tt_tc ( void ) 13280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 13290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 133078c0c09d429c95115e826ef769ecaa6cff2ac338tom if (unredir_tc == NULL) { 1331cda2f0fbda4c4b2644babc830244be8aed95de1dnjn SysRes sres = VG_(am_mmap_anon_float_valgrind) 1332cda2f0fbda4c4b2644babc830244be8aed95de1dnjn ( N_UNREDIR_TT * UNREDIR_SZB ); 1333cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 1334cda2f0fbda4c4b2644babc830244be8aed95de1dnjn VG_(out_of_memory_NORETURN)("init_unredir_tt_tc", 1335cda2f0fbda4c4b2644babc830244be8aed95de1dnjn N_UNREDIR_TT * UNREDIR_SZB); 133678c0c09d429c95115e826ef769ecaa6cff2ac338tom /*NOTREACHED*/ 133778c0c09d429c95115e826ef769ecaa6cff2ac338tom } 1338cda2f0fbda4c4b2644babc830244be8aed95de1dnjn unredir_tc = (ULong *)(AddrH)sr_Res(sres); 133978c0c09d429c95115e826ef769ecaa6cff2ac338tom } 13400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tc_used = 0; 13410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) 13420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = False; 13430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt_highwater = -1; 13440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 13450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Do a sanity check; return False on failure. */ 13470ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void ) 13480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 13490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 13500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt_highwater < -1) return False; 13510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt_highwater >= N_UNREDIR_TT) return False; 13520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = unredir_tt_highwater+1; i < N_UNREDIR_TT; i++) 13540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].inUse) 13550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return False; 13560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tc_used < 0) return False; 13580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tc_used > N_UNREDIR_TCQ) return False; 13590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return True; 13610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 13620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Add an UNREDIRECTED translation of vge to TT/TC. The translation 13650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj is temporarily in code[0 .. code_len-1]. 13660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj*/ 13670ec07f32bbbb209d749b9974408e6f025ad40b31sewardjvoid VG_(add_to_unredir_transtab)( VexGuestExtents* vge, 13680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Addr64 entry, 13690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj AddrH code, 13701dcee097db02f9ef3ba355162c4373d90d0e895cnjn UInt code_len ) 13710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 13720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i, j, code_szQ; 13730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj HChar *srcP, *dstP; 13740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(sanity_check_redir_tt_tc()); 13760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* This is the whole point: it's not redirected! */ 13780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(entry == vge->base[0]); 13790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* How many unredir_tt slots are needed */ 13810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj code_szQ = (code_len + 7) / 8; 13820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13830ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* Look for an empty unredir_tc slot */ 13840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) 13850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (!unredir_tt[i].inUse) 13860ec07f32bbbb209d749b9974408e6f025ad40b31sewardj break; 13870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (i >= N_UNREDIR_TT || code_szQ > (N_UNREDIR_TCQ - unredir_tc_used)) { 13890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* It's full; dump everything we currently have */ 13900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj init_unredir_tt_tc(); 13910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj i = 0; 13920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 13930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 13940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used >= 0); 13950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used <= N_UNREDIR_TCQ); 13960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(code_szQ > 0); 13970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(code_szQ + unredir_tc_used <= N_UNREDIR_TCQ); 13980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(i >= 0 && i < N_UNREDIR_TT); 13990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tt[i].inUse == False); 14000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 14010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (i > unredir_tt_highwater) 14020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt_highwater = i; 14030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 14040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj dstP = (HChar*)&unredir_tc[unredir_tc_used]; 14050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj srcP = (HChar*)code; 14060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (j = 0; j < code_len; j++) 14070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj dstP[j] = srcP[j]; 14080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 1409c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj invalidate_icache( dstP, code_len ); 1410c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj 14110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = True; 14120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].vge = *vge; 14130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].hcode = (Addr)dstP; 14140ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 14150ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tc_used += code_szQ; 14160ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used >= 0); 14170ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used <= N_UNREDIR_TCQ); 14180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 14190ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(&dstP[code_len] <= (HChar*)&unredir_tc[unredir_tc_used]); 14200ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 14210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 14220ec07f32bbbb209d749b9974408e6f025ad40b31sewardjBool VG_(search_unredir_transtab) ( /*OUT*/AddrH* result, 14230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Addr64 guest_addr ) 14240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 14250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 14260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) { 14270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (!unredir_tt[i].inUse) 14280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj continue; 14290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].vge.base[0] == guest_addr) { 14300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj *result = (AddrH)unredir_tt[i].hcode; 14310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return True; 14320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 14330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 14340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return False; 14350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 14360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 14370ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void unredir_discard_translations( Addr64 guest_start, ULong range ) 14380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 14390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 14400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 14410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(sanity_check_redir_tt_tc()); 14420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 14430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i <= unredir_tt_highwater; i++) { 14440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].inUse 14450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj && overlaps( guest_start, range, &unredir_tt[i].vge)) 14460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = False; 14470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 14480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 14490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 14500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 14510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/ 1452fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation. ---*/ 1453fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 1454fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1455fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void ) 14566c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 14576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, j, avg_codeszQ; 1458de4a1d01951937632098a6cda45859afa587a06fsewardj 1459663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(!init_done); 1460663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj init_done = True; 1461663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 1462fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Otherwise lots of things go wrong... */ 1463fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sizeof(ULong) == 8); 1464fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sizeof(Addr64) == 8); 14655f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache entries really are 2 words long */ 14665f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof(Addr) == sizeof(void*)); 14675f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof(FastCacheEntry) == 2 * sizeof(Addr)); 14685f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache entries are packed back-to-back with no spaces */ 14695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof( VG_(tt_fast) ) == VG_TT_FAST_SIZE * sizeof(FastCacheEntry)); 14705f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache is aligned as we requested. Not fatal if it 14715f76de086a6d643db51e50a4e623df7dfc9b6161sewardj isn't, but we might as well make sure. */ 14725f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_IS_16_ALIGNED( ((Addr) & VG_(tt_fast)[0]) )); 1473de4a1d01951937632098a6cda45859afa587a06fsewardj 1474fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 1475fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 1476fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "TT/TC: VG_(init_tt_tc) " 1477738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "(startup of code management)\n"); 1478fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1479fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Figure out how big each tc area should be. */ 148043b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn avg_codeszQ = (VG_(details).avg_translation_sizeB + 7) / 8; 148143b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn tc_sector_szQ = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ); 1482fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1483fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Ensure the calculated value is not way crazy. */ 1484fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR_USABLE); 1485e808930793aeddc4cfd3e7a94b665913bec2566csewardj vg_assert(tc_sector_szQ <= 80 * N_TTES_PER_SECTOR_USABLE); 1486fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1487fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Initialise the sectors */ 1488fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector = 0; 1489fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_SECTORS; i++) { 1490fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tc = NULL; 1491fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tt = NULL; 1492fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tc_next = NULL; 1493fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tt_n_inuse = 0; 14946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < ECLASS_N; j++) { 14956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sectors[i].ec2tte_size[j] = 0; 14966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sectors[i].ec2tte_used[j] = 0; 14976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sectors[i].ec2tte[j] = NULL; 14986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 14996c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 15004ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 15015f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* Initialise the fast caches. If not profiling (the usual case), 15025f76de086a6d643db51e50a4e623df7dfc9b6161sewardj we have to explicitly invalidate the fastN cache as 15035f76de086a6d643db51e50a4e623df7dfc9b6161sewardj invalidateFastCache() won't do that for us. */ 1504fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 15055f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if (VG_(clo_profile_flags) == 0) 15065f76de086a6d643db51e50a4e623df7dfc9b6161sewardj invalidateFastNCache(); 1507fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 15080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* and the unredir tt/tc */ 15090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj init_unredir_tt_tc(); 15100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 1511fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) { 1512fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 1513738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "TT/TC: cache: %d sectors of %d bytes each = %d total\n", 1514fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS, 8 * tc_sector_szQ, 1515fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS * 8 * tc_sector_szQ ); 1516fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 1517738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "TT/TC: table: %d total entries, max occupancy %d (%d%%)\n", 1518fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS * N_TTES_PER_SECTOR, 1519fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS * N_TTES_PER_SECTOR_USABLE, 1520fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj SECTOR_TT_LIMIT_PERCENT ); 1521fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 152245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 152345f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "transtab", 152445f4e7c91119c7d01a59f5e827c67841632c9314sewardj "cache: %d sectors of %d bytes each = %d total\n", 152545f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_SECTORS, 8 * tc_sector_szQ, 152645f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_SECTORS * 8 * tc_sector_szQ ); 152745f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "transtab", 152845f4e7c91119c7d01a59f5e827c67841632c9314sewardj "table: %d total entries, max occupancy %d (%d%%)\n", 152945f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_SECTORS * N_TTES_PER_SECTOR, 153045f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_SECTORS * N_TTES_PER_SECTOR_USABLE, 153145f4e7c91119c7d01a59f5e827c67841632c9314sewardj SECTOR_TT_LIMIT_PERCENT ); 1532de4a1d01951937632098a6cda45859afa587a06fsewardj} 1533de4a1d01951937632098a6cda45859afa587a06fsewardj 15344ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 1535fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 1536fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics. ---*/ 1537fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 1538fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1539fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong safe_idiv( ULong a, ULong b ) 154092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{ 154192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote return (b == 0 ? 0 : a / b); 154292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote} 154392e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote 1544fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void ) 1545fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 1546fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return n_in_count; 1547fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 1548fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1549fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void ) 155092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{ 155192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 1552738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " tt/tc: %'llu tt lookups requiring %'llu probes\n", 1553fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_full_lookups, n_lookup_probes ); 155492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 1555738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " tt/tc: %'llu fast-cache updates, %'llu flushes\n", 1556fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_updates, n_fast_flushes ); 1557fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 155892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 1559a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart " transtab: new %'lld " 1560738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "(%'llu -> %'llu; ratio %'llu:10) [%'llu scs]\n", 1561fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_count, n_in_osize, n_in_tsize, 156226412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj safe_idiv(10*n_in_tsize, n_in_osize), 156326412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj n_in_sc_count); 156492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 1565738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " transtab: dumped %'llu (%'llu -> ?" "?)\n", 1566fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_dump_count, n_dump_osize ); 1567fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 1568738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " transtab: discarded %'llu (%'llu -> ?" "?)\n", 1569fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_disc_count, n_disc_osize ); 15706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 15716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (0) { 15726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 15736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n"); 15746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 15756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)(" %4d", sectors[0].ec2tte_used[i]); 15766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (i % 16 == 15) 15776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n"); 15786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 15796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n\n"); 15806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 158192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote} 1582de4a1d01951937632098a6cda45859afa587a06fsewardj 1583fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 1584fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results. ---*/ 1585fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 15864ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 1587fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong score ( TTEntry* tte ) 1588fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 1589fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return ((ULong)tte->weight) * ((ULong)tte->count); 1590de4a1d01951937632098a6cda45859afa587a06fsewardj} 1591de4a1d01951937632098a6cda45859afa587a06fsewardj 15922025cf98a3210c175a90fc77cb599cca1643bd68njnULong VG_(get_BB_profile) ( BBProfEntry tops[], UInt n_tops ) 1593de4a1d01951937632098a6cda45859afa587a06fsewardj{ 1594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int sno, i, r, s; 15952025cf98a3210c175a90fc77cb599cca1643bd68njn ULong score_total; 1596fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1597fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* First, compute the total weighted count, and find the top N 15982025cf98a3210c175a90fc77cb599cca1643bd68njn ttes. tops contains pointers to the most-used n_tops blocks, in 1599fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj descending order (viz, tops[0] is the highest scorer). */ 16002025cf98a3210c175a90fc77cb599cca1643bd68njn for (i = 0; i < n_tops; i++) { 16012025cf98a3210c175a90fc77cb599cca1643bd68njn tops[i].addr = 0; 16022025cf98a3210c175a90fc77cb599cca1643bd68njn tops[i].score = 0; 16032025cf98a3210c175a90fc77cb599cca1643bd68njn } 1604fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1605fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_total = 0; 1606fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1607fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (sno = 0; sno < N_SECTORS; sno++) { 1608fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tc == NULL) 160918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj continue; 1610fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 1611fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[i].status != InUse) 1612fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 1613fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_total += score(§ors[sno].tt[i]); 1614fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find the rank for sectors[sno].tt[i]. */ 16152025cf98a3210c175a90fc77cb599cca1643bd68njn r = n_tops-1; 1616fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj while (True) { 1617fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (r == -1) 1618fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 16192025cf98a3210c175a90fc77cb599cca1643bd68njn if (tops[r].addr == 0) { 1620fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r--; 1621fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 1622fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 16232025cf98a3210c175a90fc77cb599cca1643bd68njn if ( score(§ors[sno].tt[i]) > tops[r].score ) { 1624fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r--; 1625fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 1626fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 1627fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 1628fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 1629fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r++; 16302025cf98a3210c175a90fc77cb599cca1643bd68njn vg_assert(r >= 0 && r <= n_tops); 1631fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This bb should be placed at r, and bbs above it shifted 1632fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj upwards one slot. */ 16332025cf98a3210c175a90fc77cb599cca1643bd68njn if (r < n_tops) { 16342025cf98a3210c175a90fc77cb599cca1643bd68njn for (s = n_tops-1; s > r; s--) 1635fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tops[s] = tops[s-1]; 16362025cf98a3210c175a90fc77cb599cca1643bd68njn tops[r].addr = sectors[sno].tt[i].entry; 16372025cf98a3210c175a90fc77cb599cca1643bd68njn tops[r].score = score( §ors[sno].tt[i] ); 1638fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 1639de4a1d01951937632098a6cda45859afa587a06fsewardj } 1640de4a1d01951937632098a6cda45859afa587a06fsewardj } 1641de4a1d01951937632098a6cda45859afa587a06fsewardj 16422025cf98a3210c175a90fc77cb599cca1643bd68njn return score_total; 1643c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj} 1644c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 1645de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 16468bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end ---*/ 1647de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 1648