m_transtab.c revision 8bddf58af8cc7342d4bde6712c5a6a33bf2850d4
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 11fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Copyright (C) 2000-2005 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 32f1e5e1554292c92840da50ed4cf89062b69be597nethercote#include "core.h" 3343b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn#include "pub_core_tooliface.h" 348bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn// XXX: this module should not depend on m_translate! 353cbfbc1be6a4334e57ec4213a8044c1180836b8dnjn#include "pub_core_translate.h" 368bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn#include "pub_core_transtab.h" 37de4a1d01951937632098a6cda45859afa587a06fsewardj 3818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* #define DEBUG_TRANSTAB */ 3918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj 40de4a1d01951937632098a6cda45859afa587a06fsewardj 416c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/ 426c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*--- Management of the FIFO-based translation table+cache. ---*/ 436c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/ 44de4a1d01951937632098a6cda45859afa587a06fsewardj 456c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ CONSTANTS ------------------*/ 46de4a1d01951937632098a6cda45859afa587a06fsewardj 47fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of sectors the TC is divided into. If you need a larger 48fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj overall translation cache, increase this value. */ 49fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_SECTORS 8 50de4a1d01951937632098a6cda45859afa587a06fsewardj 51fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of TC entries in each sector. This needs to be a prime 52fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj number to work properly, and it is strongly recommended not to 53fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj change this. */ 54fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_TTES_PER_SECTOR /*30011*/ 40009 55de4a1d01951937632098a6cda45859afa587a06fsewardj 56fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to 57fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj specify the maximum allowable loading, after which the sector is 58fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj deemed full. */ 59fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define SECTOR_TT_LIMIT_PERCENT 60 60de4a1d01951937632098a6cda45859afa587a06fsewardj 61fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */ 62fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_TTES_PER_SECTOR_USABLE \ 63fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ((N_TTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100) 646c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 65de4a1d01951937632098a6cda45859afa587a06fsewardj 666c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/ 67de4a1d01951937632098a6cda45859afa587a06fsewardj 68fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-cache entry is two parts: 69fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - The guest address of the first (entry) bb in the translation, 70fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj as a 64-bit word. 71fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - One or more 64-bit words containing the code. 72fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj It is supposed to be 64-bit aligned. 73fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 74fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* 756c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef 76fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj struct { 77fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Addr64 orig_addr; 78fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong code[0]; 796c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 806c3769f487145a08c01b58d6e5db3ba274062ad4sewardj TCEntry; 81fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 826c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 83fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry. This indicates precisely which areas of 84fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj guest code are included in the translation, and contains all other 85fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj auxiliary info too. */ 866c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef 876c3769f487145a08c01b58d6e5db3ba274062ad4sewardj struct { 88fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Profiling only: the count and weight (arbitrary meaning) for 89fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj this translation. Weight is a property of the translation 90fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj itself and computed once when the translation is created. 91fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Count is an entry count for the translation and is 92fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj incremented by 1 every time the translation is used, if we 93fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj are profiling. */ 94fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt count; 95fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UShort weight; 96fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 97fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Status of the slot. Note, we need to be able to do lazy 98fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj deletion, hence the Deleted state. */ 99fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj enum { InUse, Deleted, Empty } status; 100fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 101fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Pointer to the corresponding TCEntry (must be in the same 102fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector!) */ 103fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tce; 104fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 105fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This is the original guest address that purportedly is the 106fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj entry point of the translation. You might think that .entry 107fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj should be the same as .vge->base[0], and most of the time it 108fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj is. However, when doing redirections, that is not the case. 109fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj .vge must always correctly describe the guest code sections 110fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj from which this translation was made. However, .entry may or 111fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj may not be a lie, depending on whether or not we're doing 112fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj redirection. */ 113fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Addr64 entry; 114fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 115fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This structure describes precisely what ranges of guest code 116fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj the translation covers, so we can decide whether or not to 117fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj delete it when translations of a given address range are 118fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidated. */ 119fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VexGuestExtents vge; 1206c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 1216c3769f487145a08c01b58d6e5db3ba274062ad4sewardj TTEntry; 1226c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 1234ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 124fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself. Each sector contains an array of 125fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TCEntries, which hold code, and an array of TTEntries, containing 126fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj all required administrative info. Profiling is supported using the 127fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TTEntry .count and .weight fields, if required. Each sector is 128fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj independent in that no cross-sector references are allowed. 1294ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 130fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj If the sector is not in use, all three pointers are NULL and 131fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tt_n_inuse is zero. 132fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 133fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef 134fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj struct { 135fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The TCEntry area. Size of this depends on the average 136fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj translation size. We try and size it so it becomes full 137fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj precisely when this sector's translation table (tt) reaches 138fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj its load limit (SECTOR_TT_LIMIT_PERCENT). */ 139fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tc; 1404ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 141fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The TTEntry array. This is a fixed size, always containing 142fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj exactly N_TTES_PER_SECTOR entries. */ 143fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TTEntry* tt; 1446c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 145fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This points to the current allocation point in tc. */ 146fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tc_next; 147de4a1d01951937632098a6cda45859afa587a06fsewardj 148fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The count of tt entries with state InUse. */ 149fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int tt_n_inuse; 150fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 151fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Sector; 152de4a1d01951937632098a6cda45859afa587a06fsewardj 153de4a1d01951937632098a6cda45859afa587a06fsewardj 1546c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/ 1556c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 156fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors. The index of the 157fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest sector is recorded, and new translations are put into that 158fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. When it fills up, we move along to the next sector and 159fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj start to fill that up, wrapping around at the end of the array. 160fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj That way, once all N_TC_SECTORS have been bought into use for the 161fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj first time, and are full, we then re-use the oldest sector, 162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj endlessly. 163fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 164fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj When running, youngest sector should be between >= 0 and < 165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_TC_SECTORS. The initial -1 value indicates the TT/TC system is 166fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj not yet initialised. 167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 168fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Sector sectors[N_SECTORS]; 169fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int youngest_sector = -1; 1706c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 171fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area. This is computed once 172fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj at startup and does not change. */ 173fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int tc_sector_szQ; 1746c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 1756c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 176fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Fast helper for the TC. A direct-mapped cache which holds a 177fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj pointer to a TC entry which may or may not be the correct one, but 178fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj which we hope usually is. This array is referred to directly from 179fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj <arch>/dispatch.S. 1806c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 181fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Entries in tt_fast may point to any valid TC entry, regardless of 182fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj which sector it's in. Consequently we must be very careful to 183fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidate this cache when TC entries are changed or disappear. 184c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 185fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj A special TCEntry -- bogus_tc_entry -- must be pointed at to cause 186fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj that cache entry to miss. This relies on the assumption that no 187fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj guest code actually has an address of 0x1. 188fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 189fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*global*/ ULong* VG_(tt_fast)[VG_TT_FAST_SIZE]; 19092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote 191fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong bogus_tc_entry = (Addr64)1; 19292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote 19392e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote 194fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* For profiling, we have a parallel array of pointers to .count 195fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj fields in TT entries. Again, these pointers must be invalidated 196fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj when translations disappear. A NULL pointer suffices to indicate 197fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj an unused slot. 1986c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 199fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tt_fast and tt_fastN change together: if tt_fast[i] points to 200fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj bogus_tc_entry then the corresponding tt_fastN[i] must be null. If 201fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tt_fast[i] points to some TC entry somewhere, then tt_fastN[i] 202fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj *must* point to the .count field of the corresponding TT entry. 2036c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 204fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tt_fast and tt_fastN are referred to from assembly code 205fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj (dispatch.S). 206fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 207fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*global*/ UInt* VG_(tt_fastN)[VG_TT_FAST_SIZE]; 208de4a1d01951937632098a6cda45859afa587a06fsewardj 209de4a1d01951937632098a6cda45859afa587a06fsewardj 210663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */ 211663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False; 212663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 213663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 214fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/ 215de4a1d01951937632098a6cda45859afa587a06fsewardj 216fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */ 217fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_fast_flushes = 0; 218fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_fast_updates = 0; 21922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 220fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */ 221fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_full_lookups = 0; 222fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_lookup_probes = 0; 22322854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 224fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize/tsize of translations entered. */ 225fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_in_count = 0; 226fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_in_osize = 0; 227fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_in_tsize = 0; 228de4a1d01951937632098a6cda45859afa587a06fsewardj 229fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */ 230fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_dump_count = 0; 231fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_dump_osize = 0; 232fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 233fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */ 234fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_disc_count = 0; 235fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_disc_osize = 0; 236fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 237fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 238fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 239fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/ 240fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Add/delete/find translations ---*/ 241fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/ 242fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 243fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic UInt vge_osize ( VexGuestExtents* vge ) 244c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{ 245fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt i, n = 0; 246fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < vge->n_used; i++) 247fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n += (UInt)vge->len[i]; 248fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return n; 249c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj} 250c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 251fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Bool isValidSector ( Int sector ) 2526c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 253fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sector < 0 || sector >= N_SECTORS) 254fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 255fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 2566c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 257de4a1d01951937632098a6cda45859afa587a06fsewardj 258fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline UInt HASH_TT ( Addr64 key ) 259de4a1d01951937632098a6cda45859afa587a06fsewardj{ 260fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt kHi = (UInt)(key >> 32); 261fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt kLo = (UInt)key; 262fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return (kHi ^ kLo) % N_TTES_PER_SECTOR; 263de4a1d01951937632098a6cda45859afa587a06fsewardj} 264de4a1d01951937632098a6cda45859afa587a06fsewardj 265fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void setFastCacheEntry ( Addr64 key, ULong* tce, UInt* count ) 266de4a1d01951937632098a6cda45859afa587a06fsewardj{ 267fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt cno = ((UInt)key) & VG_TT_FAST_MASK; 268fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(tt_fast)[cno] = tce; 269fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(tt_fastN)[cno] = count; 270fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_updates++; 2716c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 272de4a1d01951937632098a6cda45859afa587a06fsewardj 273fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void invalidateFastCache ( void ) 2746c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 275fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt j; 276fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (j = 0; j < VG_TT_FAST_SIZE; j++) { 277fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(tt_fast)[j] = &bogus_tc_entry; 278fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(tt_fastN)[j] = NULL; 2796c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 280fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_flushes++; 2816c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 282de4a1d01951937632098a6cda45859afa587a06fsewardj 283fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void initialiseSector ( Int sno ) 2846c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 285fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int i; 286fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(isValidSector(sno)); 287fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 288fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tc == NULL) { 289fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Sector has never been used before. Need to allocate tt and 290fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tc. */ 291fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[sno].tt == NULL); 292fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[sno].tc_next == NULL); 293fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[sno].tt_n_inuse == 0); 294fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[sno].tc 295fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj = VG_(get_memory_from_mmap) 296fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ( 8 * tc_sector_szQ, "sectors[sno].tc" ); 297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[sno].tt 298fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj = VG_(get_memory_from_mmap) 299fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ( N_TTES_PER_SECTOR * sizeof(TTEntry), "sectors[sno].tt" ); 300fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d", sno); 302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } else { 303fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Sector has been used before. */ 304fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[sno].tt != NULL); 305fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[sno].tc_next != NULL); 306fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_dump_count += sectors[sno].tt_n_inuse; 307fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 308fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[i].status == InUse) { 309fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_dump_osize += vge_osize(§ors[sno].tt[i].vge); 310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 311fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 312fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 313fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d", sno); 3146c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 3154ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 316fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[sno].tc_next = sectors[sno].tc; 317fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[sno].tt_n_inuse = 0; 318fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) 319fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[sno].tt[i].status = Empty; 320fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 321fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 3226c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 323de4a1d01951937632098a6cda45859afa587a06fsewardj 324de4a1d01951937632098a6cda45859afa587a06fsewardj 325fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC. The translation is temporarily 326fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj in code[0 .. code_len-1]. 327de4a1d01951937632098a6cda45859afa587a06fsewardj 328fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj pre: youngest_sector points to a valid (although possibly full) 329fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. 330fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 3318bddf58af8cc7342d4bde6712c5a6a33bf2850d4njnvoid VG_(add_to_transtab)( VexGuestExtents* vge, 3328bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn Addr64 entry, 3338bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn AddrH code, 3348bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn UInt code_len ) 33522854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{ 336fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int tcAvailQ, reqdQ, y, i; 337fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong *tce, *tce2; 338fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UChar* srcP; 339fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UChar* dstP; 340fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 341663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 342fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(vge->n_used >= 1 && vge->n_used <= 3); 343fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(code_len > 0 && code_len < 20000); 344fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (0) 3468bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn VG_(printf)("add_to_transtab(entry = 0x%llx, len = %d)\n", 347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj entry, code_len); 348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_count++; 350fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_tsize += code_len; 351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_osize += vge_osize(vge); 352fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 353fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj y = youngest_sector; 354fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(isValidSector(y)); 355fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 356fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[y].tc == NULL) 357fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj initialiseSector(y); 358fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 359fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Try putting the translation in this sector. */ 360fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj reqdQ = 1 + ((code_len + 7) >> 3); 361fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 362fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Will it fit in tc? */ 363fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tcAvailQ = ((ULong*)(§ors[y].tc[tc_sector_szQ])) 364fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - ((ULong*)(sectors[y].tc_next)); 365fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= 0); 366fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ <= tc_sector_szQ); 367fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 368fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (tcAvailQ < reqdQ 369fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR_USABLE) { 370fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* No. So move on to the next sector. Either it's never been 371fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj used before, in which case it will get its tt/tc allocated 372fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj now, or it has been used before, in which case it is set to be 373fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj empty, hence throwing out the oldest sector. */ 374fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector++; 375fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (youngest_sector >= N_SECTORS) 376fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector = 0; 377fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj y = youngest_sector; 378fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj initialiseSector(y); 379fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 38022854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 381fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Be sure ... */ 382fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tcAvailQ = ((ULong*)(§ors[y].tc[tc_sector_szQ])) 383fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - ((ULong*)(sectors[y].tc_next)); 384fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= 0); 385fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ <= tc_sector_szQ); 386fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= reqdQ); 387fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR_USABLE); 388fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[y].tt_n_inuse >= 0); 389fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 390fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Copy into tc. */ 391fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tce = sectors[y].tc_next; 392fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tce >= §ors[y].tc[0]); 393fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tce <= §ors[y].tc[tc_sector_szQ]); 394fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 395fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tce[0] = entry; 396fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj dstP = (UChar*)(&tce[1]); 397fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj srcP = (UChar*)code; 398fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < code_len; i++) 399fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj dstP[i] = srcP[i]; 400fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tc_next += reqdQ; 401fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt_n_inuse++; 402fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 403fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* more paranoia */ 404fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tce2 = sectors[y].tc_next; 405fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tce2 >= §ors[y].tc[0]); 406fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tce2 <= §ors[y].tc[tc_sector_szQ]); 407fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 408fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find an empty tt slot, and use it. There must be such a slot 409fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj since tt is never allowed to get completely full. */ 410fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i = HASH_TT(entry); 411fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(i >= 0 && i < N_TTES_PER_SECTOR); 41222854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj while (True) { 413fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[y].tt[i].status == Empty 414fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj || sectors[y].tt[i].status == Deleted) 415fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 416fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i++; 417fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (i >= N_TTES_PER_SECTOR) 418fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i = 0; 41922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj } 420fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 421fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].status = InUse; 422fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].tce = tce; 423fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].count = 0; 424fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].weight = 1; 425fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].vge = *vge; 426fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].entry = entry; 427fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 428fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj setFastCacheEntry( entry, tce, §ors[y].tt[i].count ); 42922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj} 43022854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 431fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 432fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address. If 433fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj requested, a successful search can also cause the fast-caches to be 434fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj updated. 435fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 436fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjBool VG_(search_transtab) ( /*OUT*/AddrH* result, 437fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Addr64 guest_addr, 438fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Bool upd_cache ) 4396c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 440fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int i, j, k, kstart, sno; 441663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 442663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 443fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find the initial probe point just once. It will be the same in 444fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj all sectors and avoids multiple expensive % operations. */ 445fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_full_lookups++; 446fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = -1; 447fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj kstart = HASH_TT(guest_addr); 448fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(kstart >= 0 && kstart < N_TTES_PER_SECTOR); 449fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 450fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Search in all the sectors. Although the order should not matter, 451fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj it might be most efficient to search in the order youngest to 452fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj oldest. */ 453fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sno = youngest_sector; 454fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_SECTORS; i++) { 455fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 456fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tc == NULL) 457fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj goto notfound; /* sector not in use. */ 458fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 459fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = kstart; 460fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (j = 0; j < N_TTES_PER_SECTOR; j++) { 461fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_lookup_probes++; 462fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[k].status == InUse 463fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj && sectors[sno].tt[k].entry == guest_addr) { 464fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* found it */ 465fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (upd_cache) 466fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj setFastCacheEntry( 467fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj guest_addr, sectors[sno].tt[k].tce, 468fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj §ors[sno].tt[k].count ); 469fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (result) 470fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj *result = sizeof(Addr64) + (AddrH)sectors[sno].tt[k].tce; 471fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 472fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 473fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[k].status == Empty) 474fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; /* not found in this sector */ 475fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k++; 476fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (k == N_TTES_PER_SECTOR) 477fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = 0; 4786c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 479fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 480fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* If we fall off the end, all entries are InUse and not 481fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj matching, or Deleted. In any case we did not find it in this 482fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. */ 483fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 484fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj notfound: 485fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* move to the next oldest sector */ 486fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sno = sno==0 ? (N_SECTORS-1) : (sno-1); 4876c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 488fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 489fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Not found in any sector. */ 490fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 4916c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 492de4a1d01951937632098a6cda45859afa587a06fsewardj 493de4a1d01951937632098a6cda45859afa587a06fsewardj 494fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Delete all translations which intersect with any part of the 495fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj specified guest address range. Note, this is SLOW. 496fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 497fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 498fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline 499fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjBool overlap1 ( Addr64 s1, UInt r1, Addr64 s2, UInt r2 ) 5006c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 501fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Addr64 e1 = s1 + (ULong)r1 - 1ULL; 502fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Addr64 e2 = s2 + (ULong)r1 - 1ULL; 503fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (e1 < s2 || e2 < s1) 504fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 505fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 5066c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 507de4a1d01951937632098a6cda45859afa587a06fsewardj 508fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline 509fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjBool overlaps ( Addr64 start, UInt range, VexGuestExtents* vge ) 5106c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 511fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (overlap1(start, range, vge->base[0], (UInt)vge->len[0])) 512fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 513fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (vge->n_used < 2) 514fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 515fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (overlap1(start, range, vge->base[1], (UInt)vge->len[1])) 516fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 517fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (vge->n_used < 3) 518fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 519fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (overlap1(start, range, vge->base[2], (UInt)vge->len[2])) 520fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 521fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 5226c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 523de4a1d01951937632098a6cda45859afa587a06fsewardj 524de4a1d01951937632098a6cda45859afa587a06fsewardj 525fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(discard_translations) ( Addr64 guest_start, UInt range ) 5266c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 527fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int sno, i; 528fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Bool anyDeleted = False; 5296c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 530663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 531663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 532fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (sno = 0; sno < N_SECTORS; sno++) { 533fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tc == NULL) 534fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 535fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 536fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[i].status == InUse 537fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj && overlaps( guest_start, range, §ors[sno].tt[i].vge )) { 538fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[sno].tt[i].status = Deleted; 539fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[sno].tt_n_inuse--; 540fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj anyDeleted = True; 541fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_disc_count++; 542fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_disc_osize += vge_osize(§ors[sno].tt[i].vge); 543fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 544fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 545de4a1d01951937632098a6cda45859afa587a06fsewardj } 546de4a1d01951937632098a6cda45859afa587a06fsewardj 547fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (anyDeleted) 548fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 549fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 5506c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 5516c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 552fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 553fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Sanity checking ---*/ 554fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 555de4a1d01951937632098a6cda45859afa587a06fsewardj 556fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(sanity_check_tt_tc) ( Char* who ) 557fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 5586c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 5596c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 5606c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 561fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 562fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation. ---*/ 563fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 564fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 565fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void ) 5666c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 567fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int i, avg_codeszQ; 568de4a1d01951937632098a6cda45859afa587a06fsewardj 569663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(!init_done); 570663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj init_done = True; 571663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 572fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Otherwise lots of things go wrong... */ 573fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sizeof(ULong) == 8); 574fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sizeof(Addr64) == 8); 575de4a1d01951937632098a6cda45859afa587a06fsewardj 576fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 577fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 578fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "TT/TC: VG_(init_tt_tc) " 579fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "(startup of code management)"); 580fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 581fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Figure out how big each tc area should be. */ 58243b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn avg_codeszQ = (VG_(details).avg_translation_sizeB + 7) / 8; 58343b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn tc_sector_szQ = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ); 584fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 585fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Ensure the calculated value is not way crazy. */ 586fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR_USABLE); 587fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tc_sector_szQ <= 50 * N_TTES_PER_SECTOR_USABLE); 588fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 589fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Initialise the sectors */ 590fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector = 0; 591fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_SECTORS; i++) { 592fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tc = NULL; 593fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tt = NULL; 594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tc_next = NULL; 595fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tt_n_inuse = 0; 5966c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 5974ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 598fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* and the fast caches. */ 599fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 600fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 601fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) { 602fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 603fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "TT/TC: cache: %d sectors of %d bytes each = %d total", 604fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS, 8 * tc_sector_szQ, 605fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS * 8 * tc_sector_szQ ); 606fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 607fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "TT/TC: table: %d total entries, max occupancy %d (%d%%)", 608fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS * N_TTES_PER_SECTOR, 609fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS * N_TTES_PER_SECTOR_USABLE, 610fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj SECTOR_TT_LIMIT_PERCENT ); 611fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 612de4a1d01951937632098a6cda45859afa587a06fsewardj} 613de4a1d01951937632098a6cda45859afa587a06fsewardj 6144ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 615fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 616fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics. ---*/ 617fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 618fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 619fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong safe_idiv( ULong a, ULong b ) 62092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{ 62192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote return (b == 0 ? 0 : a / b); 62292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote} 62392e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote 624fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void ) 625fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 626fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return n_in_count; 627fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 628fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 629fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void ) 63092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{ 63192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 632fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj " tt/tc: %llu tt lookups requiring %llu probes", 633fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_full_lookups, n_lookup_probes ); 63492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 635fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj " tt/tc: %llu fast-cache updates, %llu flushes", 636fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_updates, n_fast_flushes ); 637fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 63892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 639fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "translate: new %lld (%lld -> %lld; ratio %lld:10)", 640fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_count, n_in_osize, n_in_tsize, 641fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj safe_idiv(10*n_in_tsize, n_in_osize)); 64292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 643fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "translate: dumped %lld (%lld -> ?" "?)", 644fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_dump_count, n_dump_osize ); 645fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 646fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "translate: discarded %lld (%lld -> ?" "?)", 647fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_disc_count, n_disc_osize ); 64892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote} 649de4a1d01951937632098a6cda45859afa587a06fsewardj 650fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 651fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results. ---*/ 652fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 6534ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 654fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Only the top N_MAX bbs will be displayed. */ 655f9f1949469b24847644c3ae9d62773f97ae1b994sewardj#define N_MAX 200 656c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 657fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic TTEntry* tops[N_MAX]; 658c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 659fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong score ( TTEntry* tte ) 660fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 661fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return ((ULong)tte->weight) * ((ULong)tte->count); 662de4a1d01951937632098a6cda45859afa587a06fsewardj} 663de4a1d01951937632098a6cda45859afa587a06fsewardj 664fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Bool heavier ( TTEntry* t1, TTEntry* t2 ) 665fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 666fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return score(t1) > score(t2); 667fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 668de4a1d01951937632098a6cda45859afa587a06fsewardj 669fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Print n/m in form xx.yy% */ 670fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic 671fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid percentify ( ULong n, ULong m, Int field_width, Char* buf) 672de4a1d01951937632098a6cda45859afa587a06fsewardj{ 673fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int i, len, space; 674fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong lo, hi; 675fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (m == 0) m = 1; /* stay sane */ 676fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj hi = (n * 100) / m; 677fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj lo = (((n * 100) - hi * m) * 100) / m; 678fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(lo < 100); 679fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (lo < 10) 680fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(sprintf)(buf, "%lld.0%lld%%", hi, lo); 681fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj else 682fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(sprintf)(buf, "%lld.%lld%%", hi, lo); 683fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 684fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj len = VG_(strlen)(buf); 685fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj space = field_width - len; 686fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (space < 0) space = 0; /* Allow for v. small field_width */ 687fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i = len; 688fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 689fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Right justify in field */ 690fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for ( ; i >= 0; i--) buf[i + space] = buf[i]; 691fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < space; i++) buf[i] = ' '; 692de4a1d01951937632098a6cda45859afa587a06fsewardj} 693de4a1d01951937632098a6cda45859afa587a06fsewardj 694de4a1d01951937632098a6cda45859afa587a06fsewardj 695fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(show_BB_profile) ( void ) 696de4a1d01951937632098a6cda45859afa587a06fsewardj{ 697fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Char name[64]; 698fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int sno, i, r, s; 699fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong score_total, score_cumul, score_here; 700fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Char buf_cumul[10]; 701fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Char buf_here[10]; 702fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 703fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* First, compute the total weighted count, and find the top N 704fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ttes. tops contains pointers to the most-used N_MAX blocks, in 705fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj descending order (viz, tops[0] is the highest scorer). */ 706fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_MAX; i++) 707fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tops[i] = NULL; 708fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 709fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_total = 0; 710fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 711fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (sno = 0; sno < N_SECTORS; sno++) { 712fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tc == NULL) 71318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj continue; 714fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 715fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[i].status != InUse) 716fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 717fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_total += score(§ors[sno].tt[i]); 718fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find the rank for sectors[sno].tt[i]. */ 719fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r = N_MAX-1; 720fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj while (True) { 721fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (r == -1) 722fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 723fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (tops[r] == NULL) { 724fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r--; 725fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 726fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 727fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (heavier(§ors[sno].tt[i], tops[r])) { 728fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r--; 729fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 730fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 731fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 732fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 733fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r++; 734fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(r >= 0 && r <= N_MAX); 735fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This bb should be placed at r, and bbs above it shifted 736fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj upwards one slot. */ 737fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (r < N_MAX) { 738fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (s = N_MAX-1; s > r; s--) 739fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tops[s] = tops[s-1]; 740fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tops[r] = §ors[sno].tt[i]; 741fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 742de4a1d01951937632098a6cda45859afa587a06fsewardj } 743de4a1d01951937632098a6cda45859afa587a06fsewardj } 744de4a1d01951937632098a6cda45859afa587a06fsewardj 745fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("\n"); 746fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("------------------------------------------------------------\n"); 747fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n"); 748fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("------------------------------------------------------------\n"); 749fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("\n"); 750de4a1d01951937632098a6cda45859afa587a06fsewardj 751fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("Total score = %lld\n\n", score_total); 752de4a1d01951937632098a6cda45859afa587a06fsewardj 753fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_cumul = 0; 754fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (r = 0; r < N_MAX; r++) { 755fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (tops[r] == NULL) 756fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 757fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj name[0] = 0; 758fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(get_fnname_w_offset)(tops[r]->entry, name, 64); 759fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj name[63] = 0; 760fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_here = score(tops[r]); 761fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_cumul += score_here; 762fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj percentify(score_cumul, score_total, 6, buf_cumul); 763fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj percentify(score_here, score_total, 6, buf_here); 764fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n", 765fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r, 766fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_cumul, buf_cumul, 767fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_here, buf_here, tops[r]->entry, name ); 768c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj } 769c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 770fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("\n"); 771fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("------------------------------------------------------------\n"); 772fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("--- BB Profile (BB details) ---\n"); 773fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("------------------------------------------------------------\n"); 774fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("\n"); 775c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 776fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_cumul = 0; 777fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (r = 0; r < N_MAX; r++) { 778fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (tops[r] == NULL) 779fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 780fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj name[0] = 0; 781fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(get_fnname_w_offset)(tops[r]->entry, name, 64); 782fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj name[63] = 0; 783fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_here = score(tops[r]); 784fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_cumul += score_here; 785fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj percentify(score_cumul, score_total, 6, buf_cumul); 786fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj percentify(score_here, score_total, 6, buf_here); 787fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("\n"); 788fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d " 789fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r); 790fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n", 791fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r, 792fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_cumul, buf_cumul, 793fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_here, buf_here, tops[r]->entry, name ); 794fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("\n"); 795fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(translate)(0, tops[r]->entry, True, VG_(clo_profile_flags)); 796fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d " 797fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r); 798c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj } 799c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 800fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("\n"); 801fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("------------------------------------------------------------\n"); 802fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("--- END BB Profile ---\n"); 803fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("------------------------------------------------------------\n"); 804fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(printf)("\n"); 805c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj} 806c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 807fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 808de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 8098bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end ---*/ 810de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 811