m_transtab.c revision 3a5322057616d0da214b9e0f897866e203c03e40
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 1103f8d3fc25f5a45c5826259d1b33b7f310117279sewardj Copyright (C) 2000-2012 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" 34291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_machine.h" // For VG_(machine_get_VexArchInfo) 3597405b2d134b52880d6dbec3eb2929e2002c2542njn#include "pub_core_libcbase.h" 36291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_vki.h" // to keep pub_core_libproc.h happy, sigh 37291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_libcproc.h" // VG_(invalidate_icache) 38132bfccd21960e462352175f8553a5bdce8a210cnjn#include "pub_core_libcassert.h" 3936a20fa5f779a0a6fb7b4a90dcaa6376481f1faanjn#include "pub_core_libcprint.h" 402024234c590f408994b373abfb00bc2cd2a90c48njn#include "pub_core_options.h" 4110f08cf5b84882eebbb6712a7be890577650e8adsewardj#include "pub_core_tooliface.h" // For VG_(details).avg_translation_sizeB 428bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn#include "pub_core_transtab.h" 4345f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_aspacemgr.h" 4445f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_mallocfree.h" // VG_(out_of_memory_NORETURN) 45291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_xarray.h" 46291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_dispatch.h" // For VG_(disp_cp*) addresses 4759570ffbe31930ab4d678754daaeec0715117a3dsewardj 4859570ffbe31930ab4d678754daaeec0715117a3dsewardj 493a5322057616d0da214b9e0f897866e203c03e40philippe#define DEBUG_TRANSTAB 0 5018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj 51de4a1d01951937632098a6cda45859afa587a06fsewardj 526c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/ 536c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*--- Management of the FIFO-based translation table+cache. ---*/ 546c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/ 55de4a1d01951937632098a6cda45859afa587a06fsewardj 566c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ CONSTANTS ------------------*/ 57de4a1d01951937632098a6cda45859afa587a06fsewardj 58fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of sectors the TC is divided into. If you need a larger 59fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj overall translation cache, increase this value. */ 60fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_SECTORS 8 61de4a1d01951937632098a6cda45859afa587a06fsewardj 62fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of TC entries in each sector. This needs to be a prime 636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj number to work properly, it must be <= 65535 (so that a TT index 646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj fits in a UShort, leaving room for 0xFFFF(EC2TTE_DELETED) to denote 656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 'deleted') and it is strongly recommended not to change this. 666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 65521 is the largest prime <= 65535. */ 67e25053c5aaefc6a4039dcd557adf24d8bb23db69sewardj#define N_TTES_PER_SECTOR /*10007*/ /*30011*/ /*40009*/ 65521 68de4a1d01951937632098a6cda45859afa587a06fsewardj 69fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to 70fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj specify the maximum allowable loading, after which the sector is 71fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj deemed full. */ 725d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj#define SECTOR_TT_LIMIT_PERCENT 65 73de4a1d01951937632098a6cda45859afa587a06fsewardj 74fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */ 75fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_TTES_PER_SECTOR_USABLE \ 76fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ((N_TTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100) 776c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Equivalence classes for fast address range deletion. There are 1 + 796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 2^ECLASS_WIDTH bins. The highest one, ECLASS_MISC, describes an 806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range which does not fall cleanly within any specific bin. 816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Note that ECLASS_SHIFT + ECLASS_WIDTH must be < 32. */ 826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_SHIFT 11 836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_WIDTH 8 846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_MISC (1 << ECLASS_WIDTH) 856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_N (1 + ECLASS_MISC) 866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define EC2TTE_DELETED 0xFFFF /* 16-bit special value */ 886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 89de4a1d01951937632098a6cda45859afa587a06fsewardj 906c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/ 91de4a1d01951937632098a6cda45859afa587a06fsewardj 92291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* In edges ("to-me") in the graph created by chaining. */ 93291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 94291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 95291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_sNo; /* sector number */ 96291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_tteNo; /* TTE number in given sector */ 97291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_offs; /* code offset from TCEntry::tcptr where the patch is */ 98291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool to_fastEP; /* Is the patch to a fast or slow entry point? */ 99291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 100291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge; 101291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 102291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 103291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Out edges ("from-me") in the graph created by chaining. */ 104291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 105291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 106291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt to_sNo; /* sector number */ 107291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt to_tteNo; /* TTE number in given sector */ 108291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_offs; /* code offset in owning translation where patch is */ 109291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 110291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge; 111291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 112291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 113291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_IN_EDGE_ARR 3 114291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 115291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 116291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt n_fixed; /* 0 .. N_FIXED_IN_EDGE_ARR */ 117291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge fixed[N_FIXED_IN_EDGE_ARR]; 118291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* var; /* XArray* of InEdgeArr */ 119291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 120291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr; 121291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 122291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_OUT_EDGE_ARR 2 123291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 124291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 125291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt n_fixed; /* 0 .. N_FIXED_OUT_EDGE_ARR */ 126291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge fixed[N_FIXED_OUT_EDGE_ARR]; 127291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* var; /* XArray* of OutEdgeArr */ 128291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 129291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr; 130291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 131291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 132fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry. This indicates precisely which areas of 133fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj guest code are included in the translation, and contains all other 134fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj auxiliary info too. */ 1356c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef 1366c3769f487145a08c01b58d6e5db3ba274062ad4sewardj struct { 137fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Profiling only: the count and weight (arbitrary meaning) for 138fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj this translation. Weight is a property of the translation 139fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj itself and computed once when the translation is created. 140fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Count is an entry count for the translation and is 141fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj incremented by 1 every time the translation is used, if we 142fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj are profiling. */ 143291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ULong count; 144fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UShort weight; 145fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 146fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Status of the slot. Note, we need to be able to do lazy 147fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj deletion, hence the Deleted state. */ 148fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj enum { InUse, Deleted, Empty } status; 149fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1505f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* 64-bit aligned pointer to one or more 64-bit words containing 1515f76de086a6d643db51e50a4e623df7dfc9b6161sewardj the corresponding host code (must be in the same sector!) 1525f76de086a6d643db51e50a4e623df7dfc9b6161sewardj This is a pointer into the sector's tc (code) area. */ 1535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj ULong* tcptr; 154fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 155fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This is the original guest address that purportedly is the 156fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj entry point of the translation. You might think that .entry 157fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj should be the same as .vge->base[0], and most of the time it 158fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj is. However, when doing redirections, that is not the case. 159fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj .vge must always correctly describe the guest code sections 160fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj from which this translation was made. However, .entry may or 161fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj may not be a lie, depending on whether or not we're doing 162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj redirection. */ 163fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Addr64 entry; 164fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This structure describes precisely what ranges of guest code 166fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj the translation covers, so we can decide whether or not to 167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj delete it when translations of a given address range are 168fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidated. */ 169fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VexGuestExtents vge; 1706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Address range summary info: these are pointers back to 1726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclass[] entries in the containing Sector. Those entries in 1736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj turn point back here -- the two structures are mutually 1746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj redundant but both necessary to make fast deletions work. 1756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj The eclass info is similar to, and derived from, this entry's 1766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 'vge' field, but it is not the same */ 1776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort n_tte2ec; // # tte2ec pointers (1 to 3) 1786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort tte2ec_ec[3]; // for each, the eclass # 1796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt tte2ec_ix[3]; // and the index within the eclass. 1806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // for i in 0 .. n_tte2ec-1 1816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // sec->ec2tte[ tte2ec_ec[i] ][ tte2ec_ix[i] ] 1826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // should be the index 1836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // of this TTEntry in the containing Sector's tt array. 184291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 185291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Admin information for chaining. 'in_edges' is a set of the 186291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj patch points which jump to this translation -- hence are 187291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj predecessors in the control flow graph. 'out_edges' points 188291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj to successors in the control flow graph -- translations to 189291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj which this one has a patched jump. In short these are just 190291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj backwards and forwards edges in the graph of patched-together 191291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj blocks. The 'in_edges' contain slightly more info, enough 192291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj that we can undo the chaining of each mentioned patch point. 193291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The 'out_edges' list exists only so that we can visit the 194291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 'in_edges' entries of all blocks we're patched through to, in 195291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj order to remove ourselves from then when we're deleted. */ 196291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 197291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* A translation can disappear for two reasons: 198291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 1. erased (as part of the oldest sector cleanup) when the 199291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj youngest sector is full. 200291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 2. discarded due to calls to VG_(discard_translations). 201291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(discard_translations) sets the status of the 202291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation to 'Deleted'. 203291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj A.o., the gdbserver discards one or more translations 204291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj when a breakpoint is inserted or removed at an Addr, 205291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj or when single stepping mode is enabled/disabled 206291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj or when a translation is instrumented for gdbserver 207291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (all the target jumps of this translation are 208291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj invalidated). 209291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 210291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj So, it is possible that the translation A to be patched 211291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (to obtain a patched jump from A to B) is invalidated 212291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj after B is translated and before A is patched. 213291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj In case a translation is erased or discarded, the patching 214291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj cannot be done. VG_(tt_tc_do_chaining) and find_TTEntry_from_hcode 215291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj are checking the 'from' translation still exists before 216291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj doing the patching. 217291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 218291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Is it safe to erase or discard the current translation E being 219291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj executed ? Amazing, but yes, it is safe. 220291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Here is the explanation: 221291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 222291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The translation E being executed can only be erased if a new 223291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation N is being done. A new translation is done only 224291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if the host addr is a not yet patched jump to another 225291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation. In such a case, the guest address of N is 226291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj assigned to the PC in the VEX state. Control is returned 227291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj to the scheduler. N will be translated. This can erase the 228291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation E (in case of sector full). VG_(tt_tc_do_chaining) 229291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj will not do the chaining to a non found translation E. 230291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The execution will continue at the current guest PC 231291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (i.e. the translation N). 232291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj => it is safe to erase the current translation being executed. 233291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 234291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The current translation E being executed can also be discarded 235291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (e.g. by gdbserver). VG_(discard_translations) will mark 236291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj this translation E as Deleted, but the translation itself 237291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj is not erased. In particular, its host code can only 238291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj be overwritten or erased in case a new translation is done. 239291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj A new translation will only be done if a not yet translated 240291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj jump is to be executed. The execution of the Deleted translation 241291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj E will continue till a non patched jump is encountered. 242291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj This situation is then similar to the 'erasing' case above : 243291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj the current translation E can be erased or overwritten, as the 244291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj execution will continue at the new translation N. 245291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 246291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj */ 247291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 248291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* It is possible, although very unlikely, that a block A has 249291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj more than one patched jump to block B. This could happen if 250291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (eg) A finishes "jcond B; jmp B". 251291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 252291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj This means in turn that B's in_edges set can list A more than 253291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj once (twice in this example). However, each such entry must 254291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj have a different from_offs, since a patched jump can only 255291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj jump to one place at once (it's meaningless for it to have 256291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj multiple destinations.) IOW, the successor and predecessor 257291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj edges in the graph are not uniquely determined by a 258291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry --> TTEntry pair, but rather by a 259291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (TTEntry,offset) --> TTEntry triple. 260291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 261291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj If A has multiple edges to B then B will mention A multiple 262291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj times in its in_edges. To make things simpler, we then 263291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj require that A mentions B exactly the same number of times in 264291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj its out_edges. Furthermore, a matching out-in pair must have 265291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj the same offset (from_offs). This facilitates sanity 266291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj checking, and it facilitates establishing the invariant that 267291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj a out_edges set may not have duplicates when using the 268291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj equality defined by (TTEntry,offset). Hence the out_edges 269291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj and in_edges sets really do have both have set semantics. 270291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 271291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj eg if A has been patched to B at offsets 42 and 87 (in A) 272291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj then A.out_edges = { (B,42), (B,87) } (in any order) 273291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj and B.in_edges = { (A,42), (A,87) } (in any order) 274291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 275291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Hence for each node pair P->Q in the graph, there's a 1:1 276291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj mapping between P.out_edges and Q.in_edges. 277291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj */ 278291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr in_edges; 279291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr out_edges; 2806c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 2816c3769f487145a08c01b58d6e5db3ba274062ad4sewardj TTEntry; 2826c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 2834ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 284291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* A structure used for mapping host code addresses back to the 285291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj relevant TTEntry. Used when doing chaining, for finding the 286291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry to which some arbitrary patch address belongs. */ 287291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 288291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 289291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* start; 290291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt len; 291291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt tteNo; 292291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 293291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent; 294291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 295fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself. Each sector contains an array of 296fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TCEntries, which hold code, and an array of TTEntries, containing 297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj all required administrative info. Profiling is supported using the 298291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry .count and .weight fields, if required. 2994ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 300fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj If the sector is not in use, all three pointers are NULL and 301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tt_n_inuse is zero. 302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 303fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef 304fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj struct { 305fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The TCEntry area. Size of this depends on the average 306fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj translation size. We try and size it so it becomes full 307fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj precisely when this sector's translation table (tt) reaches 308fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj its load limit (SECTOR_TT_LIMIT_PERCENT). */ 309fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tc; 3104ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 311fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The TTEntry array. This is a fixed size, always containing 312fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj exactly N_TTES_PER_SECTOR entries. */ 313fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TTEntry* tt; 3146c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 315fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This points to the current allocation point in tc. */ 316fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tc_next; 317de4a1d01951937632098a6cda45859afa587a06fsewardj 318fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The count of tt entries with state InUse. */ 319fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int tt_n_inuse; 3206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Expandable arrays of tt indices for each of the ECLASS_N 3226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range equivalence classes. These hold indices into 3236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj the containing sector's tt array, which in turn should point 3246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj back here. */ 3256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int ec2tte_size[ECLASS_N]; 3266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int ec2tte_used[ECLASS_N]; 3276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort* ec2tte[ECLASS_N]; 328291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 329291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* The host extents. The [start, +len) ranges are constructed 330291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj in strictly non-overlapping order, so we can binary search 331291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj them at any time. */ 332291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* host_extents; /* XArray* of HostExtent */ 333fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 334fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Sector; 335de4a1d01951937632098a6cda45859afa587a06fsewardj 336de4a1d01951937632098a6cda45859afa587a06fsewardj 3376c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/ 3386c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 339fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors. The index of the 340fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest sector is recorded, and new translations are put into that 341fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. When it fills up, we move along to the next sector and 342fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj start to fill that up, wrapping around at the end of the array. 343fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj That way, once all N_TC_SECTORS have been bought into use for the 344fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj first time, and are full, we then re-use the oldest sector, 345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj endlessly. 346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj When running, youngest sector should be between >= 0 and < 348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_TC_SECTORS. The initial -1 value indicates the TT/TC system is 349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj not yet initialised. 350fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Sector sectors[N_SECTORS]; 352fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int youngest_sector = -1; 3536c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 354fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area. This is computed once 355fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj at startup and does not change. */ 356fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int tc_sector_szQ; 3576c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 3586c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 3595d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj/* A list of sector numbers, in the order which they should be 3605d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj searched to find translations. This is an optimisation to be used 3615d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj when searching for translations and should not affect 3625d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj correctness. -1 denotes "no entry". */ 3635d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardjstatic Int sector_search_order[N_SECTORS]; 3645d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 3655d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 3665f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Fast helper for the TC. A direct-mapped cache which holds a set of 3675f76de086a6d643db51e50a4e623df7dfc9b6161sewardj recently used (guest address, host address) pairs. This array is 3685f76de086a6d643db51e50a4e623df7dfc9b6161sewardj referred to directly from m_dispatch/dispatch-<platform>.S. 3696c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 3705f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Entries in tt_fast may refer to any valid TC entry, regardless of 371fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj which sector it's in. Consequently we must be very careful to 372fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidate this cache when TC entries are changed or disappear. 373c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 3745f76de086a6d643db51e50a4e623df7dfc9b6161sewardj A special .guest address - TRANSTAB_BOGUS_GUEST_ADDR -- must be 3755f76de086a6d643db51e50a4e623df7dfc9b6161sewardj pointed at to cause that cache entry to miss. This relies on the 3765f76de086a6d643db51e50a4e623df7dfc9b6161sewardj assumption that no guest code actually has that address, hence a 3775f76de086a6d643db51e50a4e623df7dfc9b6161sewardj value 0x1 seems good. m_translate gives the client a synthetic 3785f76de086a6d643db51e50a4e623df7dfc9b6161sewardj segfault if it tries to execute at this address. 3795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/ 3805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* 3815f76de086a6d643db51e50a4e623df7dfc9b6161sewardjtypedef 3825f76de086a6d643db51e50a4e623df7dfc9b6161sewardj struct { 3835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Addr guest; 3845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Addr host; 3855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 3865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj FastCacheEntry; 3875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/ 3885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*global*/ __attribute__((aligned(16))) 3895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj FastCacheEntry VG_(tt_fast)[VG_TT_FAST_SIZE]; 390de4a1d01951937632098a6cda45859afa587a06fsewardj 391663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */ 392663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False; 393663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 394663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 395fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/ 396de4a1d01951937632098a6cda45859afa587a06fsewardj 397fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */ 398291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_flushes = 0; 399291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_updates = 0; 40022854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 401fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */ 402291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_full_lookups = 0; 403291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_lookup_probes = 0; 40422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 40526412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj/* Number/osize/tsize of translations entered; also the number of 40626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj those for which self-checking was requested. */ 407291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_count = 0; 408291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_osize = 0; 409291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_tsize = 0; 410291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_sc_count = 0; 411de4a1d01951937632098a6cda45859afa587a06fsewardj 412fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */ 413291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_count = 0; 414291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_osize = 0; 415fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 416fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */ 417291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_count = 0; 418291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_osize = 0; 419291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 420291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 421291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 422291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Misc ---*/ 423291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 424291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 42554fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorianstatic void* ttaux_malloc ( const HChar* tag, SizeT n ) 426291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 427291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return VG_(arena_malloc)(VG_AR_TTAUX, tag, n); 428291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 429291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 430291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void ttaux_free ( void* p ) 431291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 432291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(arena_free)(VG_AR_TTAUX, p); 433291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 434291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 435291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 436291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 437291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Chaining support ---*/ 438291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 439291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 440291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic inline TTEntry* index_tte ( UInt sNo, UInt tteNo ) 441291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 442291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sNo < N_SECTORS); 443291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(tteNo < N_TTES_PER_SECTOR); 444291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Sector* s = §ors[sNo]; 445291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(s->tt); 446291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* tte = &s->tt[tteNo]; 447291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(tte->status == InUse); 448291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return tte; 449291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 450291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 451291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdge__init ( InEdge* ie ) 452291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 453291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->from_sNo = -1; /* invalid */ 454291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->from_tteNo = 0; 455291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->from_offs = 0; 456291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->to_fastEP = False; 457291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 458291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 459291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdge__init ( OutEdge* oe ) 460291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 461291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe->to_sNo = -1; /* invalid */ 462291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe->to_tteNo = 0; 463291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe->from_offs = 0; 464291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 465291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 466291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void TTEntry__init ( TTEntry* tte ) 467291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 468291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(memset)(tte, 0, sizeof(*tte)); 469291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 470291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 471291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic UWord InEdgeArr__size ( InEdgeArr* iea ) 472291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 473291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->var) { 474291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 475291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return VG_(sizeXA)(iea->var); 476291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 477291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR); 478291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return iea->n_fixed; 479291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 480291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 481291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 482291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdgeArr__makeEmpty ( InEdgeArr* iea ) 483291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 484291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->var) { 485291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 486291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(deleteXA)(iea->var); 487291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->var = NULL; 488291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 489291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR); 490291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->n_fixed = 0; 491291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 492291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 493291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 494291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 495291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjInEdge* InEdgeArr__index ( InEdgeArr* iea, UWord i ) 496291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 497291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->var) { 498291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 499291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return (InEdge*)VG_(indexXA)(iea->var, i); 500291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 501291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < iea->n_fixed); 502291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return &iea->fixed[i]; 503291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 504291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 505291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 506291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 507291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__deleteIndex ( InEdgeArr* iea, UWord i ) 508291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 509291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->var) { 510291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 511291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(removeIndexXA)(iea->var, i); 512291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 513291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < iea->n_fixed); 514291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (; i+1 < iea->n_fixed; i++) { 515291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->fixed[i] = iea->fixed[i+1]; 516291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 517291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->n_fixed--; 518291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 519291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 520291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 521291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 522291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__add ( InEdgeArr* iea, InEdge* ie ) 523291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 524291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->var) { 525291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 526291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(iea->var, ie); 527291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 528291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR); 529291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->n_fixed == N_FIXED_IN_EDGE_ARR) { 530291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* The fixed array is full, so we have to initialise an 531291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray and copy the fixed array into it. */ 532291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->var = VG_(newXA)(ttaux_malloc, "transtab.IEA__add", 533291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free, 534291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sizeof(InEdge)); 535291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UWord i; 536291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < iea->n_fixed; i++) { 537291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(iea->var, &iea->fixed[i]); 538291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 539291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(iea->var, ie); 540291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->n_fixed = 0; 541291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 542291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Just add to the fixed array. */ 543291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->fixed[iea->n_fixed++] = *ie; 544291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 545291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 546291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 547291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 548291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic UWord OutEdgeArr__size ( OutEdgeArr* oea ) 549291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 550291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->var) { 551291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 552291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return VG_(sizeXA)(oea->var); 553291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 554291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR); 555291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return oea->n_fixed; 556291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 557291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 558291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 559291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdgeArr__makeEmpty ( OutEdgeArr* oea ) 560291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 561291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->var) { 562291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 563291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(deleteXA)(oea->var); 564291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->var = NULL; 565291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 566291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR); 567291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->n_fixed = 0; 568291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 569291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 570291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 571291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 572291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjOutEdge* OutEdgeArr__index ( OutEdgeArr* oea, UWord i ) 573291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 574291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->var) { 575291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 576291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return (OutEdge*)VG_(indexXA)(oea->var, i); 577291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 578291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < oea->n_fixed); 579291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return &oea->fixed[i]; 580291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 581291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 582291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 583291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 584291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__deleteIndex ( OutEdgeArr* oea, UWord i ) 585291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 586291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->var) { 587291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 588291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(removeIndexXA)(oea->var, i); 589291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 590291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < oea->n_fixed); 591291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (; i+1 < oea->n_fixed; i++) { 592291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->fixed[i] = oea->fixed[i+1]; 593291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 594291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->n_fixed--; 595291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 596291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 597291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 598291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 599291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__add ( OutEdgeArr* oea, OutEdge* oe ) 600291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 601291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->var) { 602291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 603291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(oea->var, oe); 604291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 605291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR); 606291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->n_fixed == N_FIXED_OUT_EDGE_ARR) { 607291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* The fixed array is full, so we have to initialise an 608291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray and copy the fixed array into it. */ 609291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->var = VG_(newXA)(ttaux_malloc, "transtab.OEA__add", 610291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free, 611291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sizeof(OutEdge)); 612291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UWord i; 613291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < oea->n_fixed; i++) { 614291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(oea->var, &oea->fixed[i]); 615291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 616291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(oea->var, oe); 617291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->n_fixed = 0; 618291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 619291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Just add to the fixed array. */ 620291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->fixed[oea->n_fixed++] = *oe; 621291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 622291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 623291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 624291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 625291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 6266bd9dc18c043927c1196caba20a327238a179c42florianInt HostExtent__cmpOrd ( const void* v1, const void* v2 ) 627291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 6286bd9dc18c043927c1196caba20a327238a179c42florian const HostExtent* hx1 = v1; 6296bd9dc18c043927c1196caba20a327238a179c42florian const HostExtent* hx2 = v2; 630291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (hx1->start + hx1->len <= hx2->start) return -1; 631291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (hx2->start + hx2->len <= hx1->start) return 1; 632291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return 0; /* partial overlap */ 633291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 634291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 6353a5322057616d0da214b9e0f897866e203c03e40philippe/* True if hx is a dead host extent, i.e. corresponds to host code 6363a5322057616d0da214b9e0f897866e203c03e40philippe of an entry that was invalidated. */ 6373a5322057616d0da214b9e0f897866e203c03e40philippestatic 6383a5322057616d0da214b9e0f897866e203c03e40philippeBool HostExtent__is_dead (const HostExtent* hx, const Sector* sec) 6393a5322057616d0da214b9e0f897866e203c03e40philippe{ 6403a5322057616d0da214b9e0f897866e203c03e40philippe const UInt tteNo = hx->tteNo; 6413a5322057616d0da214b9e0f897866e203c03e40philippe#define LDEBUG(m) if (DEBUG_TRANSTAB) \ 6423a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf) (m \ 6433a5322057616d0da214b9e0f897866e203c03e40philippe " start 0x%p len %u sector %d ttslot %u" \ 6443a5322057616d0da214b9e0f897866e203c03e40philippe " tt.entry 0x%llu tt.tcptr 0x%p\n", \ 6453a5322057616d0da214b9e0f897866e203c03e40philippe hx->start, hx->len, (int)(sec - sectors), \ 6463a5322057616d0da214b9e0f897866e203c03e40philippe hx->tteNo, \ 6473a5322057616d0da214b9e0f897866e203c03e40philippe sec->tt[tteNo].entry, sec->tt[tteNo].tcptr) 6483a5322057616d0da214b9e0f897866e203c03e40philippe 6493a5322057616d0da214b9e0f897866e203c03e40philippe /* Entry might have been invalidated and not re-used yet.*/ 6503a5322057616d0da214b9e0f897866e203c03e40philippe if (sec->tt[tteNo].status == Deleted) { 6513a5322057616d0da214b9e0f897866e203c03e40philippe LDEBUG("found deleted entry"); 6523a5322057616d0da214b9e0f897866e203c03e40philippe return True; 6533a5322057616d0da214b9e0f897866e203c03e40philippe } 6543a5322057616d0da214b9e0f897866e203c03e40philippe /* Maybe we found this entry via a host_extents which was 6553a5322057616d0da214b9e0f897866e203c03e40philippe inserted for an entry which was changed to Deleted then 6563a5322057616d0da214b9e0f897866e203c03e40philippe re-used after. If this entry was re-used, then its tcptr 6573a5322057616d0da214b9e0f897866e203c03e40philippe is >= to host_extents start (i.e. the previous tcptr) + len. 6583a5322057616d0da214b9e0f897866e203c03e40philippe This is the case as there is no re-use of host code: a new 6593a5322057616d0da214b9e0f897866e203c03e40philippe entry or re-used entry always gets "higher value" host code. */ 6603a5322057616d0da214b9e0f897866e203c03e40philippe if ((UChar*) sec->tt[tteNo].tcptr >= hx->start + hx->len) { 6613a5322057616d0da214b9e0f897866e203c03e40philippe LDEBUG("found re-used entry"); 6623a5322057616d0da214b9e0f897866e203c03e40philippe return True; 6633a5322057616d0da214b9e0f897866e203c03e40philippe } 6643a5322057616d0da214b9e0f897866e203c03e40philippe 6653a5322057616d0da214b9e0f897866e203c03e40philippe return False; 6663a5322057616d0da214b9e0f897866e203c03e40philippe#undef LDEBUG 6673a5322057616d0da214b9e0f897866e203c03e40philippe} 6683a5322057616d0da214b9e0f897866e203c03e40philippe 669291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic __attribute__((noinline)) 670291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool find_TTEntry_from_hcode( /*OUT*/UInt* from_sNo, 671291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /*OUT*/UInt* from_tteNo, 672291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj void* hcode ) 673291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 674291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int i; 675291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 676291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Search order logic copied from VG_(search_transtab). */ 677291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < N_SECTORS; i++) { 678291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int sno = sector_search_order[i]; 679291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (UNLIKELY(sno == -1)) 680291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; /* run out of sectors to search */ 681291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 682291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Sector* sec = §ors[sno]; 683291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* /* of HostExtent */ host_extents = sec->host_extents; 684291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(host_extents); 685291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 686291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent key; 687291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(memset)(&key, 0, sizeof(key)); 688291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj key.start = hcode; 689291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj key.len = 1; 690291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Word firstW = -1, lastW = -1; 691291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool found = VG_(lookupXA_UNSAFE)( 692291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj host_extents, &key, &firstW, &lastW, 6936bd9dc18c043927c1196caba20a327238a179c42florian HostExtent__cmpOrd ); 694291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(firstW == lastW); // always true, even if not found 695291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (found) { 696291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent* hx = VG_(indexXA)(host_extents, firstW); 697291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt tteNo = hx->tteNo; 698291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Do some additional sanity checks. */ 699291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(tteNo <= N_TTES_PER_SECTOR); 7003a5322057616d0da214b9e0f897866e203c03e40philippe 7013a5322057616d0da214b9e0f897866e203c03e40philippe /* if this hx entry corresponds to dead host code, we must 7023a5322057616d0da214b9e0f897866e203c03e40philippe tell this code has not been found, as it cannot be patched. */ 7033a5322057616d0da214b9e0f897866e203c03e40philippe if (HostExtent__is_dead (hx, sec)) 704291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; 7053a5322057616d0da214b9e0f897866e203c03e40philippe 706291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec->tt[tteNo].status == InUse); 707291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Can only half check that the found TTEntry contains hcode, 708291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj due to not having a length value for the hcode in the 709291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry. */ 710291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert((UChar*)sec->tt[tteNo].tcptr <= (UChar*)hcode); 711291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Looks plausible */ 712291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *from_sNo = sno; 713291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *from_tteNo = (UInt)tteNo; 714291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return True; 715291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 716291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; 718291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 720291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 721291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Figure out whether or not hcode is jitted code present in the main 722291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj code cache (but not in the no-redir cache). Used for sanity 723291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj checking. */ 724291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic Bool is_in_the_main_TC ( void* hcode ) 725291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 726291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int i, sno; 727291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < N_SECTORS; i++) { 728291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sno = sector_search_order[i]; 729291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (sno == -1) 730291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj break; /* run out of sectors to search */ 731291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if ((UChar*)hcode >= (UChar*)sectors[sno].tc 732291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj && (UChar*)hcode <= (UChar*)sectors[sno].tc_next 733291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj + sizeof(ULong) - 1) 734291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return True; 735291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 736291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; 737291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 738291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 739291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 740291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Fulfill a chaining request, and record admin info so we 741291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj can undo it later, if required. 742291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj*/ 743291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid VG_(tt_tc_do_chaining) ( void* from__patch_addr, 744291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt to_sNo, 745291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt to_tteNo, 746291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool to_fastEP ) 747291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 748291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Get the CPU info established at startup. */ 749291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexArch vex_arch = VexArch_INVALID; 750291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(machine_get_VexArchInfo)( &vex_arch, NULL ); 751291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 752291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // host_code is where we're patching to. So it needs to 753291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // take into account, whether we're jumping to the slow 754291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // or fast entry point. By definition, the fast entry point 755291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // is exactly one event check's worth of code along from 756291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // the slow (tcptr) entry point. 757291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* to_tte = index_tte(to_sNo, to_tteNo); 758291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj void* host_code = ((UChar*)to_tte->tcptr) 759291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj + (to_fastEP ? LibVEX_evCheckSzB(vex_arch) : 0); 760291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 761291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // stay sane -- the patch point (dst) is in this sector's code cache 762291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( (UChar*)host_code >= (UChar*)sectors[to_sNo].tc ); 763291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( (UChar*)host_code <= (UChar*)sectors[to_sNo].tc_next 764291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj + sizeof(ULong) - 1 ); 765291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 766291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Find the TTEntry for the from__ code. This isn't simple since 767291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj we only know the patch address, which is going to be somewhere 768291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj inside the from_ block. */ 769291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_sNo = (UInt)-1; 770291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_tteNo = (UInt)-1; 771291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool from_found 772291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = find_TTEntry_from_hcode( &from_sNo, &from_tteNo, 773291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj from__patch_addr ); 774291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (!from_found) { 775291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // The from code might have been discarded due to sector re-use 776291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // or marked Deleted due to translation invalidation. 777291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // In such a case, don't do the chaining. 778291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(debugLog)(1,"transtab", 779291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj "host code %p not found (discarded? sector recycled?)" 780291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj " => no chaining done\n", 781291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj from__patch_addr); 782291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return; 783291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 784291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 785291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* from_tte = index_tte(from_sNo, from_tteNo); 786291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 787291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Get VEX to do the patching itself. We have to hand it off 788291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj since it is host-dependent. */ 789291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexInvalRange vir 790291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = LibVEX_Chain( 791291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vex_arch, 792291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj from__patch_addr, 793291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(fnptr_to_fnentry)( 794291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP) 795291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj : &VG_(disp_cp_chain_me_to_slowEP)), 796291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (void*)host_code 797291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 798291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( (void*)vir.start, vir.len ); 799291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 800291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Now do the tricky bit -- update the ch_succs and ch_preds info 801291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for the two translations involved, so we can undo the chaining 802291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj later, which we will have to do if the to_ block gets removed 803291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for whatever reason. */ 804291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 805291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* This is the new from_ -> to_ link to add. */ 806291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge ie; 807291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge__init(&ie); 808291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.from_sNo = from_sNo; 809291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.from_tteNo = from_tteNo; 810291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.to_fastEP = to_fastEP; 811291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HWord from_offs = (HWord)( (UChar*)from__patch_addr 812291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj - (UChar*)from_tte->tcptr ); 813291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(from_offs < 100000/* let's say */); 814291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.from_offs = (UInt)from_offs; 815291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 816291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* This is the new to_ -> from_ backlink to add. */ 817291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge oe; 818291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge__init(&oe); 819291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe.to_sNo = to_sNo; 820291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe.to_tteNo = to_tteNo; 821291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe.from_offs = (UInt)from_offs; 822291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 823291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Add .. */ 824291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr__add(&to_tte->in_edges, &ie); 825291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr__add(&from_tte->out_edges, &oe); 826291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 827291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 828291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 829291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Unchain one patch, as described by the specified InEdge. For 830291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sanity check purposes only (to check that the patched location is 831291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj as expected) it also requires the fast and slow entry point 832291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj addresses of the destination block (that is, the block that owns 833291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj this InEdge). */ 834291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj__attribute__((noinline)) 835291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void unchain_one ( VexArch vex_arch, 836291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge* ie, 837291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj void* to_fastEPaddr, void* to_slowEPaddr ) 838291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 839291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(ie); 840291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* tte 841291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = index_tte(ie->from_sNo, ie->from_tteNo); 842291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* place_to_patch 84319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian = ((UChar*)tte->tcptr) + ie->from_offs; 844291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* disp_cp_chain_me 845291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = VG_(fnptr_to_fnentry)( 846291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP) 847291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj : &VG_(disp_cp_chain_me_to_slowEP) 848291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 849291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* place_to_jump_to_EXPECTED 850291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = ie->to_fastEP ? to_fastEPaddr : to_slowEPaddr; 851291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 852291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // stay sane: both src and dst for this unchaining are 853291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // in the main code cache 854291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( is_in_the_main_TC(place_to_patch) ); // src 855291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( is_in_the_main_TC(place_to_jump_to_EXPECTED) ); // dst 856291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // dst check is ok because LibVEX_UnChain checks that 857291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // place_to_jump_to_EXPECTED really is the current dst, and 858291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // asserts if it isn't. 859291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexInvalRange vir 860291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = LibVEX_UnChain( vex_arch, place_to_patch, 861291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj place_to_jump_to_EXPECTED, disp_cp_chain_me ); 862291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( (void*)vir.start, vir.len ); 863291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 864291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 865291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 866291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* The specified block is about to be deleted. Update the preds and 867291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj succs of its associated blocks accordingly. This includes undoing 868291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj any chained jumps to this block. */ 869291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 870291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid unchain_in_preparation_for_deletion ( VexArch vex_arch, 871291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt here_sNo, UInt here_tteNo ) 872291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 8733a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 8743a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf)("QQQ unchain_in_prep %u.%u...\n", here_sNo, here_tteNo); 875291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UWord i, j, n, m; 876291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int evCheckSzB = LibVEX_evCheckSzB(vex_arch); 877291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* here_tte = index_tte(here_sNo, here_tteNo); 8783a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 8793a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf)("... QQQ tt.entry 0x%llu tt.tcptr 0x%p\n", 8803a5322057616d0da214b9e0f897866e203c03e40philippe here_tte->entry, here_tte->tcptr); 881291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(here_tte->status == InUse); 882291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 883291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Visit all InEdges owned by here_tte. */ 884291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj n = InEdgeArr__size(&here_tte->in_edges); 885291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < n; i++) { 886291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge* ie = InEdgeArr__index(&here_tte->in_edges, i); 887291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // Undo the chaining. 888291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* here_slow_EP = (UChar*)here_tte->tcptr; 889291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* here_fast_EP = here_slow_EP + evCheckSzB; 890291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj unchain_one(vex_arch, ie, here_fast_EP, here_slow_EP); 891291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // Find the corresponding entry in the "from" node's out_edges, 892291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // and remove it. 893291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* from_tte = index_tte(ie->from_sNo, ie->from_tteNo); 894291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj m = OutEdgeArr__size(&from_tte->out_edges); 895291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(m > 0); // it must have at least one entry 896291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (j = 0; j < m; j++) { 897291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge* oe = OutEdgeArr__index(&from_tte->out_edges, j); 898291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oe->to_sNo == here_sNo && oe->to_tteNo == here_tteNo 899291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj && oe->from_offs == ie->from_offs) 900291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj break; 901291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 902291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(j < m); // "oe must be findable" 903291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr__deleteIndex(&from_tte->out_edges, j); 904291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 905291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 906291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Visit all OutEdges owned by here_tte. */ 907291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj n = OutEdgeArr__size(&here_tte->out_edges); 908291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < n; i++) { 909291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge* oe = OutEdgeArr__index(&here_tte->out_edges, i); 910291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // Find the corresponding entry in the "to" node's in_edges, 911291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // and remove it. 912291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* to_tte = index_tte(oe->to_sNo, oe->to_tteNo); 913291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj m = InEdgeArr__size(&to_tte->in_edges); 914291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(m > 0); // it must have at least one entry 915291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (j = 0; j < m; j++) { 916291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge* ie = InEdgeArr__index(&to_tte->in_edges, j); 917291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (ie->from_sNo == here_sNo && ie->from_tteNo == here_tteNo 918291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj && ie->from_offs == oe->from_offs) 919291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj break; 920291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 921291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(j < m); // "ie must be findable" 922291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr__deleteIndex(&to_tte->in_edges, j); 923291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 924291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 925291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr__makeEmpty(&here_tte->in_edges); 926291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr__makeEmpty(&here_tte->out_edges); 927291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 928fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 929fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 9306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 9316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Address-range equivalence class stuff ---*/ 9326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 9336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Return equivalence class number for a range. */ 9356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Int range_to_eclass ( Addr64 start, UInt len ) 9376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 9386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt mask = (1 << ECLASS_WIDTH) - 1; 9396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt lo = (UInt)start; 9406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt hi = lo + len - 1; 9416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt loBits = (lo >> ECLASS_SHIFT) & mask; 9426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt hiBits = (hi >> ECLASS_SHIFT) & mask; 9436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (loBits == hiBits) { 9446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(loBits < ECLASS_N-1); 9456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return loBits; 9466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 9476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return ECLASS_MISC; 9486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 9496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 9506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Calculates the equivalence class numbers for any VexGuestExtent. 9536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj These are written in *eclasses, which must be big enough to hold 3 9546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Ints. The number written, between 1 and 3, is returned. The 9556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses are presented in order, and any duplicates are removed. 9566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj*/ 9576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 9596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjInt vexGuestExtents_to_eclasses ( /*OUT*/Int* eclasses, 9606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VexGuestExtents* vge ) 9616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 9626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# define SWAP(_lv1,_lv2) \ 9636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj do { Int t = _lv1; _lv1 = _lv2; _lv2 = t; } while (0) 9646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, j, n_ec, r; 9666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(vge->n_used >= 1 && vge->n_used <= 3); 9686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_ec = 0; 9706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < vge->n_used; i++) { 9716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj r = range_to_eclass( vge->base[i], (UInt)vge->len[i] ); 9726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (r == ECLASS_MISC) 9736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj goto bad; 9746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* only add if we haven't already seen it */ 9756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < n_ec; j++) 9766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[j] == r) 9776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj break; 9786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (j == n_ec) 9796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses[n_ec++] = r; 9806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 9816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 1) 9836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 1; 9846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 2) { 9866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* sort */ 9876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[1]) 9886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[1]); 9896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 2; 9906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 9916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 3) { 9936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* sort */ 9946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[2]) 9956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[2]); 9966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[1]) 9976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[1]); 9986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[1] > eclasses[2]) 9996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[1], eclasses[2]); 10006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 3; 10016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* NOTREACHED */ 10046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(0); 10056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bad: 10076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses[0] = ECLASS_MISC; 10086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 1; 10096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# undef SWAP 10116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 10126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Add tteno to the set of entries listed for equivalence class ec in 10156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj this sector. Returns used location in eclass array. */ 10166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 10186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjUInt addEClassNo ( /*MOD*/Sector* sec, Int ec, UShort tteno ) 10196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 10206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int old_sz, new_sz, i, r; 10216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort *old_ar, *new_ar; 10226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_N); 10246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno < N_TTES_PER_SECTOR); 10256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10263a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("ec %d gets %d\n", ec, (Int)tteno); 10276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[ec] >= sec->ec2tte_size[ec]) { 10296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_used[ec] == sec->ec2tte_size[ec]); 10316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj old_sz = sec->ec2tte_size[ec]; 10336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj old_ar = sec->ec2tte[ec]; 10346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj new_sz = old_sz==0 ? 8 : old_sz<64 ? 2*old_sz : (3*old_sz)/2; 1035291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj new_ar = ttaux_malloc("transtab.aECN.1", 1036291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj new_sz * sizeof(UShort)); 10376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < old_sz; i++) 10386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj new_ar[i] = old_ar[i]; 10396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (old_ar) 1040291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free(old_ar); 10416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte_size[ec] = new_sz; 10426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec] = new_ar; 10436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10443a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("expand ec %d to %d\n", ec, new_sz); 10456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Common case */ 10486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj r = sec->ec2tte_used[ec]++; 10496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(r >= 0 && r < sec->ec2tte_size[ec]); 10506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec][r] = tteno; 10516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return (UInt)r; 10526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 10536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* 'vge' is being added to 'sec' at TT entry 'tteno'. Add appropriate 10566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclass entries to 'sec'. */ 10576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 10596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjvoid upd_eclasses_after_add ( /*MOD*/Sector* sec, Int tteno ) 10606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 10616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, r, eclasses[3]; 10626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 10636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR); 10646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 10666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj r = vexGuestExtents_to_eclasses( eclasses, &tte->vge ); 10676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(r >= 1 && r <= 3); 10696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->n_tte2ec = r; 10706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < r; i++) { 10726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->tte2ec_ec[i] = eclasses[i]; 10736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->tte2ec_ix[i] = addEClassNo( sec, eclasses[i], (UShort)tteno ); 10746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 10766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Check the eclass info in 'sec' to ensure it is consistent. Returns 10796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj True if OK, False if something's not right. Expensive. */ 10806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_eclasses_in_sector ( Sector* sec ) 10826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 10836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# define BAD(_str) do { whassup = (_str); goto bad; } while (0) 10846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10856bd9dc18c043927c1196caba20a327238a179c42florian const HChar* whassup = NULL; 10866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, j, k, n, ec_num, ec_idx; 10876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 10886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort tteno; 10896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ULong* tce; 10906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Basic checks on this sector */ 10926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tt_n_inuse < 0 || sec->tt_n_inuse > N_TTES_PER_SECTOR_USABLE) 10936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("invalid sec->tt_n_inuse"); 10946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tce = sec->tc_next; 10956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tce < &sec->tc[0] || tce > &sec->tc[tc_sector_szQ]) 10966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("sec->tc_next points outside tc"); 10976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* For each eclass ... */ 10996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 11006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] == 0 && sec->ec2tte[i] != NULL) 11016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte_size/ec2tte mismatch(1)"); 11026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] != 0 && sec->ec2tte[i] == NULL) 11036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte_size/ec2tte mismatch(2)"); 11046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[i] < 0 11056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj || sec->ec2tte_used[i] > sec->ec2tte_size[i]) 11066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("implausible ec2tte_used"); 11076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[i] == 0) 11086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* For each tt reference in each eclass .. ensure the reference 11116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj is to a valid tt entry, and that the entry's address ranges 11126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj really include this eclass. */ 11136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < sec->ec2tte_used[i]; j++) { 11156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tteno = sec->ec2tte[i][j]; 11166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno == EC2TTE_DELETED) 11176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno >= N_TTES_PER_SECTOR) 11196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("implausible tteno"); 11206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 11216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != InUse) 11226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tteno points to non-inuse tte"); 11236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3) 11246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_tte2ec out of range"); 11256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Exactly least one of tte->eclasses[0 .. tte->n_eclasses-1] 11266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj must equal i. Inspect tte's eclass info. */ 11276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n = 0; 11286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (k = 0; k < tte->n_tte2ec; k++) { 11296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (k < tte->n_tte2ec-1 11306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj && tte->tte2ec_ec[k] >= tte->tte2ec_ec[k+1]) 11316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ec[..] out of order"); 11326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = tte->tte2ec_ec[k]; 11336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num < 0 || ec_num >= ECLASS_N) 11346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ec[..] out of range"); 11356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num != i) 11366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[k]; 11386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[i]) 11396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ix[..] out of range"); 11406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx == j) 11416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n++; 11426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n != 1) 11446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tteno does not point back at eclass"); 11456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* That establishes that for each forward pointer from TTEntrys 11496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj there is a corresponding backward pointer from the eclass[] 11506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj arrays. However, it doesn't rule out the possibility of other, 11516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bogus pointers in the eclass[] arrays. So do those similarly: 11526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj scan through them and check the TTEntryies they point at point 11536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj back. */ 11546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR_USABLE; i++) { 11566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[i]; 11586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status == Empty || tte->status == Deleted) { 11596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec != 0) 11606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_eclasses nonzero for unused tte"); 11616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 11656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3) 11676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_eclasses out of range(2)"); 11686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < tte->n_tte2ec; j++) { 11706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = tte->tte2ec_ec[j]; 11716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num < 0 || ec_num >= ECLASS_N) 11726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->eclass[..] out of range"); 11736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[j]; 11746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[ec_num]) 11756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->ec_idx[..] out of range(2)"); 11766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte[ec_num][ec_idx] != i) 11776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte does not point back to tte"); 11786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return True; 11826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bad: 11846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (whassup) 11856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(0, "transtab", "eclass sanity fail: %s\n", whassup); 11866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# if 0 11886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("eclass = %d\n", i); 11896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("tteno = %d\n", (Int)tteno); 11906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj switch (tte->status) { 11916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case InUse: VG_(printf)("InUse\n"); break; 11926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case Deleted: VG_(printf)("Deleted\n"); break; 11936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case Empty: VG_(printf)("Empty\n"); break; 11946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != Empty) { 11966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (k = 0; k < tte->vge.n_used; k++) 11976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("0x%llx %d\n", tte->vge.base[k], 11986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj (Int)tte->vge.len[k]); 11996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# endif 12016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return False; 12036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# undef BAD 12056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 12066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Sanity check absolutely everything. True == check passed. */ 12096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12105f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* forwards */ 12110ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void ); 12120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 12135d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardjstatic Bool sanity_check_sector_search_order ( void ) 12145d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj{ 12155d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj Int i, j, nListed; 12165d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* assert the array is the right size */ 12175d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj vg_assert(N_SECTORS == (sizeof(sector_search_order) 12185d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj / sizeof(sector_search_order[0]))); 12195d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Check it's of the form valid_sector_numbers ++ [-1, -1, ..] */ 12205d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj for (i = 0; i < N_SECTORS; i++) { 12215d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[i] < 0 || sector_search_order[i] >= N_SECTORS) 12225d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 12235d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12245d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj nListed = i; 12255d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj for (/* */; i < N_SECTORS; i++) { 12265d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[i] != -1) 12275d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 12285d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12295d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (i != N_SECTORS) 12305d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 12315d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Check each sector number only appears once */ 12325d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj for (i = 0; i < N_SECTORS; i++) { 12335d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[i] == -1) 12345d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj continue; 12355d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj for (j = i+1; j < N_SECTORS; j++) { 12365d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[j] == sector_search_order[i]) 12375d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 12385d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12395d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12405d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Check that the number of listed sectors equals the number 12415d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj in use, by counting nListed back down. */ 12425d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj for (i = 0; i < N_SECTORS; i++) { 12435d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sectors[i].tc != NULL) 12445d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj nListed--; 12455d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12465d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (nListed != 0) 12475d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 12485d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return True; 12495d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj} 12505d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 12516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_all_sectors ( void ) 12526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 12536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int sno; 12546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane; 12556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 12566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (sno = 0; sno < N_SECTORS; sno++) { 12573a5322057616d0da214b9e0f897866e203c03e40philippe Int i; 12583a5322057616d0da214b9e0f897866e203c03e40philippe Int nr_not_dead_hx = 0; 12593a5322057616d0da214b9e0f897866e203c03e40philippe Int szhxa; 12606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 12616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 12626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 12636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sane = sanity_check_eclasses_in_sector( sec ); 12646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (!sane) 12656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return False; 12663a5322057616d0da214b9e0f897866e203c03e40philippe szhxa = VG_(sizeXA)(sec->host_extents); 12673a5322057616d0da214b9e0f897866e203c03e40philippe for (i = 0; i < szhxa; i++) { 12683a5322057616d0da214b9e0f897866e203c03e40philippe const HostExtent* hx = VG_(indexXA)(sec->host_extents, i); 12693a5322057616d0da214b9e0f897866e203c03e40philippe if (!HostExtent__is_dead (hx, sec)) 12703a5322057616d0da214b9e0f897866e203c03e40philippe nr_not_dead_hx++; 12713a5322057616d0da214b9e0f897866e203c03e40philippe } 12723a5322057616d0da214b9e0f897866e203c03e40philippe if (nr_not_dead_hx != sec->tt_n_inuse) { 12733a5322057616d0da214b9e0f897866e203c03e40philippe VG_(debugLog)(0, "transtab", 12743a5322057616d0da214b9e0f897866e203c03e40philippe "nr_not_dead_hx %d sanity fail (expected == in use %d)\n", 12753a5322057616d0da214b9e0f897866e203c03e40philippe nr_not_dead_hx, sec->tt_n_inuse); 12763a5322057616d0da214b9e0f897866e203c03e40philippe return False; 12773a5322057616d0da214b9e0f897866e203c03e40philippe } 12786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12793a5322057616d0da214b9e0f897866e203c03e40philippe 12805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if ( !sanity_check_redir_tt_tc() ) 12815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj return False; 12825d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if ( !sanity_check_sector_search_order() ) 12835d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 12846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return True; 12856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 12866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1287fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 12885d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 1289fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/ 12906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Add/find translations ---*/ 1291fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/ 1292fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1293fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic UInt vge_osize ( VexGuestExtents* vge ) 1294c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{ 1295fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt i, n = 0; 1296fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < vge->n_used; i++) 1297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n += (UInt)vge->len[i]; 1298fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return n; 1299c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj} 1300c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 1301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Bool isValidSector ( Int sector ) 13026c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1303fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sector < 0 || sector >= N_SECTORS) 1304fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1305fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 13066c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1307de4a1d01951937632098a6cda45859afa587a06fsewardj 1308fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline UInt HASH_TT ( Addr64 key ) 1309de4a1d01951937632098a6cda45859afa587a06fsewardj{ 1310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt kHi = (UInt)(key >> 32); 1311fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt kLo = (UInt)key; 13126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt k32 = kHi ^ kLo; 13136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt ror = 7; 13146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ror > 0) 13156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj k32 = (k32 >> ror) | (k32 << (32-ror)); 13166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return k32 % N_TTES_PER_SECTOR; 1317de4a1d01951937632098a6cda45859afa587a06fsewardj} 1318de4a1d01951937632098a6cda45859afa587a06fsewardj 1319291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void setFastCacheEntry ( Addr64 key, ULong* tcptr ) 1320de4a1d01951937632098a6cda45859afa587a06fsewardj{ 13213387dda4479102751d544c176a7bfc24f3766669sewardj UInt cno = (UInt)VG_TT_FAST_HASH(key); 13225f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[cno].guest = (Addr)key; 13235f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[cno].host = (Addr)tcptr; 1324fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_updates++; 13255f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* This shouldn't fail. It should be assured by m_translate 13265f76de086a6d643db51e50a4e623df7dfc9b6161sewardj which should reject any attempt to make translation of code 13275f76de086a6d643db51e50a4e623df7dfc9b6161sewardj starting at TRANSTAB_BOGUS_GUEST_ADDR. */ 13285f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_(tt_fast)[cno].guest != TRANSTAB_BOGUS_GUEST_ADDR); 13296c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1330de4a1d01951937632098a6cda45859afa587a06fsewardj 1331291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Invalidate the fast cache VG_(tt_fast). */ 13325f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastCache ( void ) 13335f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{ 13345f76de086a6d643db51e50a4e623df7dfc9b6161sewardj UInt j; 13355f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* This loop is popular enough to make it worth unrolling a 13365f76de086a6d643db51e50a4e623df7dfc9b6161sewardj bit, at least on ppc32. */ 13375f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0); 13385f76de086a6d643db51e50a4e623df7dfc9b6161sewardj for (j = 0; j < VG_TT_FAST_SIZE; j += 4) { 13395f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+0].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13405f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+1].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13415f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+2].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13425f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+3].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13435f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 13445f76de086a6d643db51e50a4e623df7dfc9b6161sewardj 13455f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(j == VG_TT_FAST_SIZE); 1346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_flushes++; 13476c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1348de4a1d01951937632098a6cda45859afa587a06fsewardj 1349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void initialiseSector ( Int sno ) 13506c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1351291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int i; 1352291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj SysRes sres; 13536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 1354fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(isValidSector(sno)); 1355fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 13565d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj { Bool sane = sanity_check_sector_search_order(); 13575d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj vg_assert(sane); 13585d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 13596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 13606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 13616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) { 13626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1363fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Sector has never been used before. Need to allocate tt and 1364fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tc. */ 13656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt == NULL); 13666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tc_next == NULL); 13676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt_n_inuse == 0); 13686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 13696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_size[i] == 0); 13706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_used[i] == 0); 13716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[i] == NULL); 13726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 1373291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec->host_extents == NULL); 137445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 137545f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(1,"transtab", "allocate sector %d\n", sno); 1376059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj if (VG_(clo_stats)) 1377059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj VG_(dmsg)("transtab: " "allocate sector %d\n", sno); 137845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 137945f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ ); 1380cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 138145f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(out_of_memory_NORETURN)("initialiseSector(TC)", 138245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 8 * tc_sector_szQ ); 138345f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*NOTREACHED*/ 138445f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 1385cda2f0fbda4c4b2644babc830244be8aed95de1dnjn sec->tc = (ULong*)(AddrH)sr_Res(sres); 138645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 138745f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_mmap_anon_float_valgrind) 138845f4e7c91119c7d01a59f5e827c67841632c9314sewardj ( N_TTES_PER_SECTOR * sizeof(TTEntry) ); 1389cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 139045f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(out_of_memory_NORETURN)("initialiseSector(TT)", 139145f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_TTES_PER_SECTOR * sizeof(TTEntry) ); 139245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*NOTREACHED*/ 139345f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 1394cda2f0fbda4c4b2644babc830244be8aed95de1dnjn sec->tt = (TTEntry*)(AddrH)sr_Res(sres); 13956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 13966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 13976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].status = Empty; 13986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].n_tte2ec = 0; 13996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 140045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1401291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Set up the host_extents array. */ 1402291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sec->host_extents 1403291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = VG_(newXA)(ttaux_malloc, "transtab.initialiseSector(host_extents)", 1404291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free, 1405291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sizeof(HostExtent)); 1406291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 14075d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Add an entry in the sector_search_order */ 14085d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj for (i = 0; i < N_SECTORS; i++) { 14095d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[i] == -1) 14105d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 14115d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 14125d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj vg_assert(i >= 0 && i < N_SECTORS); 14135d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i] = sno; 14145d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 1415fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 1416738856f99eea33d86ce91dcb1d6cd5b151e307casewardj VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d\n", sno); 14176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1418fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } else { 14196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 14206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Sector has been used before. Dump the old contents. */ 142145f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(1,"transtab", "recycle sector %d\n", sno); 1422059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj if (VG_(clo_stats)) 1423059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj VG_(dmsg)("transtab: " "recycle sector %d\n", sno); 1424059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj 14256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt != NULL); 14266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tc_next != NULL); 14276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_dump_count += sec->tt_n_inuse; 14286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1429291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexArch vex_arch = VexArch_INVALID; 1430291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(machine_get_VexArchInfo)( &vex_arch, NULL ); 1431291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 14326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Visit each just-about-to-be-abandoned translation. */ 14333a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("QQQ unlink-entire-sector: %d START\n", 14343a5322057616d0da214b9e0f897866e203c03e40philippe sno); 1435fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 14366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tt[i].status == InUse) { 14376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt[i].n_tte2ec >= 1); 14386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt[i].n_tte2ec <= 3); 14396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_dump_osize += vge_osize(&sec->tt[i].vge); 14403786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj /* Tell the tool too. */ 14410b9d74abd0a663b530d290b2b788ddeda46e5400sewardj if (VG_(needs).superblock_discards) { 14420b9d74abd0a663b530d290b2b788ddeda46e5400sewardj VG_TDICT_CALL( tool_discard_superblock_info, 14434ba057cce1d81a949f5a899b5abb99e90a731bccsewardj sec->tt[i].entry, 14446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].vge ); 14453786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj } 1446291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj unchain_in_preparation_for_deletion(vex_arch, sno, i); 14476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 14486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt[i].n_tte2ec == 0); 14496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 14506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].status = Empty; 14516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].n_tte2ec = 0; 14526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 14533a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("QQQ unlink-entire-sector: %d END\n", 14543a5322057616d0da214b9e0f897866e203c03e40philippe sno); 14556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 14566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Free up the eclass structures. */ 14576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 14586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] == 0) { 14596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_used[i] == 0); 14606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[i] == NULL); 14616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 14626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[i] != NULL); 1463291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free(sec->ec2tte[i]); 14646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[i] = NULL; 14656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte_size[i] = 0; 14666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte_used[i] = 0; 1467fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 1468fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 14696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1470291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Empty out the host extents array. */ 1471291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec->host_extents != NULL); 1472291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(dropTailXA)(sec->host_extents, VG_(sizeXA)(sec->host_extents)); 1473291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(VG_(sizeXA)(sec->host_extents) == 0); 1474291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 14755d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Sanity check: ensure it is already in 14765d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[]. */ 14775d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj for (i = 0; i < N_SECTORS; i++) { 14785d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[i] == sno) 14795d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 14805d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 14815d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj vg_assert(i >= 0 && i < N_SECTORS); 14825d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 1483fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 1484738856f99eea33d86ce91dcb1d6cd5b151e307casewardj VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d\n", sno); 14856c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 14864ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 14876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tc_next = sec->tc; 14886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt_n_inuse = 0; 1489fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1490fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 14915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 14925d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj { Bool sane = sanity_check_sector_search_order(); 14935d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj vg_assert(sane); 14945d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 14956c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1496de4a1d01951937632098a6cda45859afa587a06fsewardj 1497de4a1d01951937632098a6cda45859afa587a06fsewardj 1498fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC. The translation is temporarily 1499fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj in code[0 .. code_len-1]. 1500de4a1d01951937632098a6cda45859afa587a06fsewardj 1501fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj pre: youngest_sector points to a valid (although possibly full) 1502fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. 1503fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 15048bddf58af8cc7342d4bde6712c5a6a33bf2850d4njnvoid VG_(add_to_transtab)( VexGuestExtents* vge, 15058bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn Addr64 entry, 15068bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn AddrH code, 150726412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj UInt code_len, 1508291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool is_self_checking, 1509291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int offs_profInc, 1510b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj UInt n_guest_instrs, 1511291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexArch arch_host ) 151222854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{ 1513fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int tcAvailQ, reqdQ, y, i; 15145f76de086a6d643db51e50a4e623df7dfc9b6161sewardj ULong *tcptr, *tcptr2; 1515fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UChar* srcP; 1516fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UChar* dstP; 1517fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1518663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 1519fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(vge->n_used >= 1 && vge->n_used <= 3); 1520e808930793aeddc4cfd3e7a94b665913bec2566csewardj 1521e808930793aeddc4cfd3e7a94b665913bec2566csewardj /* 60000: should agree with N_TMPBUF in m_translate.c. */ 1522e808930793aeddc4cfd3e7a94b665913bec2566csewardj vg_assert(code_len > 0 && code_len < 60000); 1523fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1524b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj /* Generally stay sane */ 1525b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj vg_assert(n_guest_instrs < 200); /* it can be zero, tho */ 1526b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj 15273a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 15283a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf)("add_to_transtab(entry = 0x%llx, len = %d) ...\n", 1529fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj entry, code_len); 1530fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1531fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_count++; 1532fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_tsize += code_len; 1533fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_osize += vge_osize(vge); 153426412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj if (is_self_checking) 153526412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj n_in_sc_count++; 1536fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1537fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj y = youngest_sector; 1538fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(isValidSector(y)); 1539fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1540fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[y].tc == NULL) 1541fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj initialiseSector(y); 1542fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1543fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Try putting the translation in this sector. */ 15445f76de086a6d643db51e50a4e623df7dfc9b6161sewardj reqdQ = (code_len + 7) >> 3; 1545fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1546fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Will it fit in tc? */ 1547fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tcAvailQ = ((ULong*)(§ors[y].tc[tc_sector_szQ])) 1548fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - ((ULong*)(sectors[y].tc_next)); 1549fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= 0); 1550fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ <= tc_sector_szQ); 1551fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1552fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (tcAvailQ < reqdQ 1553fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR_USABLE) { 1554fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* No. So move on to the next sector. Either it's never been 1555fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj used before, in which case it will get its tt/tc allocated 1556fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj now, or it has been used before, in which case it is set to be 1557fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj empty, hence throwing out the oldest sector. */ 1558a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj vg_assert(tc_sector_szQ > 0); 1559059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj Int tt_loading_pct = (100 * sectors[y].tt_n_inuse) 1560059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj / N_TTES_PER_SECTOR; 1561059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj Int tc_loading_pct = (100 * (tc_sector_szQ - tcAvailQ)) 1562059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj / tc_sector_szQ; 1563a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj VG_(debugLog)(1,"transtab", 1564a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj "declare sector %d full " 1565a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj "(TT loading %2d%%, TC loading %2d%%)\n", 1566059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj y, tt_loading_pct, tc_loading_pct); 1567059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj if (VG_(clo_stats)) { 1568059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj VG_(dmsg)("transtab: " 1569059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj "declare sector %d full " 1570059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj "(TT loading %2d%%, TC loading %2d%%)\n", 1571059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj y, tt_loading_pct, tc_loading_pct); 1572059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj } 1573fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector++; 1574fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (youngest_sector >= N_SECTORS) 1575fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector = 0; 1576fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj y = youngest_sector; 1577fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj initialiseSector(y); 1578fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 157922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 1580fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Be sure ... */ 1581fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tcAvailQ = ((ULong*)(§ors[y].tc[tc_sector_szQ])) 1582fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - ((ULong*)(sectors[y].tc_next)); 1583fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= 0); 1584fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ <= tc_sector_szQ); 1585fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= reqdQ); 1586fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR_USABLE); 1587fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[y].tt_n_inuse >= 0); 1588fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1589fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Copy into tc. */ 15905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj tcptr = sectors[y].tc_next; 15915f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr >= §ors[y].tc[0]); 15925f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr <= §ors[y].tc[tc_sector_szQ]); 1593fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 15945f76de086a6d643db51e50a4e623df7dfc9b6161sewardj dstP = (UChar*)tcptr; 1595fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj srcP = (UChar*)code; 1596291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(memcpy)(dstP, srcP, code_len); 1597fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tc_next += reqdQ; 1598fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt_n_inuse++; 1599fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1600fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* more paranoia */ 16015f76de086a6d643db51e50a4e623df7dfc9b6161sewardj tcptr2 = sectors[y].tc_next; 16025f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr2 >= §ors[y].tc[0]); 16035f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr2 <= §ors[y].tc[tc_sector_szQ]); 1604fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1605fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find an empty tt slot, and use it. There must be such a slot 1606fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj since tt is never allowed to get completely full. */ 1607fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i = HASH_TT(entry); 1608fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(i >= 0 && i < N_TTES_PER_SECTOR); 160922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj while (True) { 1610fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[y].tt[i].status == Empty 1611fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj || sectors[y].tt[i].status == Deleted) 1612fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 1613fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i++; 1614fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (i >= N_TTES_PER_SECTOR) 1615fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i = 0; 161622854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj } 1617fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1618291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry__init(§ors[y].tt[i]); 1619fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].status = InUse; 16205f76de086a6d643db51e50a4e623df7dfc9b6161sewardj sectors[y].tt[i].tcptr = tcptr; 1621fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].count = 0; 1622b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj sectors[y].tt[i].weight = n_guest_instrs == 0 ? 1 : n_guest_instrs; 1623fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].vge = *vge; 1624fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].entry = entry; 1625fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1626291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Patch in the profile counter location, if necessary. */ 1627291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (offs_profInc != -1) { 1628291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(offs_profInc >= 0 && offs_profInc < code_len); 1629291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexInvalRange vir 1630291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = LibVEX_PatchProfInc( arch_host, 1631291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj dstP + offs_profInc, 1632291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj §ors[y].tt[i].count ); 1633291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( (void*)vir.start, vir.len ); 1634291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 1635291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 1636291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( dstP, code_len ); 1637291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 1638291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Add this entry to the host_extents map, checking that we're 1639291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj adding in order. */ 1640291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj { HostExtent hx; 1641291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj hx.start = (UChar*)tcptr; 1642291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj hx.len = code_len; 1643291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj hx.tteNo = i; 1644291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(hx.len > 0); /* bsearch fails w/ zero length entries */ 1645291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* hx_array = sectors[y].host_extents; 1646291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(hx_array); 1647291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Word n = VG_(sizeXA)(hx_array); 1648291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (n > 0) { 1649291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent* hx_prev = (HostExtent*)VG_(indexXA)(hx_array, n-1); 1650291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(hx_prev->start + hx_prev->len <= hx.start); 1651291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 1652291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(hx_array, &hx); 16533a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 16543a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf)("... hx.start 0x%p hx.len %u sector %d ttslot %d\n", 16553a5322057616d0da214b9e0f897866e203c03e40philippe hx.start, hx.len, y, i); 1656291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 1657291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 16586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Update the fast-cache. */ 1659291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj setFastCacheEntry( entry, tcptr ); 16606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 16616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Note the eclass numbers for this translation. */ 16626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj upd_eclasses_after_add( §ors[y], i ); 166322854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj} 166422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 1665fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1666fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address. If 1667fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj requested, a successful search can also cause the fast-caches to be 1668fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj updated. 1669fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 1670291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool VG_(search_transtab) ( /*OUT*/AddrH* res_hcode, 1671291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /*OUT*/UInt* res_sNo, 1672291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /*OUT*/UInt* res_tteNo, 1673fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Addr64 guest_addr, 1674fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Bool upd_cache ) 16756c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1676fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int i, j, k, kstart, sno; 1677663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 1678663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 1679fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find the initial probe point just once. It will be the same in 1680fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj all sectors and avoids multiple expensive % operations. */ 1681fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_full_lookups++; 1682fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = -1; 1683fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj kstart = HASH_TT(guest_addr); 1684fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(kstart >= 0 && kstart < N_TTES_PER_SECTOR); 1685fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 16865d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Search in all the sectors,using sector_search_order[] as a 16875d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj heuristic guide as to what order to visit the sectors. */ 1688fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_SECTORS; i++) { 1689fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 16905d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sno = sector_search_order[i]; 16915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (UNLIKELY(sno == -1)) 16925d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; /* run out of sectors to search */ 1693fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1694fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = kstart; 1695fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (j = 0; j < N_TTES_PER_SECTOR; j++) { 1696fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_lookup_probes++; 1697fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[k].status == InUse 1698fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj && sectors[sno].tt[k].entry == guest_addr) { 1699fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* found it */ 1700fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (upd_cache) 1701fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj setFastCacheEntry( 1702291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj guest_addr, sectors[sno].tt[k].tcptr ); 1703291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (res_hcode) 1704291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *res_hcode = (AddrH)sectors[sno].tt[k].tcptr; 1705291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (res_sNo) 1706291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *res_sNo = sno; 1707291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (res_tteNo) 1708291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *res_tteNo = k; 17095d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* pull this one one step closer to the front. For large 17105d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj apps this more or less halves the number of required 17115d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj probes. */ 17125d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (i > 0) { 17135d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj Int tmp = sector_search_order[i-1]; 17145d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i-1] = sector_search_order[i]; 17155d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i] = tmp; 17165d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 1717fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1718fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 1719fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[k].status == Empty) 1720fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; /* not found in this sector */ 1721fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k++; 1722fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (k == N_TTES_PER_SECTOR) 1723fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = 0; 17246c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 1725fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1726fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* If we fall off the end, all entries are InUse and not 1727fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj matching, or Deleted. In any case we did not find it in this 1728fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. */ 17296c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 1730fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1731fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Not found in any sector. */ 1732fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 17336c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1734de4a1d01951937632098a6cda45859afa587a06fsewardj 1735de4a1d01951937632098a6cda45859afa587a06fsewardj 17366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 17376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Delete translations. ---*/ 17386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 17396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 17400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* forward */ 17410ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void unredir_discard_translations( Addr64, ULong ); 17420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 17436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Stuff for deleting translations which intersect with a given 17446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range. Unfortunately, to make this run at a reasonable 17456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj speed, it is complex. */ 1746fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1747fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline 1748a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlap1 ( Addr64 s1, ULong r1, Addr64 s2, ULong r2 ) 17496c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1750a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj Addr64 e1 = s1 + r1 - 1ULL; 1751a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj Addr64 e2 = s2 + r2 - 1ULL; 1752fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (e1 < s2 || e2 < s1) 1753fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1754fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 17556c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1756de4a1d01951937632098a6cda45859afa587a06fsewardj 1757fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline 1758a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlaps ( Addr64 start, ULong range, VexGuestExtents* vge ) 17596c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1760fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (overlap1(start, range, vge->base[0], (UInt)vge->len[0])) 1761fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1762fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (vge->n_used < 2) 1763fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1764fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (overlap1(start, range, vge->base[1], (UInt)vge->len[1])) 1765fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1766fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (vge->n_used < 3) 1767fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1768fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (overlap1(start, range, vge->base[2], (UInt)vge->len[2])) 1769fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1770fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 17716c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1772de4a1d01951937632098a6cda45859afa587a06fsewardj 1773de4a1d01951937632098a6cda45859afa587a06fsewardj 17746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete a tt entry, and update all the eclass data accordingly. */ 17756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1776291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void delete_tte ( /*MOD*/Sector* sec, UInt secNo, Int tteno, 1777291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexArch vex_arch ) 17786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 17796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, ec_num, ec_idx; 17806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 17816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1782291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* sec and secNo are mutually redundant; cross-check. */ 1783291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec == §ors[secNo]); 1784291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 17856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR); 17866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 17876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 17886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->n_tte2ec >= 1 && tte->n_tte2ec <= 3); 17896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1790291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Unchain .. */ 1791291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj unchain_in_preparation_for_deletion(vex_arch, secNo, tteno); 1792291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 17936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Deal with the ec-to-tte links first. */ 17946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < tte->n_tte2ec; i++) { 17956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = (Int)tte->tte2ec_ec[i]; 17966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[i]; 17976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_num >= 0 && ec_num < ECLASS_N); 17986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_idx >= 0); 17996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_idx < sec->ec2tte_used[ec_num]); 18006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Assert that the two links point at each other. */ 18016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[ec_num][ec_idx] == (UShort)tteno); 18026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* "delete" the pointer back to here. */ 18036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec_num][ec_idx] = EC2TTE_DELETED; 18046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Now fix up this TTEntry. */ 18076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->status = Deleted; 18086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->n_tte2ec = 0; 18096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Stats .. */ 18116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt_n_inuse--; 18126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_disc_count++; 18136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_disc_osize += vge_osize(&tte->vge); 18146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Tell the tool too. */ 18160b9d74abd0a663b530d290b2b788ddeda46e5400sewardj if (VG_(needs).superblock_discards) { 18170b9d74abd0a663b530d290b2b788ddeda46e5400sewardj VG_TDICT_CALL( tool_discard_superblock_info, 18184ba057cce1d81a949f5a899b5abb99e90a731bccsewardj tte->entry, 18196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->vge ); 18206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 18226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, but 18256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj only consider translations in the specified eclass. */ 18266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 1828291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool delete_translations_in_sector_eclass ( /*MOD*/Sector* sec, UInt secNo, 18296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Addr64 guest_start, ULong range, 1830291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int ec, 1831291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexArch vex_arch ) 18326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 18336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 18346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort tteno; 18356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeld = False; 18366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 18376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_N); 18396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < sec->ec2tte_used[ec]; i++) { 18416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tteno = sec->ec2tte[ec][i]; 18436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno == EC2TTE_DELETED) { 18446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* already deleted */ 18456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 18466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno < N_TTES_PER_SECTOR); 18496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 18516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 18526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (overlaps( guest_start, range, &tte->vge )) { 18546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeld = True; 1855291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj delete_tte( sec, secNo, (Int)tteno, vex_arch ); 18566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return anyDeld; 18616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 18626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, the 18656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj slow way, by inspecting all translations in sec. */ 18666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 1868291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool delete_translations_in_sector ( /*MOD*/Sector* sec, UInt secNo, 1869291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Addr64 guest_start, ULong range, 1870291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexArch vex_arch ) 18716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 18726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 18736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeld = False; 18746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 18766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tt[i].status == InUse 18776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj && overlaps( guest_start, range, &sec->tt[i].vge )) { 18786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeld = True; 1879291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj delete_tte( sec, secNo, i, vex_arch ); 18806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return anyDeld; 18846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 18856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 188745f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid VG_(discard_translations) ( Addr64 guest_start, ULong range, 18881636d33c13958b9c0e7d3059cdd5005746418eb2florian const HChar* who ) 18896c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 18906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 18916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int sno, ec; 18926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeleted = False; 18936c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 1894663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 1895663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 1896a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj VG_(debugLog)(2, "transtab", 189745f4e7c91119c7d01a59f5e827c67841632c9314sewardj "discard_translations(0x%llx, %lld) req by %s\n", 189845f4e7c91119c7d01a59f5e827c67841632c9314sewardj guest_start, range, who ); 189945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 19006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Pre-deletion sanity check */ 19016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (VG_(clo_sanity_level >= 4)) { 19026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane = sanity_check_all_sectors(); 19036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sane); 19046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (range == 0) 19076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return; 19086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1909291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexArch vex_arch = VexArch_INVALID; 1910291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(machine_get_VexArchInfo)( &vex_arch, NULL ); 1911291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 19126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* There are two different ways to do this. 19136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj If the range fits within a single address-range equivalence 19156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class, as will be the case for a cache line sized invalidation, 19166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj then we only have to inspect the set of translations listed in 19176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj that equivalence class, and also in the "sin-bin" equivalence 19186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class ECLASS_MISC. 19196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Otherwise, the invalidation is of a larger range and probably 19216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj results from munmap. In this case it's (probably!) faster just 19226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj to inspect all translations, dump those we don't want, and 19236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj regenerate the equivalence class information (since modifying it 19246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj in-situ is even more expensive). 19256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj */ 19266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* First off, figure out if the range falls within a single class, 19286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj and if so which one. */ 19296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec = ECLASS_MISC; 19316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (range < (1ULL << ECLASS_SHIFT)) 19326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec = range_to_eclass( guest_start, (UInt)range ); 19336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* if ec is ECLASS_MISC then we aren't looking at just a single 19356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class, so use the slow scheme. Else use the fast scheme, 19366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj examining 'ec' and ECLASS_MISC. */ 19376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec != ECLASS_MISC) { 19396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(2, "transtab", 19416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj " FAST, ec = %d\n", ec); 19426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Fast scheme */ 19446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_MISC); 19456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (sno = 0; sno < N_SECTORS; sno++) { 19476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 19486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 19496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 19506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector_eclass( 1951291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sec, sno, guest_start, range, ec, 1952291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vex_arch 1953291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 19546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector_eclass( 1955291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sec, sno, guest_start, range, ECLASS_MISC, 1956291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vex_arch 1957291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 19586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 19616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* slow scheme */ 19636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(2, "transtab", 19656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj " SLOW, ec = %d\n", ec); 19666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (sno = 0; sno < N_SECTORS; sno++) { 19686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 19696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 19706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 19716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector( 1972291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sec, sno, guest_start, range, vex_arch ); 19736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1975de4a1d01951937632098a6cda45859afa587a06fsewardj } 1976de4a1d01951937632098a6cda45859afa587a06fsewardj 1977fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (anyDeleted) 1978fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 19796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* don't forget the no-redir cache */ 19810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_discard_translations( guest_start, range ); 19820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 19836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Post-deletion sanity check */ 19846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (VG_(clo_sanity_level >= 4)) { 19856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 19866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 19876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane = sanity_check_all_sectors(); 19886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sane); 19896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* But now, also check the requested address range isn't 19906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj present anywhere. */ 19916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (sno = 0; sno < N_SECTORS; sno++) { 19926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 19936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 19946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 19956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 19966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[i]; 19976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != InUse) 19986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 19996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(!overlaps( guest_start, range, &tte->vge )); 20006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 20016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 20026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 2003fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 20046c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 20056c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 2006fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 20070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*--- AUXILIARY: the unredirected TT/TC ---*/ 20080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/ 20090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* A very simple translation cache which holds a small number of 20110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredirected translations. This is completely independent of the 20120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj main tt/tc structures. When unredir_tc or unredir_tt becomes full, 20130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj both structures are simply dumped and we start over. 20140ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20150ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Since these translations are unredirected, the search key is (by 20160ec07f32bbbb209d749b9974408e6f025ad40b31sewardj definition) the first address entry in the .vge field. */ 20170ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Sized to hold 500 translations of average size 1000 bytes. */ 20190ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20200ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define UNREDIR_SZB 1000 20210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TT 500 20230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TCQ (N_UNREDIR_TT * UNREDIR_SZB / sizeof(ULong)) 20240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20250ec07f32bbbb209d749b9974408e6f025ad40b31sewardjtypedef 20260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj struct { 20270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj VexGuestExtents vge; 20280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Addr hcode; 20290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Bool inUse; 20300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 20310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj UTCEntry; 20320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* We just allocate forwards in _tc, never deleting. */ 203478c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic ULong *unredir_tc; 203578c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic Int unredir_tc_used = N_UNREDIR_TCQ; 20360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Slots in _tt can come into use and out again (.inUse). 20380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Nevertheless _tt_highwater is maintained so that invalidations 20390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj don't have to scan all the slots when only a few are in use. 20400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj _tt_highwater holds the index of the highest ever allocated 20410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj slot. */ 20420ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic UTCEntry unredir_tt[N_UNREDIR_TT]; 20430ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Int unredir_tt_highwater; 20440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20460ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void init_unredir_tt_tc ( void ) 20470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 20480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 204978c0c09d429c95115e826ef769ecaa6cff2ac338tom if (unredir_tc == NULL) { 2050cda2f0fbda4c4b2644babc830244be8aed95de1dnjn SysRes sres = VG_(am_mmap_anon_float_valgrind) 2051cda2f0fbda4c4b2644babc830244be8aed95de1dnjn ( N_UNREDIR_TT * UNREDIR_SZB ); 2052cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 2053cda2f0fbda4c4b2644babc830244be8aed95de1dnjn VG_(out_of_memory_NORETURN)("init_unredir_tt_tc", 2054cda2f0fbda4c4b2644babc830244be8aed95de1dnjn N_UNREDIR_TT * UNREDIR_SZB); 205578c0c09d429c95115e826ef769ecaa6cff2ac338tom /*NOTREACHED*/ 205678c0c09d429c95115e826ef769ecaa6cff2ac338tom } 2057cda2f0fbda4c4b2644babc830244be8aed95de1dnjn unredir_tc = (ULong *)(AddrH)sr_Res(sres); 205878c0c09d429c95115e826ef769ecaa6cff2ac338tom } 20590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tc_used = 0; 20600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) 20610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = False; 20620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt_highwater = -1; 20630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 20640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Do a sanity check; return False on failure. */ 20660ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void ) 20670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 20680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 20690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt_highwater < -1) return False; 20700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt_highwater >= N_UNREDIR_TT) return False; 20710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = unredir_tt_highwater+1; i < N_UNREDIR_TT; i++) 20730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].inUse) 20740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return False; 20750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tc_used < 0) return False; 20770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tc_used > N_UNREDIR_TCQ) return False; 20780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return True; 20800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 20810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20830ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Add an UNREDIRECTED translation of vge to TT/TC. The translation 20840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj is temporarily in code[0 .. code_len-1]. 20850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj*/ 20860ec07f32bbbb209d749b9974408e6f025ad40b31sewardjvoid VG_(add_to_unredir_transtab)( VexGuestExtents* vge, 20870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Addr64 entry, 20880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj AddrH code, 20891dcee097db02f9ef3ba355162c4373d90d0e895cnjn UInt code_len ) 20900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 20910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i, j, code_szQ; 20920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj HChar *srcP, *dstP; 20930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(sanity_check_redir_tt_tc()); 20950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* This is the whole point: it's not redirected! */ 20970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(entry == vge->base[0]); 20980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* How many unredir_tt slots are needed */ 21000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj code_szQ = (code_len + 7) / 8; 21010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* Look for an empty unredir_tc slot */ 21030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) 21040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (!unredir_tt[i].inUse) 21050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj break; 21060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (i >= N_UNREDIR_TT || code_szQ > (N_UNREDIR_TCQ - unredir_tc_used)) { 21080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* It's full; dump everything we currently have */ 21090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj init_unredir_tt_tc(); 21100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj i = 0; 21110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 21120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used >= 0); 21140ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used <= N_UNREDIR_TCQ); 21150ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(code_szQ > 0); 21160ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(code_szQ + unredir_tc_used <= N_UNREDIR_TCQ); 21170ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(i >= 0 && i < N_UNREDIR_TT); 21180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tt[i].inUse == False); 21190ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21200ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (i > unredir_tt_highwater) 21210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt_highwater = i; 21220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj dstP = (HChar*)&unredir_tc[unredir_tc_used]; 21240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj srcP = (HChar*)code; 21250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (j = 0; j < code_len; j++) 21260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj dstP[j] = srcP[j]; 21270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 2128291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( dstP, code_len ); 2129c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj 21300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = True; 21310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].vge = *vge; 21320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].hcode = (Addr)dstP; 21330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tc_used += code_szQ; 21350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used >= 0); 21360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used <= N_UNREDIR_TCQ); 21370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(&dstP[code_len] <= (HChar*)&unredir_tc[unredir_tc_used]); 21390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 21400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21410ec07f32bbbb209d749b9974408e6f025ad40b31sewardjBool VG_(search_unredir_transtab) ( /*OUT*/AddrH* result, 21420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Addr64 guest_addr ) 21430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 21440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 21450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) { 21460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (!unredir_tt[i].inUse) 21470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj continue; 21480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].vge.base[0] == guest_addr) { 21490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj *result = (AddrH)unredir_tt[i].hcode; 21500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return True; 21510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 21520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 21530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return False; 21540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 21550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21560ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void unredir_discard_translations( Addr64 guest_start, ULong range ) 21570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 21580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 21590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(sanity_check_redir_tt_tc()); 21610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i <= unredir_tt_highwater; i++) { 21630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].inUse 21640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj && overlaps( guest_start, range, &unredir_tt[i].vge)) 21650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = False; 21660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 21670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 21680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/ 2171fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation. ---*/ 2172fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2173fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2174fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void ) 21756c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 21766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, j, avg_codeszQ; 2177de4a1d01951937632098a6cda45859afa587a06fsewardj 2178663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(!init_done); 2179663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj init_done = True; 2180663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 2181fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Otherwise lots of things go wrong... */ 2182fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sizeof(ULong) == 8); 2183fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sizeof(Addr64) == 8); 21845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache entries really are 2 words long */ 21855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof(Addr) == sizeof(void*)); 21865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof(FastCacheEntry) == 2 * sizeof(Addr)); 21875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache entries are packed back-to-back with no spaces */ 21885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof( VG_(tt_fast) ) == VG_TT_FAST_SIZE * sizeof(FastCacheEntry)); 21895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache is aligned as we requested. Not fatal if it 21905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj isn't, but we might as well make sure. */ 21915f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_IS_16_ALIGNED( ((Addr) & VG_(tt_fast)[0]) )); 2192de4a1d01951937632098a6cda45859afa587a06fsewardj 2193fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 2194fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2195fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "TT/TC: VG_(init_tt_tc) " 2196738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "(startup of code management)\n"); 2197fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2198fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Figure out how big each tc area should be. */ 219943b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn avg_codeszQ = (VG_(details).avg_translation_sizeB + 7) / 8; 220043b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn tc_sector_szQ = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ); 2201fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2202fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Ensure the calculated value is not way crazy. */ 2203fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR_USABLE); 22041e0fff690e9c571275e8025eb2dcff7bf29b53afsewardj vg_assert(tc_sector_szQ <= 100 * N_TTES_PER_SECTOR_USABLE); 2205fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2206fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Initialise the sectors */ 2207fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector = 0; 2208fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_SECTORS; i++) { 2209fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tc = NULL; 2210fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tt = NULL; 2211fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tc_next = NULL; 2212fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[i].tt_n_inuse = 0; 22136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < ECLASS_N; j++) { 22146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sectors[i].ec2tte_size[j] = 0; 22156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sectors[i].ec2tte_used[j] = 0; 22166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sectors[i].ec2tte[j] = NULL; 22176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 2218291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sectors[i].host_extents = NULL; 22196c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 22204ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 22215d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Initialise the sector_search_order hint table. */ 22225d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj for (i = 0; i < N_SECTORS; i++) 22235d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i] = -1; 22245d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 2225291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Initialise the fast cache. */ 2226fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 2227fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 22280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* and the unredir tt/tc */ 22290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj init_unredir_tt_tc(); 22300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 2231059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj if (VG_(clo_verbosity) > 2 || VG_(clo_stats)) { 2232fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2233738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "TT/TC: cache: %d sectors of %d bytes each = %d total\n", 2234fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS, 8 * tc_sector_szQ, 2235fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS * 8 * tc_sector_szQ ); 2236fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2237738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "TT/TC: table: %d total entries, max occupancy %d (%d%%)\n", 2238fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS * N_TTES_PER_SECTOR, 2239fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_SECTORS * N_TTES_PER_SECTOR_USABLE, 2240fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj SECTOR_TT_LIMIT_PERCENT ); 2241fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 224245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 224345f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "transtab", 224445f4e7c91119c7d01a59f5e827c67841632c9314sewardj "cache: %d sectors of %d bytes each = %d total\n", 224545f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_SECTORS, 8 * tc_sector_szQ, 224645f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_SECTORS * 8 * tc_sector_szQ ); 224745f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "transtab", 224845f4e7c91119c7d01a59f5e827c67841632c9314sewardj "table: %d total entries, max occupancy %d (%d%%)\n", 224945f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_SECTORS * N_TTES_PER_SECTOR, 225045f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_SECTORS * N_TTES_PER_SECTOR_USABLE, 225145f4e7c91119c7d01a59f5e827c67841632c9314sewardj SECTOR_TT_LIMIT_PERCENT ); 2252de4a1d01951937632098a6cda45859afa587a06fsewardj} 2253de4a1d01951937632098a6cda45859afa587a06fsewardj 22544ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 2255fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2256fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics. ---*/ 2257fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2258fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2259fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong safe_idiv( ULong a, ULong b ) 226092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{ 226192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote return (b == 0 ? 0 : a / b); 226292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote} 226392e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote 2264fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void ) 2265fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 2266fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return n_in_count; 2267fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 2268fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2269fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void ) 227092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{ 227192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 2272738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " tt/tc: %'llu tt lookups requiring %'llu probes\n", 2273fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_full_lookups, n_lookup_probes ); 227492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 2275738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " tt/tc: %'llu fast-cache updates, %'llu flushes\n", 2276fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_updates, n_fast_flushes ); 2277fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 227892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 2279a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart " transtab: new %'lld " 2280738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "(%'llu -> %'llu; ratio %'llu:10) [%'llu scs]\n", 2281fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_count, n_in_osize, n_in_tsize, 228226412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj safe_idiv(10*n_in_tsize, n_in_osize), 228326412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj n_in_sc_count); 228492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 2285738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " transtab: dumped %'llu (%'llu -> ?" "?)\n", 2286fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_dump_count, n_dump_osize ); 2287fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2288738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " transtab: discarded %'llu (%'llu -> ?" "?)\n", 2289fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_disc_count, n_disc_osize ); 22906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 22913a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) { 22926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 22936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n"); 22946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 22956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)(" %4d", sectors[0].ec2tte_used[i]); 22966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (i % 16 == 15) 22976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n"); 22986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 22996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n\n"); 23006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 230192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote} 2302de4a1d01951937632098a6cda45859afa587a06fsewardj 2303fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2304fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results. ---*/ 2305fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 23064ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 2307fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong score ( TTEntry* tte ) 2308fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 2309fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return ((ULong)tte->weight) * ((ULong)tte->count); 2310de4a1d01951937632098a6cda45859afa587a06fsewardj} 2311de4a1d01951937632098a6cda45859afa587a06fsewardj 231217c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardjULong VG_(get_SB_profile) ( SBProfEntry tops[], UInt n_tops ) 2313de4a1d01951937632098a6cda45859afa587a06fsewardj{ 2314fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int sno, i, r, s; 23152025cf98a3210c175a90fc77cb599cca1643bd68njn ULong score_total; 2316fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2317fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* First, compute the total weighted count, and find the top N 23182025cf98a3210c175a90fc77cb599cca1643bd68njn ttes. tops contains pointers to the most-used n_tops blocks, in 2319fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj descending order (viz, tops[0] is the highest scorer). */ 23202025cf98a3210c175a90fc77cb599cca1643bd68njn for (i = 0; i < n_tops; i++) { 23212025cf98a3210c175a90fc77cb599cca1643bd68njn tops[i].addr = 0; 23222025cf98a3210c175a90fc77cb599cca1643bd68njn tops[i].score = 0; 23232025cf98a3210c175a90fc77cb599cca1643bd68njn } 2324fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2325fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_total = 0; 2326fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2327fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (sno = 0; sno < N_SECTORS; sno++) { 2328fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tc == NULL) 232918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj continue; 2330fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 2331fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[i].status != InUse) 2332fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 2333fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_total += score(§ors[sno].tt[i]); 2334fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find the rank for sectors[sno].tt[i]. */ 23352025cf98a3210c175a90fc77cb599cca1643bd68njn r = n_tops-1; 2336fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj while (True) { 2337fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (r == -1) 2338fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 23392025cf98a3210c175a90fc77cb599cca1643bd68njn if (tops[r].addr == 0) { 2340fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r--; 2341fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 2342fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 23432025cf98a3210c175a90fc77cb599cca1643bd68njn if ( score(§ors[sno].tt[i]) > tops[r].score ) { 2344fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r--; 2345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 2346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 2348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r++; 23502025cf98a3210c175a90fc77cb599cca1643bd68njn vg_assert(r >= 0 && r <= n_tops); 2351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This bb should be placed at r, and bbs above it shifted 2352fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj upwards one slot. */ 23532025cf98a3210c175a90fc77cb599cca1643bd68njn if (r < n_tops) { 23542025cf98a3210c175a90fc77cb599cca1643bd68njn for (s = n_tops-1; s > r; s--) 2355fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tops[s] = tops[s-1]; 23562025cf98a3210c175a90fc77cb599cca1643bd68njn tops[r].addr = sectors[sno].tt[i].entry; 23572025cf98a3210c175a90fc77cb599cca1643bd68njn tops[r].score = score( §ors[sno].tt[i] ); 2358fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2359de4a1d01951937632098a6cda45859afa587a06fsewardj } 2360de4a1d01951937632098a6cda45859afa587a06fsewardj } 2361de4a1d01951937632098a6cda45859afa587a06fsewardj 236217c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj /* Now zero out all the counter fields, so that we can make 236317c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj multiple calls here and just get the values since the last call, 236417c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj each time, rather than values accumulated for the whole run. */ 236517c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj for (sno = 0; sno < N_SECTORS; sno++) { 236617c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj if (sectors[sno].tc == NULL) 236717c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj continue; 236817c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 236917c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj if (sectors[sno].tt[i].status != InUse) 237017c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj continue; 237117c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj sectors[sno].tt[i].count = 0; 237217c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj } 237317c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj } 237417c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj 23752025cf98a3210c175a90fc77cb599cca1643bd68njn return score_total; 2376c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj} 2377c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 2378de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 23798bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end ---*/ 2380de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 2381