m_transtab.c revision 5e47e3fae6c8bd8e3b669801a1edbc30ec10499c
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 110f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj Copyright (C) 2000-2013 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 568e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe/* Nr of sectors provided via command line parameter. */ 578e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippeUInt VG_(clo_num_transtab_sectors) = N_SECTORS_DEFAULT; 588e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe/* Nr of sectors. 598e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe Will be set by VG_(init_tt_tc) to VG_(clo_num_transtab_sectors). */ 60a11ec17946cdbafb336e9121b64961c0633af2e7sewardjstatic UInt n_sectors = 0; 61de4a1d01951937632098a6cda45859afa587a06fsewardj 628e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe/*------------------ CONSTANTS ------------------*/ 63fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of TC entries in each sector. This needs to be a prime 646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj number to work properly, it must be <= 65535 (so that a TT index 656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj fits in a UShort, leaving room for 0xFFFF(EC2TTE_DELETED) to denote 666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 'deleted') and it is strongly recommended not to change this. 676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 65521 is the largest prime <= 65535. */ 68e25053c5aaefc6a4039dcd557adf24d8bb23db69sewardj#define N_TTES_PER_SECTOR /*10007*/ /*30011*/ /*40009*/ 65521 69de4a1d01951937632098a6cda45859afa587a06fsewardj 70fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to 71fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj specify the maximum allowable loading, after which the sector is 72fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj deemed full. */ 735d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj#define SECTOR_TT_LIMIT_PERCENT 65 74de4a1d01951937632098a6cda45859afa587a06fsewardj 75fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */ 76fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_TTES_PER_SECTOR_USABLE \ 77fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ((N_TTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100) 786c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Equivalence classes for fast address range deletion. There are 1 + 806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 2^ECLASS_WIDTH bins. The highest one, ECLASS_MISC, describes an 816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range which does not fall cleanly within any specific bin. 826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Note that ECLASS_SHIFT + ECLASS_WIDTH must be < 32. */ 836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_SHIFT 11 846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_WIDTH 8 856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_MISC (1 << ECLASS_WIDTH) 866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_N (1 + ECLASS_MISC) 876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define EC2TTE_DELETED 0xFFFF /* 16-bit special value */ 896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 90de4a1d01951937632098a6cda45859afa587a06fsewardj 916c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/ 92de4a1d01951937632098a6cda45859afa587a06fsewardj 93291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* In edges ("to-me") in the graph created by chaining. */ 94291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 95291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 96291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_sNo; /* sector number */ 97291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_tteNo; /* TTE number in given sector */ 98291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_offs; /* code offset from TCEntry::tcptr where the patch is */ 99291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool to_fastEP; /* Is the patch to a fast or slow entry point? */ 100291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 101291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge; 102291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 103291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 104291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Out edges ("from-me") in the graph created by chaining. */ 105291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 106291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 107291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt to_sNo; /* sector number */ 108291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt to_tteNo; /* TTE number in given sector */ 109291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_offs; /* code offset in owning translation where patch is */ 110291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 111291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge; 112291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 113291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 114291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_IN_EDGE_ARR 3 115291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 116291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 117291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt n_fixed; /* 0 .. N_FIXED_IN_EDGE_ARR */ 118291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge fixed[N_FIXED_IN_EDGE_ARR]; 119291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* var; /* XArray* of InEdgeArr */ 120291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 121291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr; 122291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 123291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_OUT_EDGE_ARR 2 124291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 125291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 126291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt n_fixed; /* 0 .. N_FIXED_OUT_EDGE_ARR */ 127291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge fixed[N_FIXED_OUT_EDGE_ARR]; 128291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* var; /* XArray* of OutEdgeArr */ 129291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 130291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr; 131291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 132291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 133fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry. This indicates precisely which areas of 134fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj guest code are included in the translation, and contains all other 135fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj auxiliary info too. */ 1366c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef 1376c3769f487145a08c01b58d6e5db3ba274062ad4sewardj struct { 138fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Profiling only: the count and weight (arbitrary meaning) for 139fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj this translation. Weight is a property of the translation 140fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj itself and computed once when the translation is created. 141fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Count is an entry count for the translation and is 142fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj incremented by 1 every time the translation is used, if we 143fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj are profiling. */ 144291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ULong count; 145fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UShort weight; 146fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 147fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Status of the slot. Note, we need to be able to do lazy 148fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj deletion, hence the Deleted state. */ 149fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj enum { InUse, Deleted, Empty } status; 150fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1515f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* 64-bit aligned pointer to one or more 64-bit words containing 1525f76de086a6d643db51e50a4e623df7dfc9b6161sewardj the corresponding host code (must be in the same sector!) 1535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj This is a pointer into the sector's tc (code) area. */ 1545f76de086a6d643db51e50a4e623df7dfc9b6161sewardj ULong* tcptr; 155fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 156fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This is the original guest address that purportedly is the 157fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj entry point of the translation. You might think that .entry 158fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj should be the same as .vge->base[0], and most of the time it 159fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj is. However, when doing redirections, that is not the case. 160fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj .vge must always correctly describe the guest code sections 161fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj from which this translation was made. However, .entry may or 162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj may not be a lie, depending on whether or not we're doing 163fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj redirection. */ 164ddd61ff058f02059064e083a8accaefed23d5548florian Addr entry; 165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 166fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This structure describes precisely what ranges of guest code 167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj the translation covers, so we can decide whether or not to 168fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj delete it when translations of a given address range are 169fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidated. */ 170fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VexGuestExtents vge; 1716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Address range summary info: these are pointers back to 1736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclass[] entries in the containing Sector. Those entries in 1746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj turn point back here -- the two structures are mutually 1756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj redundant but both necessary to make fast deletions work. 1766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj The eclass info is similar to, and derived from, this entry's 1776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 'vge' field, but it is not the same */ 1786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort n_tte2ec; // # tte2ec pointers (1 to 3) 1796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort tte2ec_ec[3]; // for each, the eclass # 1806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt tte2ec_ix[3]; // and the index within the eclass. 1816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // for i in 0 .. n_tte2ec-1 1826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // sec->ec2tte[ tte2ec_ec[i] ][ tte2ec_ix[i] ] 1836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // should be the index 1846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // of this TTEntry in the containing Sector's tt array. 185291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 186291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Admin information for chaining. 'in_edges' is a set of the 187291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj patch points which jump to this translation -- hence are 188291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj predecessors in the control flow graph. 'out_edges' points 189291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj to successors in the control flow graph -- translations to 190291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj which this one has a patched jump. In short these are just 191291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj backwards and forwards edges in the graph of patched-together 192291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj blocks. The 'in_edges' contain slightly more info, enough 193291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj that we can undo the chaining of each mentioned patch point. 194291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The 'out_edges' list exists only so that we can visit the 195291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 'in_edges' entries of all blocks we're patched through to, in 196291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj order to remove ourselves from then when we're deleted. */ 197291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 198291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* A translation can disappear for two reasons: 199291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 1. erased (as part of the oldest sector cleanup) when the 200291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj youngest sector is full. 201291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 2. discarded due to calls to VG_(discard_translations). 202291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(discard_translations) sets the status of the 203291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation to 'Deleted'. 204291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj A.o., the gdbserver discards one or more translations 205291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj when a breakpoint is inserted or removed at an Addr, 206291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj or when single stepping mode is enabled/disabled 207291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj or when a translation is instrumented for gdbserver 208291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (all the target jumps of this translation are 209291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj invalidated). 210291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 211291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj So, it is possible that the translation A to be patched 212291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (to obtain a patched jump from A to B) is invalidated 213291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj after B is translated and before A is patched. 214291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj In case a translation is erased or discarded, the patching 215291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj cannot be done. VG_(tt_tc_do_chaining) and find_TTEntry_from_hcode 216291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj are checking the 'from' translation still exists before 217291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj doing the patching. 218291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 219291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Is it safe to erase or discard the current translation E being 220291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj executed ? Amazing, but yes, it is safe. 221291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Here is the explanation: 222291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 223291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The translation E being executed can only be erased if a new 224291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation N is being done. A new translation is done only 225291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if the host addr is a not yet patched jump to another 226291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation. In such a case, the guest address of N is 227291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj assigned to the PC in the VEX state. Control is returned 228291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj to the scheduler. N will be translated. This can erase the 229291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation E (in case of sector full). VG_(tt_tc_do_chaining) 230291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj will not do the chaining to a non found translation E. 231291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The execution will continue at the current guest PC 232291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (i.e. the translation N). 233291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj => it is safe to erase the current translation being executed. 234291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 235291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The current translation E being executed can also be discarded 236291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (e.g. by gdbserver). VG_(discard_translations) will mark 237291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj this translation E as Deleted, but the translation itself 238291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj is not erased. In particular, its host code can only 239291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj be overwritten or erased in case a new translation is done. 240291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj A new translation will only be done if a not yet translated 241291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj jump is to be executed. The execution of the Deleted translation 242291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj E will continue till a non patched jump is encountered. 243291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj This situation is then similar to the 'erasing' case above : 244291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj the current translation E can be erased or overwritten, as the 245291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj execution will continue at the new translation N. 246291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 247291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj */ 248291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 249291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* It is possible, although very unlikely, that a block A has 250291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj more than one patched jump to block B. This could happen if 251291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (eg) A finishes "jcond B; jmp B". 252291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 253291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj This means in turn that B's in_edges set can list A more than 254291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj once (twice in this example). However, each such entry must 255291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj have a different from_offs, since a patched jump can only 256291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj jump to one place at once (it's meaningless for it to have 257291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj multiple destinations.) IOW, the successor and predecessor 258291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj edges in the graph are not uniquely determined by a 259291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry --> TTEntry pair, but rather by a 260291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (TTEntry,offset) --> TTEntry triple. 261291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 262291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj If A has multiple edges to B then B will mention A multiple 263291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj times in its in_edges. To make things simpler, we then 264291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj require that A mentions B exactly the same number of times in 265291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj its out_edges. Furthermore, a matching out-in pair must have 266291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj the same offset (from_offs). This facilitates sanity 267291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj checking, and it facilitates establishing the invariant that 268291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj a out_edges set may not have duplicates when using the 269291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj equality defined by (TTEntry,offset). Hence the out_edges 270291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj and in_edges sets really do have both have set semantics. 271291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 272291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj eg if A has been patched to B at offsets 42 and 87 (in A) 273291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj then A.out_edges = { (B,42), (B,87) } (in any order) 274291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj and B.in_edges = { (A,42), (A,87) } (in any order) 275291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 276291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Hence for each node pair P->Q in the graph, there's a 1:1 277291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj mapping between P.out_edges and Q.in_edges. 278291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj */ 279291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr in_edges; 280291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr out_edges; 2816c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 2826c3769f487145a08c01b58d6e5db3ba274062ad4sewardj TTEntry; 2836c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 2844ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 285291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* A structure used for mapping host code addresses back to the 286291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj relevant TTEntry. Used when doing chaining, for finding the 287291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry to which some arbitrary patch address belongs. */ 288291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 289291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 290291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* start; 291291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt len; 292291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt tteNo; 293291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 294291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent; 295291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 296fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself. Each sector contains an array of 297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TCEntries, which hold code, and an array of TTEntries, containing 298fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj all required administrative info. Profiling is supported using the 299291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry .count and .weight fields, if required. 3004ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj If the sector is not in use, all three pointers are NULL and 302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tt_n_inuse is zero. 303fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 304fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef 305fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj struct { 306fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The TCEntry area. Size of this depends on the average 307fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj translation size. We try and size it so it becomes full 308fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj precisely when this sector's translation table (tt) reaches 309fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj its load limit (SECTOR_TT_LIMIT_PERCENT). */ 310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tc; 3114ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 312fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The TTEntry array. This is a fixed size, always containing 313fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj exactly N_TTES_PER_SECTOR entries. */ 314fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TTEntry* tt; 3156c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 316fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This points to the current allocation point in tc. */ 317fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tc_next; 318de4a1d01951937632098a6cda45859afa587a06fsewardj 319fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The count of tt entries with state InUse. */ 320fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int tt_n_inuse; 3216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 3226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Expandable arrays of tt indices for each of the ECLASS_N 3236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range equivalence classes. These hold indices into 3246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj the containing sector's tt array, which in turn should point 3256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj back here. */ 3266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int ec2tte_size[ECLASS_N]; 3276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int ec2tte_used[ECLASS_N]; 3286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort* ec2tte[ECLASS_N]; 329291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 330291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* The host extents. The [start, +len) ranges are constructed 331291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj in strictly non-overlapping order, so we can binary search 332291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj them at any time. */ 333291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* host_extents; /* XArray* of HostExtent */ 334fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 335fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Sector; 336de4a1d01951937632098a6cda45859afa587a06fsewardj 337de4a1d01951937632098a6cda45859afa587a06fsewardj 3386c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/ 3396c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 340fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors. The index of the 341fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest sector is recorded, and new translations are put into that 342fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. When it fills up, we move along to the next sector and 343fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj start to fill that up, wrapping around at the end of the array. 344fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj That way, once all N_TC_SECTORS have been bought into use for the 345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj first time, and are full, we then re-use the oldest sector, 346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj endlessly. 347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj When running, youngest sector should be between >= 0 and < 349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj N_TC_SECTORS. The initial -1 value indicates the TT/TC system is 350fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj not yet initialised. 351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 3528e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippestatic Sector sectors[MAX_N_SECTORS]; 353fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int youngest_sector = -1; 3546c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 355fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area. This is computed once 356fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj at startup and does not change. */ 357a11ec17946cdbafb336e9121b64961c0633af2e7sewardjstatic Int tc_sector_szQ = 0; 3586c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 3596c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 3605d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj/* A list of sector numbers, in the order which they should be 3615d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj searched to find translations. This is an optimisation to be used 3625d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj when searching for translations and should not affect 3635d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj correctness. -1 denotes "no entry". */ 3648e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippestatic Int sector_search_order[MAX_N_SECTORS]; 3655d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 3665d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 3675f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Fast helper for the TC. A direct-mapped cache which holds a set of 3685f76de086a6d643db51e50a4e623df7dfc9b6161sewardj recently used (guest address, host address) pairs. This array is 3695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj referred to directly from m_dispatch/dispatch-<platform>.S. 3706c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 3715f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Entries in tt_fast may refer to any valid TC entry, regardless of 372fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj which sector it's in. Consequently we must be very careful to 373fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidate this cache when TC entries are changed or disappear. 374c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 3755f76de086a6d643db51e50a4e623df7dfc9b6161sewardj A special .guest address - TRANSTAB_BOGUS_GUEST_ADDR -- must be 3765f76de086a6d643db51e50a4e623df7dfc9b6161sewardj pointed at to cause that cache entry to miss. This relies on the 3775f76de086a6d643db51e50a4e623df7dfc9b6161sewardj assumption that no guest code actually has that address, hence a 3785f76de086a6d643db51e50a4e623df7dfc9b6161sewardj value 0x1 seems good. m_translate gives the client a synthetic 3795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj segfault if it tries to execute at this address. 3805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/ 3815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* 3825f76de086a6d643db51e50a4e623df7dfc9b6161sewardjtypedef 3835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj struct { 3845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Addr guest; 3855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Addr host; 3865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 3875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj FastCacheEntry; 3885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/ 3895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*global*/ __attribute__((aligned(16))) 3905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj FastCacheEntry VG_(tt_fast)[VG_TT_FAST_SIZE]; 391de4a1d01951937632098a6cda45859afa587a06fsewardj 392663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */ 393663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False; 394663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 395663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 396fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/ 397de4a1d01951937632098a6cda45859afa587a06fsewardj 398fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */ 399291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_flushes = 0; 400291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_updates = 0; 40122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 402fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */ 403291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_full_lookups = 0; 404291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_lookup_probes = 0; 40522854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 40626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj/* Number/osize/tsize of translations entered; also the number of 40726412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj those for which self-checking was requested. */ 408291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_count = 0; 409291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_osize = 0; 410291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_tsize = 0; 411291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_sc_count = 0; 412de4a1d01951937632098a6cda45859afa587a06fsewardj 413fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */ 414291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_count = 0; 415291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_osize = 0; 4165e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippestatic ULong n_sectors_recycled = 0; 417fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 418fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */ 419291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_count = 0; 420291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_osize = 0; 421291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 422291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 423291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 424291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Misc ---*/ 425291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 426291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 42754fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorianstatic void* ttaux_malloc ( const HChar* tag, SizeT n ) 428291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 429291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return VG_(arena_malloc)(VG_AR_TTAUX, tag, n); 430291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 431291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 432291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void ttaux_free ( void* p ) 433291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 434291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(arena_free)(VG_AR_TTAUX, p); 435291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 436291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 437291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 438291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 439291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Chaining support ---*/ 440291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 441291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 442291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic inline TTEntry* index_tte ( UInt sNo, UInt tteNo ) 443291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 4448e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(sNo < n_sectors); 445291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(tteNo < N_TTES_PER_SECTOR); 446291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Sector* s = §ors[sNo]; 447291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(s->tt); 448291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* tte = &s->tt[tteNo]; 449291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(tte->status == InUse); 450291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return tte; 451291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 452291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 453291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdge__init ( InEdge* ie ) 454291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 455291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->from_sNo = -1; /* invalid */ 456291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->from_tteNo = 0; 457291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->from_offs = 0; 458291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->to_fastEP = False; 459291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 460291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 461291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdge__init ( OutEdge* oe ) 462291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 463291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe->to_sNo = -1; /* invalid */ 464291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe->to_tteNo = 0; 465291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe->from_offs = 0; 466291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 467291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 468291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void TTEntry__init ( TTEntry* tte ) 469291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 470291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(memset)(tte, 0, sizeof(*tte)); 471291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 472291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 473518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UWord InEdgeArr__size ( const InEdgeArr* iea ) 474291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 475291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->var) { 476291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 477291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return VG_(sizeXA)(iea->var); 478291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 479291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR); 480291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return iea->n_fixed; 481291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 482291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 483291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 484291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdgeArr__makeEmpty ( InEdgeArr* iea ) 485291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 486291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->var) { 487291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 488291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(deleteXA)(iea->var); 489291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->var = NULL; 490291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 491291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR); 492291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->n_fixed = 0; 493291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 494291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 495291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 496291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 497291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjInEdge* InEdgeArr__index ( InEdgeArr* iea, UWord i ) 498291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 499291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->var) { 500291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 501291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return (InEdge*)VG_(indexXA)(iea->var, i); 502291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 503291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < iea->n_fixed); 504291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return &iea->fixed[i]; 505291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 506291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 507291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 508291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 509291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__deleteIndex ( InEdgeArr* iea, UWord i ) 510291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 511291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->var) { 512291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 513291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(removeIndexXA)(iea->var, i); 514291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 515291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < iea->n_fixed); 516291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (; i+1 < iea->n_fixed; i++) { 517291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->fixed[i] = iea->fixed[i+1]; 518291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 519291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->n_fixed--; 520291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 521291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 522291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 523291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 524291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__add ( InEdgeArr* iea, InEdge* ie ) 525291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 526291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->var) { 527291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 528291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(iea->var, ie); 529291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 530291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR); 531291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->n_fixed == N_FIXED_IN_EDGE_ARR) { 532291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* The fixed array is full, so we have to initialise an 533291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray and copy the fixed array into it. */ 534291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->var = VG_(newXA)(ttaux_malloc, "transtab.IEA__add", 535291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free, 536291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sizeof(InEdge)); 537291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UWord i; 538291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < iea->n_fixed; i++) { 539291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(iea->var, &iea->fixed[i]); 540291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 541291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(iea->var, ie); 542291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->n_fixed = 0; 543291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 544291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Just add to the fixed array. */ 545291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->fixed[iea->n_fixed++] = *ie; 546291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 547291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 548291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 549291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 550518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UWord OutEdgeArr__size ( const OutEdgeArr* oea ) 551291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 552291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->var) { 553291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 554291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return VG_(sizeXA)(oea->var); 555291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 556291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR); 557291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return oea->n_fixed; 558291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 559291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 560291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 561291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdgeArr__makeEmpty ( OutEdgeArr* oea ) 562291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 563291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->var) { 564291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 565291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(deleteXA)(oea->var); 566291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->var = NULL; 567291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 568291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR); 569291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->n_fixed = 0; 570291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 571291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 572291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 573291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 574291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjOutEdge* OutEdgeArr__index ( OutEdgeArr* oea, UWord i ) 575291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 576291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->var) { 577291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 578291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return (OutEdge*)VG_(indexXA)(oea->var, i); 579291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 580291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < oea->n_fixed); 581291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return &oea->fixed[i]; 582291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 583291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 584291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 585291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 586291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__deleteIndex ( OutEdgeArr* oea, UWord i ) 587291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 588291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->var) { 589291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 590291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(removeIndexXA)(oea->var, i); 591291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 592291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < oea->n_fixed); 593291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (; i+1 < oea->n_fixed; i++) { 594291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->fixed[i] = oea->fixed[i+1]; 595291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 596291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->n_fixed--; 597291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 598291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 599291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 600291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 601291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__add ( OutEdgeArr* oea, OutEdge* oe ) 602291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 603291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->var) { 604291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 605291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(oea->var, oe); 606291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 607291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR); 608291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->n_fixed == N_FIXED_OUT_EDGE_ARR) { 609291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* The fixed array is full, so we have to initialise an 610291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray and copy the fixed array into it. */ 611291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->var = VG_(newXA)(ttaux_malloc, "transtab.OEA__add", 612291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free, 613291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sizeof(OutEdge)); 614291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UWord i; 615291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < oea->n_fixed; i++) { 616291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(oea->var, &oea->fixed[i]); 617291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 618291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(oea->var, oe); 619291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->n_fixed = 0; 620291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 621291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Just add to the fixed array. */ 622291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->fixed[oea->n_fixed++] = *oe; 623291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 624291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 625291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 626291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 627291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 6286bd9dc18c043927c1196caba20a327238a179c42florianInt HostExtent__cmpOrd ( const void* v1, const void* v2 ) 629291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 6306bd9dc18c043927c1196caba20a327238a179c42florian const HostExtent* hx1 = v1; 6316bd9dc18c043927c1196caba20a327238a179c42florian const HostExtent* hx2 = v2; 632291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (hx1->start + hx1->len <= hx2->start) return -1; 633291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (hx2->start + hx2->len <= hx1->start) return 1; 634291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return 0; /* partial overlap */ 635291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 636291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 6373a5322057616d0da214b9e0f897866e203c03e40philippe/* True if hx is a dead host extent, i.e. corresponds to host code 6383a5322057616d0da214b9e0f897866e203c03e40philippe of an entry that was invalidated. */ 6393a5322057616d0da214b9e0f897866e203c03e40philippestatic 6403a5322057616d0da214b9e0f897866e203c03e40philippeBool HostExtent__is_dead (const HostExtent* hx, const Sector* sec) 6413a5322057616d0da214b9e0f897866e203c03e40philippe{ 6423a5322057616d0da214b9e0f897866e203c03e40philippe const UInt tteNo = hx->tteNo; 6433a5322057616d0da214b9e0f897866e203c03e40philippe#define LDEBUG(m) if (DEBUG_TRANSTAB) \ 6443a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf) (m \ 6453a5322057616d0da214b9e0f897866e203c03e40philippe " start 0x%p len %u sector %d ttslot %u" \ 646ddd61ff058f02059064e083a8accaefed23d5548florian " tt.entry 0x%lu tt.tcptr 0x%p\n", \ 6473a5322057616d0da214b9e0f897866e203c03e40philippe hx->start, hx->len, (int)(sec - sectors), \ 6483a5322057616d0da214b9e0f897866e203c03e40philippe hx->tteNo, \ 6493a5322057616d0da214b9e0f897866e203c03e40philippe sec->tt[tteNo].entry, sec->tt[tteNo].tcptr) 6503a5322057616d0da214b9e0f897866e203c03e40philippe 6513a5322057616d0da214b9e0f897866e203c03e40philippe /* Entry might have been invalidated and not re-used yet.*/ 6523a5322057616d0da214b9e0f897866e203c03e40philippe if (sec->tt[tteNo].status == Deleted) { 6533a5322057616d0da214b9e0f897866e203c03e40philippe LDEBUG("found deleted entry"); 6543a5322057616d0da214b9e0f897866e203c03e40philippe return True; 6553a5322057616d0da214b9e0f897866e203c03e40philippe } 6563a5322057616d0da214b9e0f897866e203c03e40philippe /* Maybe we found this entry via a host_extents which was 6573a5322057616d0da214b9e0f897866e203c03e40philippe inserted for an entry which was changed to Deleted then 6583a5322057616d0da214b9e0f897866e203c03e40philippe re-used after. If this entry was re-used, then its tcptr 6593a5322057616d0da214b9e0f897866e203c03e40philippe is >= to host_extents start (i.e. the previous tcptr) + len. 6603a5322057616d0da214b9e0f897866e203c03e40philippe This is the case as there is no re-use of host code: a new 6613a5322057616d0da214b9e0f897866e203c03e40philippe entry or re-used entry always gets "higher value" host code. */ 6623a5322057616d0da214b9e0f897866e203c03e40philippe if ((UChar*) sec->tt[tteNo].tcptr >= hx->start + hx->len) { 6633a5322057616d0da214b9e0f897866e203c03e40philippe LDEBUG("found re-used entry"); 6643a5322057616d0da214b9e0f897866e203c03e40philippe return True; 6653a5322057616d0da214b9e0f897866e203c03e40philippe } 6663a5322057616d0da214b9e0f897866e203c03e40philippe 6673a5322057616d0da214b9e0f897866e203c03e40philippe return False; 6683a5322057616d0da214b9e0f897866e203c03e40philippe#undef LDEBUG 6693a5322057616d0da214b9e0f897866e203c03e40philippe} 6703a5322057616d0da214b9e0f897866e203c03e40philippe 671291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic __attribute__((noinline)) 672291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool find_TTEntry_from_hcode( /*OUT*/UInt* from_sNo, 673291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /*OUT*/UInt* from_tteNo, 674291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj void* hcode ) 675291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 676291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int i; 677291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 678291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Search order logic copied from VG_(search_transtab). */ 6798e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 680291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int sno = sector_search_order[i]; 681291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (UNLIKELY(sno == -1)) 682291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; /* run out of sectors to search */ 683291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 684518850bf0da07ed3e2244e307268ae0fd80e93a8florian const Sector* sec = §ors[sno]; 685518850bf0da07ed3e2244e307268ae0fd80e93a8florian const XArray* /* of HostExtent */ host_extents = sec->host_extents; 686291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(host_extents); 687291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 688291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent key; 689291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(memset)(&key, 0, sizeof(key)); 690291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj key.start = hcode; 691291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj key.len = 1; 692291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Word firstW = -1, lastW = -1; 693291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool found = VG_(lookupXA_UNSAFE)( 694291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj host_extents, &key, &firstW, &lastW, 6956bd9dc18c043927c1196caba20a327238a179c42florian HostExtent__cmpOrd ); 696291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(firstW == lastW); // always true, even if not found 697291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (found) { 698291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent* hx = VG_(indexXA)(host_extents, firstW); 699291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt tteNo = hx->tteNo; 700291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Do some additional sanity checks. */ 701291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(tteNo <= N_TTES_PER_SECTOR); 7023a5322057616d0da214b9e0f897866e203c03e40philippe 7033a5322057616d0da214b9e0f897866e203c03e40philippe /* if this hx entry corresponds to dead host code, we must 7043a5322057616d0da214b9e0f897866e203c03e40philippe tell this code has not been found, as it cannot be patched. */ 7053a5322057616d0da214b9e0f897866e203c03e40philippe if (HostExtent__is_dead (hx, sec)) 706291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; 7073a5322057616d0da214b9e0f897866e203c03e40philippe 708291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec->tt[tteNo].status == InUse); 709291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Can only half check that the found TTEntry contains hcode, 710291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj due to not having a length value for the hcode in the 711291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry. */ 712291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert((UChar*)sec->tt[tteNo].tcptr <= (UChar*)hcode); 713291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Looks plausible */ 714291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *from_sNo = sno; 715291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *from_tteNo = (UInt)tteNo; 716291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return True; 717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 718291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; 720291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 721291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 722291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 723291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Figure out whether or not hcode is jitted code present in the main 724291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj code cache (but not in the no-redir cache). Used for sanity 725291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj checking. */ 726518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool is_in_the_main_TC ( const void* hcode ) 727291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 728291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int i, sno; 7298e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 730291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sno = sector_search_order[i]; 731291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (sno == -1) 732291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj break; /* run out of sectors to search */ 733518850bf0da07ed3e2244e307268ae0fd80e93a8florian if ((const UChar*)hcode >= (const UChar*)sectors[sno].tc 734518850bf0da07ed3e2244e307268ae0fd80e93a8florian && (const UChar*)hcode <= (const UChar*)sectors[sno].tc_next 735291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj + sizeof(ULong) - 1) 736291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return True; 737291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 738291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; 739291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 740291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 741291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 742291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Fulfill a chaining request, and record admin info so we 743291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj can undo it later, if required. 744291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj*/ 745291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid VG_(tt_tc_do_chaining) ( void* from__patch_addr, 746291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt to_sNo, 747291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt to_tteNo, 748291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool to_fastEP ) 749291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 750291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Get the CPU info established at startup. */ 751597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host = VexArch_INVALID; 752597314210494248b4fbefd45525a748439629218sewardj VexArchInfo archinfo_host; 753597314210494248b4fbefd45525a748439629218sewardj VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host)); 754597314210494248b4fbefd45525a748439629218sewardj VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host ); 755597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host = archinfo_host.endness; 756291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 757291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // host_code is where we're patching to. So it needs to 758291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // take into account, whether we're jumping to the slow 759291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // or fast entry point. By definition, the fast entry point 760291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // is exactly one event check's worth of code along from 761291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // the slow (tcptr) entry point. 762291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* to_tte = index_tte(to_sNo, to_tteNo); 763291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj void* host_code = ((UChar*)to_tte->tcptr) 7645f8ced84fdd6ebd260cece49b51477c68437e8caflorian + (to_fastEP ? LibVEX_evCheckSzB(arch_host) : 0); 765291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 766291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // stay sane -- the patch point (dst) is in this sector's code cache 767291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( (UChar*)host_code >= (UChar*)sectors[to_sNo].tc ); 768291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( (UChar*)host_code <= (UChar*)sectors[to_sNo].tc_next 769291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj + sizeof(ULong) - 1 ); 770291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 771291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Find the TTEntry for the from__ code. This isn't simple since 772291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj we only know the patch address, which is going to be somewhere 773291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj inside the from_ block. */ 774291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_sNo = (UInt)-1; 775291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt from_tteNo = (UInt)-1; 776291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool from_found 777291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = find_TTEntry_from_hcode( &from_sNo, &from_tteNo, 778291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj from__patch_addr ); 779291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (!from_found) { 780291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // The from code might have been discarded due to sector re-use 781291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // or marked Deleted due to translation invalidation. 782291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // In such a case, don't do the chaining. 783291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(debugLog)(1,"transtab", 784291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj "host code %p not found (discarded? sector recycled?)" 785291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj " => no chaining done\n", 786291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj from__patch_addr); 787291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return; 788291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 789291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 790291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* from_tte = index_tte(from_sNo, from_tteNo); 791291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 792291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Get VEX to do the patching itself. We have to hand it off 793291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj since it is host-dependent. */ 794291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexInvalRange vir 795291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = LibVEX_Chain( 796597314210494248b4fbefd45525a748439629218sewardj arch_host, endness_host, 797291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj from__patch_addr, 798291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(fnptr_to_fnentry)( 799291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP) 800291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj : &VG_(disp_cp_chain_me_to_slowEP)), 801291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (void*)host_code 802291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 803291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( (void*)vir.start, vir.len ); 804291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 805291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Now do the tricky bit -- update the ch_succs and ch_preds info 806291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for the two translations involved, so we can undo the chaining 807291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj later, which we will have to do if the to_ block gets removed 808291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for whatever reason. */ 809291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 810291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* This is the new from_ -> to_ link to add. */ 811291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge ie; 812291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge__init(&ie); 813291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.from_sNo = from_sNo; 814291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.from_tteNo = from_tteNo; 815291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.to_fastEP = to_fastEP; 816291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HWord from_offs = (HWord)( (UChar*)from__patch_addr 817291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj - (UChar*)from_tte->tcptr ); 818291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(from_offs < 100000/* let's say */); 819291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.from_offs = (UInt)from_offs; 820291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 821291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* This is the new to_ -> from_ backlink to add. */ 822291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge oe; 823291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge__init(&oe); 824291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe.to_sNo = to_sNo; 825291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe.to_tteNo = to_tteNo; 826291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe.from_offs = (UInt)from_offs; 827291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 828291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Add .. */ 829291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr__add(&to_tte->in_edges, &ie); 830291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr__add(&from_tte->out_edges, &oe); 831291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 832291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 833291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 834291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Unchain one patch, as described by the specified InEdge. For 835291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sanity check purposes only (to check that the patched location is 836291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj as expected) it also requires the fast and slow entry point 837291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj addresses of the destination block (that is, the block that owns 838291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj this InEdge). */ 839291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj__attribute__((noinline)) 840597314210494248b4fbefd45525a748439629218sewardjstatic void unchain_one ( VexArch arch_host, VexEndness endness_host, 841291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge* ie, 842291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj void* to_fastEPaddr, void* to_slowEPaddr ) 843291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 844291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(ie); 845291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* tte 846291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = index_tte(ie->from_sNo, ie->from_tteNo); 847291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* place_to_patch 84819f91bbaedb4caef8a60ce94b0f507193cc0bc10florian = ((UChar*)tte->tcptr) + ie->from_offs; 849291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* disp_cp_chain_me 850291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = VG_(fnptr_to_fnentry)( 851291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP) 852291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj : &VG_(disp_cp_chain_me_to_slowEP) 853291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 854291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* place_to_jump_to_EXPECTED 855291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = ie->to_fastEP ? to_fastEPaddr : to_slowEPaddr; 856291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 857291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // stay sane: both src and dst for this unchaining are 858291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // in the main code cache 859291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( is_in_the_main_TC(place_to_patch) ); // src 860291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( is_in_the_main_TC(place_to_jump_to_EXPECTED) ); // dst 861291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // dst check is ok because LibVEX_UnChain checks that 862291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // place_to_jump_to_EXPECTED really is the current dst, and 863291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // asserts if it isn't. 864291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexInvalRange vir 865597314210494248b4fbefd45525a748439629218sewardj = LibVEX_UnChain( arch_host, endness_host, place_to_patch, 866291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj place_to_jump_to_EXPECTED, disp_cp_chain_me ); 867291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( (void*)vir.start, vir.len ); 868291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 869291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 870291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 871291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* The specified block is about to be deleted. Update the preds and 872291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj succs of its associated blocks accordingly. This includes undoing 873291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj any chained jumps to this block. */ 874291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 875597314210494248b4fbefd45525a748439629218sewardjvoid unchain_in_preparation_for_deletion ( VexArch arch_host, 876597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host, 877291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt here_sNo, UInt here_tteNo ) 878291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 8793a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 8803a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf)("QQQ unchain_in_prep %u.%u...\n", here_sNo, here_tteNo); 881291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UWord i, j, n, m; 8825f8ced84fdd6ebd260cece49b51477c68437e8caflorian Int evCheckSzB = LibVEX_evCheckSzB(arch_host); 883291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* here_tte = index_tte(here_sNo, here_tteNo); 8843a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 885ddd61ff058f02059064e083a8accaefed23d5548florian VG_(printf)("... QQQ tt.entry 0x%lu tt.tcptr 0x%p\n", 8863a5322057616d0da214b9e0f897866e203c03e40philippe here_tte->entry, here_tte->tcptr); 887291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(here_tte->status == InUse); 888291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 889291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Visit all InEdges owned by here_tte. */ 890291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj n = InEdgeArr__size(&here_tte->in_edges); 891291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < n; i++) { 892291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge* ie = InEdgeArr__index(&here_tte->in_edges, i); 893291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // Undo the chaining. 894291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* here_slow_EP = (UChar*)here_tte->tcptr; 895291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* here_fast_EP = here_slow_EP + evCheckSzB; 896597314210494248b4fbefd45525a748439629218sewardj unchain_one(arch_host, endness_host, ie, here_fast_EP, here_slow_EP); 897291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // Find the corresponding entry in the "from" node's out_edges, 898291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // and remove it. 899291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* from_tte = index_tte(ie->from_sNo, ie->from_tteNo); 900291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj m = OutEdgeArr__size(&from_tte->out_edges); 901291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(m > 0); // it must have at least one entry 902291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (j = 0; j < m; j++) { 903291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge* oe = OutEdgeArr__index(&from_tte->out_edges, j); 904291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oe->to_sNo == here_sNo && oe->to_tteNo == here_tteNo 905291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj && oe->from_offs == ie->from_offs) 906291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj break; 907291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 908291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(j < m); // "oe must be findable" 909291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr__deleteIndex(&from_tte->out_edges, j); 910291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 911291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 912291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Visit all OutEdges owned by here_tte. */ 913291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj n = OutEdgeArr__size(&here_tte->out_edges); 914291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < n; i++) { 915291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge* oe = OutEdgeArr__index(&here_tte->out_edges, i); 916291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // Find the corresponding entry in the "to" node's in_edges, 917291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // and remove it. 918291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* to_tte = index_tte(oe->to_sNo, oe->to_tteNo); 919291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj m = InEdgeArr__size(&to_tte->in_edges); 920291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(m > 0); // it must have at least one entry 921291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (j = 0; j < m; j++) { 922291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge* ie = InEdgeArr__index(&to_tte->in_edges, j); 923291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (ie->from_sNo == here_sNo && ie->from_tteNo == here_tteNo 924291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj && ie->from_offs == oe->from_offs) 925291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj break; 926291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 927291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(j < m); // "ie must be findable" 928291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr__deleteIndex(&to_tte->in_edges, j); 929291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 930291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 931291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr__makeEmpty(&here_tte->in_edges); 932291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr__makeEmpty(&here_tte->out_edges); 933291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 934fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 935fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 9366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 9376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Address-range equivalence class stuff ---*/ 9386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 9396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Return equivalence class number for a range. */ 9416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 942ddd61ff058f02059064e083a8accaefed23d5548florianstatic Int range_to_eclass ( Addr start, UInt len ) 9436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 9446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt mask = (1 << ECLASS_WIDTH) - 1; 9456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt lo = (UInt)start; 9466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt hi = lo + len - 1; 9476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt loBits = (lo >> ECLASS_SHIFT) & mask; 9486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt hiBits = (hi >> ECLASS_SHIFT) & mask; 9496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (loBits == hiBits) { 9506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(loBits < ECLASS_N-1); 9516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return loBits; 9526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 9536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return ECLASS_MISC; 9546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 9556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 9566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Calculates the equivalence class numbers for any VexGuestExtent. 9596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj These are written in *eclasses, which must be big enough to hold 3 9606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Ints. The number written, between 1 and 3, is returned. The 9616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses are presented in order, and any duplicates are removed. 9626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj*/ 9636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 9656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjInt vexGuestExtents_to_eclasses ( /*OUT*/Int* eclasses, 966518850bf0da07ed3e2244e307268ae0fd80e93a8florian const VexGuestExtents* vge ) 9676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 968518850bf0da07ed3e2244e307268ae0fd80e93a8florian 9696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# define SWAP(_lv1,_lv2) \ 9706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj do { Int t = _lv1; _lv1 = _lv2; _lv2 = t; } while (0) 9716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, j, n_ec, r; 9736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(vge->n_used >= 1 && vge->n_used <= 3); 9756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_ec = 0; 9776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < vge->n_used; i++) { 978ddd61ff058f02059064e083a8accaefed23d5548florian r = range_to_eclass( vge->base[i], vge->len[i] ); 9796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (r == ECLASS_MISC) 9806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj goto bad; 9816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* only add if we haven't already seen it */ 9826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < n_ec; j++) 9836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[j] == r) 9846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj break; 9856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (j == n_ec) 9866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses[n_ec++] = r; 9876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 9886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 1) 9906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 1; 9916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 2) { 9936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* sort */ 9946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[1]) 9956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[1]); 9966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 2; 9976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 9986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 3) { 10006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* sort */ 10016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[2]) 10026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[2]); 10036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[1]) 10046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[1]); 10056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[1] > eclasses[2]) 10066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[1], eclasses[2]); 10076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 3; 10086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* NOTREACHED */ 10116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(0); 10126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bad: 10146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses[0] = ECLASS_MISC; 10156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 1; 10166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# undef SWAP 10186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 10196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Add tteno to the set of entries listed for equivalence class ec in 10226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj this sector. Returns used location in eclass array. */ 10236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 10256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjUInt addEClassNo ( /*MOD*/Sector* sec, Int ec, UShort tteno ) 10266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 10276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int old_sz, new_sz, i, r; 10286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort *old_ar, *new_ar; 10296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_N); 10316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno < N_TTES_PER_SECTOR); 10326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10333a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("ec %d gets %d\n", ec, (Int)tteno); 10346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[ec] >= sec->ec2tte_size[ec]) { 10366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_used[ec] == sec->ec2tte_size[ec]); 10386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj old_sz = sec->ec2tte_size[ec]; 10406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj old_ar = sec->ec2tte[ec]; 10416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj new_sz = old_sz==0 ? 8 : old_sz<64 ? 2*old_sz : (3*old_sz)/2; 1042291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj new_ar = ttaux_malloc("transtab.aECN.1", 1043291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj new_sz * sizeof(UShort)); 10446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < old_sz; i++) 10456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj new_ar[i] = old_ar[i]; 10466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (old_ar) 1047291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free(old_ar); 10486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte_size[ec] = new_sz; 10496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec] = new_ar; 10506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10513a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("expand ec %d to %d\n", ec, new_sz); 10526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Common case */ 10556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj r = sec->ec2tte_used[ec]++; 10566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(r >= 0 && r < sec->ec2tte_size[ec]); 10576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec][r] = tteno; 10586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return (UInt)r; 10596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 10606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* 'vge' is being added to 'sec' at TT entry 'tteno'. Add appropriate 10636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclass entries to 'sec'. */ 10646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 10666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjvoid upd_eclasses_after_add ( /*MOD*/Sector* sec, Int tteno ) 10676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 10686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, r, eclasses[3]; 10696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 10706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR); 10716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 10736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj r = vexGuestExtents_to_eclasses( eclasses, &tte->vge ); 10746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(r >= 1 && r <= 3); 10766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->n_tte2ec = r; 10776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < r; i++) { 10796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->tte2ec_ec[i] = eclasses[i]; 10806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->tte2ec_ix[i] = addEClassNo( sec, eclasses[i], (UShort)tteno ); 10816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 10836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Check the eclass info in 'sec' to ensure it is consistent. Returns 10866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj True if OK, False if something's not right. Expensive. */ 10876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1088518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool sanity_check_eclasses_in_sector ( const Sector* sec ) 10896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 10906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# define BAD(_str) do { whassup = (_str); goto bad; } while (0) 10916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10926bd9dc18c043927c1196caba20a327238a179c42florian const HChar* whassup = NULL; 10936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, j, k, n, ec_num, ec_idx; 10946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 10956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort tteno; 10966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ULong* tce; 10976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Basic checks on this sector */ 10996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tt_n_inuse < 0 || sec->tt_n_inuse > N_TTES_PER_SECTOR_USABLE) 11006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("invalid sec->tt_n_inuse"); 11016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tce = sec->tc_next; 11026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tce < &sec->tc[0] || tce > &sec->tc[tc_sector_szQ]) 11036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("sec->tc_next points outside tc"); 11046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* For each eclass ... */ 11066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 11076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] == 0 && sec->ec2tte[i] != NULL) 11086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte_size/ec2tte mismatch(1)"); 11096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] != 0 && sec->ec2tte[i] == NULL) 11106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte_size/ec2tte mismatch(2)"); 11116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[i] < 0 11126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj || sec->ec2tte_used[i] > sec->ec2tte_size[i]) 11136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("implausible ec2tte_used"); 11146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[i] == 0) 11156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* For each tt reference in each eclass .. ensure the reference 11186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj is to a valid tt entry, and that the entry's address ranges 11196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj really include this eclass. */ 11206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < sec->ec2tte_used[i]; j++) { 11226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tteno = sec->ec2tte[i][j]; 11236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno == EC2TTE_DELETED) 11246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno >= N_TTES_PER_SECTOR) 11266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("implausible tteno"); 11276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 11286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != InUse) 11296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tteno points to non-inuse tte"); 11306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3) 11316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_tte2ec out of range"); 11326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Exactly least one of tte->eclasses[0 .. tte->n_eclasses-1] 11336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj must equal i. Inspect tte's eclass info. */ 11346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n = 0; 11356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (k = 0; k < tte->n_tte2ec; k++) { 11366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (k < tte->n_tte2ec-1 11376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj && tte->tte2ec_ec[k] >= tte->tte2ec_ec[k+1]) 11386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ec[..] out of order"); 11396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = tte->tte2ec_ec[k]; 11406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num < 0 || ec_num >= ECLASS_N) 11416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ec[..] out of range"); 11426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num != i) 11436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[k]; 11456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[i]) 11466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ix[..] out of range"); 11476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx == j) 11486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n++; 11496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n != 1) 11516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tteno does not point back at eclass"); 11526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* That establishes that for each forward pointer from TTEntrys 11566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj there is a corresponding backward pointer from the eclass[] 11576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj arrays. However, it doesn't rule out the possibility of other, 11586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bogus pointers in the eclass[] arrays. So do those similarly: 11596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj scan through them and check the TTEntryies they point at point 11606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj back. */ 11616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR_USABLE; i++) { 11636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[i]; 11656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status == Empty || tte->status == Deleted) { 11666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec != 0) 11676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_eclasses nonzero for unused tte"); 11686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 11726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3) 11746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_eclasses out of range(2)"); 11756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < tte->n_tte2ec; j++) { 11776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = tte->tte2ec_ec[j]; 11786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num < 0 || ec_num >= ECLASS_N) 11796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->eclass[..] out of range"); 11806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[j]; 11816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[ec_num]) 11826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->ec_idx[..] out of range(2)"); 11836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte[ec_num][ec_idx] != i) 11846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte does not point back to tte"); 11856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return True; 11896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bad: 11916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (whassup) 11926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(0, "transtab", "eclass sanity fail: %s\n", whassup); 11936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# if 0 11956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("eclass = %d\n", i); 11966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("tteno = %d\n", (Int)tteno); 11976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj switch (tte->status) { 11986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case InUse: VG_(printf)("InUse\n"); break; 11996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case Deleted: VG_(printf)("Deleted\n"); break; 12006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case Empty: VG_(printf)("Empty\n"); break; 12016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != Empty) { 12036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (k = 0; k < tte->vge.n_used; k++) 1204ddd61ff058f02059064e083a8accaefed23d5548florian VG_(printf)("0x%lx %u\n", tte->vge.base[k], (UInt)tte->vge.len[k]); 12056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# endif 12076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return False; 12096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# undef BAD 12116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 12126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Sanity check absolutely everything. True == check passed. */ 12156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12165f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* forwards */ 12170ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void ); 12180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 12195d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardjstatic Bool sanity_check_sector_search_order ( void ) 12205d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj{ 12215d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj Int i, j, nListed; 12225d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* assert the array is the right size */ 12238e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(MAX_N_SECTORS == (sizeof(sector_search_order) 12248e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe / sizeof(sector_search_order[0]))); 12255d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Check it's of the form valid_sector_numbers ++ [-1, -1, ..] */ 12268e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 12278e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe if (sector_search_order[i] < 0 || sector_search_order[i] >= n_sectors) 12285d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 12295d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12305d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj nListed = i; 12318e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (/* */; i < n_sectors; i++) { 12325d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[i] != -1) 12335d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 12345d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12358e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe if (i != n_sectors) 12365d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 12375d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Check each sector number only appears once */ 12388e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 12395d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[i] == -1) 12405d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj continue; 12418e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (j = i+1; j < n_sectors; j++) { 12425d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[j] == sector_search_order[i]) 12435d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 12445d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12455d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12465d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Check that the number of listed sectors equals the number 12475d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj in use, by counting nListed back down. */ 12488e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 12495d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sectors[i].tc != NULL) 12505d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj nListed--; 12515d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12525d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (nListed != 0) 12535d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 12545d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return True; 12555d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj} 12565d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 12576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_all_sectors ( void ) 12586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 12596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int sno; 12606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane; 12616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 12628e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 12633a5322057616d0da214b9e0f897866e203c03e40philippe Int i; 12643a5322057616d0da214b9e0f897866e203c03e40philippe Int nr_not_dead_hx = 0; 12653a5322057616d0da214b9e0f897866e203c03e40philippe Int szhxa; 12666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 12676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 12686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 12696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sane = sanity_check_eclasses_in_sector( sec ); 12706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (!sane) 12716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return False; 12723a5322057616d0da214b9e0f897866e203c03e40philippe szhxa = VG_(sizeXA)(sec->host_extents); 12733a5322057616d0da214b9e0f897866e203c03e40philippe for (i = 0; i < szhxa; i++) { 12743a5322057616d0da214b9e0f897866e203c03e40philippe const HostExtent* hx = VG_(indexXA)(sec->host_extents, i); 12753a5322057616d0da214b9e0f897866e203c03e40philippe if (!HostExtent__is_dead (hx, sec)) 12763a5322057616d0da214b9e0f897866e203c03e40philippe nr_not_dead_hx++; 12773a5322057616d0da214b9e0f897866e203c03e40philippe } 12783a5322057616d0da214b9e0f897866e203c03e40philippe if (nr_not_dead_hx != sec->tt_n_inuse) { 12793a5322057616d0da214b9e0f897866e203c03e40philippe VG_(debugLog)(0, "transtab", 12803a5322057616d0da214b9e0f897866e203c03e40philippe "nr_not_dead_hx %d sanity fail (expected == in use %d)\n", 12813a5322057616d0da214b9e0f897866e203c03e40philippe nr_not_dead_hx, sec->tt_n_inuse); 12823a5322057616d0da214b9e0f897866e203c03e40philippe return False; 12833a5322057616d0da214b9e0f897866e203c03e40philippe } 12846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12853a5322057616d0da214b9e0f897866e203c03e40philippe 12865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if ( !sanity_check_redir_tt_tc() ) 12875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj return False; 12885d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if ( !sanity_check_sector_search_order() ) 12895d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 12906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return True; 12916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 12926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1293fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 12945d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 1295fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/ 12966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Add/find translations ---*/ 1297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/ 1298fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1299518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UInt vge_osize ( const VexGuestExtents* vge ) 1300c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{ 1301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt i, n = 0; 1302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < vge->n_used; i++) 1303fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n += (UInt)vge->len[i]; 1304fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return n; 1305c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj} 1306c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 1307fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Bool isValidSector ( Int sector ) 13086c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 13098e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe if (sector < 0 || sector >= n_sectors) 1310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1311fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 13126c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1313de4a1d01951937632098a6cda45859afa587a06fsewardj 1314ddd61ff058f02059064e083a8accaefed23d5548florianstatic inline UInt HASH_TT ( Addr key ) 1315de4a1d01951937632098a6cda45859afa587a06fsewardj{ 1316ddd61ff058f02059064e083a8accaefed23d5548florian UInt kHi = sizeof(Addr) == 4 ? 0 : (key >> 32); 1317fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt kLo = (UInt)key; 13186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt k32 = kHi ^ kLo; 13196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt ror = 7; 13206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ror > 0) 13216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj k32 = (k32 >> ror) | (k32 << (32-ror)); 13226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return k32 % N_TTES_PER_SECTOR; 1323de4a1d01951937632098a6cda45859afa587a06fsewardj} 1324de4a1d01951937632098a6cda45859afa587a06fsewardj 1325ddd61ff058f02059064e083a8accaefed23d5548florianstatic void setFastCacheEntry ( Addr key, ULong* tcptr ) 1326de4a1d01951937632098a6cda45859afa587a06fsewardj{ 13273387dda4479102751d544c176a7bfc24f3766669sewardj UInt cno = (UInt)VG_TT_FAST_HASH(key); 1328ddd61ff058f02059064e083a8accaefed23d5548florian VG_(tt_fast)[cno].guest = key; 13295f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[cno].host = (Addr)tcptr; 1330fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_updates++; 13315f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* This shouldn't fail. It should be assured by m_translate 13325f76de086a6d643db51e50a4e623df7dfc9b6161sewardj which should reject any attempt to make translation of code 13335f76de086a6d643db51e50a4e623df7dfc9b6161sewardj starting at TRANSTAB_BOGUS_GUEST_ADDR. */ 13345f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_(tt_fast)[cno].guest != TRANSTAB_BOGUS_GUEST_ADDR); 13356c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1336de4a1d01951937632098a6cda45859afa587a06fsewardj 1337291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Invalidate the fast cache VG_(tt_fast). */ 13385f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastCache ( void ) 13395f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{ 13405f76de086a6d643db51e50a4e623df7dfc9b6161sewardj UInt j; 13415f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* This loop is popular enough to make it worth unrolling a 13425f76de086a6d643db51e50a4e623df7dfc9b6161sewardj bit, at least on ppc32. */ 13435f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0); 13445f76de086a6d643db51e50a4e623df7dfc9b6161sewardj for (j = 0; j < VG_TT_FAST_SIZE; j += 4) { 13455f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+0].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13465f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+1].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13475f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+2].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13485f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+3].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13495f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 13505f76de086a6d643db51e50a4e623df7dfc9b6161sewardj 13515f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(j == VG_TT_FAST_SIZE); 1352fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_flushes++; 13536c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1354de4a1d01951937632098a6cda45859afa587a06fsewardj 1355fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void initialiseSector ( Int sno ) 13566c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1357291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int i; 1358291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj SysRes sres; 13596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 1360fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(isValidSector(sno)); 1361fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 13625d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj { Bool sane = sanity_check_sector_search_order(); 13635d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj vg_assert(sane); 13645d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 13656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 13666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 13676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) { 13686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1369fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Sector has never been used before. Need to allocate tt and 1370fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tc. */ 13716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt == NULL); 13726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tc_next == NULL); 13736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt_n_inuse == 0); 13746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 13756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_size[i] == 0); 13766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_used[i] == 0); 13776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[i] == NULL); 13786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 1379291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec->host_extents == NULL); 138045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 13815e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1) 1382059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj VG_(dmsg)("transtab: " "allocate sector %d\n", sno); 138345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 138445f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ ); 1385cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 138645f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(out_of_memory_NORETURN)("initialiseSector(TC)", 138745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 8 * tc_sector_szQ ); 138845f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*NOTREACHED*/ 138945f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 139044bd4465581ff28cef83bb39e684a489297d7b71florian sec->tc = (ULong*)(Addr)sr_Res(sres); 139145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 139245f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_mmap_anon_float_valgrind) 139345f4e7c91119c7d01a59f5e827c67841632c9314sewardj ( N_TTES_PER_SECTOR * sizeof(TTEntry) ); 1394cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 139545f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(out_of_memory_NORETURN)("initialiseSector(TT)", 139645f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_TTES_PER_SECTOR * sizeof(TTEntry) ); 139745f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*NOTREACHED*/ 139845f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 139944bd4465581ff28cef83bb39e684a489297d7b71florian sec->tt = (TTEntry*)(Addr)sr_Res(sres); 14006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 14016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 14026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].status = Empty; 14036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].n_tte2ec = 0; 14046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 140545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1406291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Set up the host_extents array. */ 1407291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sec->host_extents 1408291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = VG_(newXA)(ttaux_malloc, "transtab.initialiseSector(host_extents)", 1409291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free, 1410291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sizeof(HostExtent)); 1411291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 14125d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Add an entry in the sector_search_order */ 14138e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 14145d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[i] == -1) 14155d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 14165d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 14178e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(i >= 0 && i < n_sectors); 14185d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i] = sno; 14195d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 1420fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 1421738856f99eea33d86ce91dcb1d6cd5b151e307casewardj VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d\n", sno); 14226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1423fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } else { 14246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 14256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Sector has been used before. Dump the old contents. */ 14265e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1) 14271bb648db3172e70b73a8ca3a3f3c12ffc1dcd263sewardj VG_(dmsg)("transtab: " "recycle sector %d\n", sno); 14285e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe n_sectors_recycled++; 1429059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj 14306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt != NULL); 14316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tc_next != NULL); 14326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_dump_count += sec->tt_n_inuse; 14336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1434597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host = VexArch_INVALID; 1435597314210494248b4fbefd45525a748439629218sewardj VexArchInfo archinfo_host; 1436597314210494248b4fbefd45525a748439629218sewardj VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host)); 1437597314210494248b4fbefd45525a748439629218sewardj VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host ); 1438597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host = archinfo_host.endness; 1439291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 14406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Visit each just-about-to-be-abandoned translation. */ 14413a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("QQQ unlink-entire-sector: %d START\n", 14423a5322057616d0da214b9e0f897866e203c03e40philippe sno); 1443fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 14446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tt[i].status == InUse) { 14456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt[i].n_tte2ec >= 1); 14466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt[i].n_tte2ec <= 3); 14476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_dump_osize += vge_osize(&sec->tt[i].vge); 14483786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj /* Tell the tool too. */ 14490b9d74abd0a663b530d290b2b788ddeda46e5400sewardj if (VG_(needs).superblock_discards) { 14500b9d74abd0a663b530d290b2b788ddeda46e5400sewardj VG_TDICT_CALL( tool_discard_superblock_info, 14514ba057cce1d81a949f5a899b5abb99e90a731bccsewardj sec->tt[i].entry, 14526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].vge ); 14533786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj } 1454597314210494248b4fbefd45525a748439629218sewardj unchain_in_preparation_for_deletion(arch_host, 1455597314210494248b4fbefd45525a748439629218sewardj endness_host, sno, i); 14566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 14576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt[i].n_tte2ec == 0); 14586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 14596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].status = Empty; 14606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt[i].n_tte2ec = 0; 14616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 14623a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("QQQ unlink-entire-sector: %d END\n", 14633a5322057616d0da214b9e0f897866e203c03e40philippe sno); 14646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 14656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Free up the eclass structures. */ 14666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 14676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] == 0) { 14686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_used[i] == 0); 14696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[i] == NULL); 14706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 14716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[i] != NULL); 1472291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free(sec->ec2tte[i]); 14736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[i] = NULL; 14746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte_size[i] = 0; 14756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte_used[i] = 0; 1476fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 1477fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 14786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1479291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Empty out the host extents array. */ 1480291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec->host_extents != NULL); 1481291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(dropTailXA)(sec->host_extents, VG_(sizeXA)(sec->host_extents)); 1482291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(VG_(sizeXA)(sec->host_extents) == 0); 1483291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 14845d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Sanity check: ensure it is already in 14855d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[]. */ 14868e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 14875d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[i] == sno) 14885d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 14895d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 14908e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(i >= 0 && i < n_sectors); 14915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 1492fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 1493738856f99eea33d86ce91dcb1d6cd5b151e307casewardj VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d\n", sno); 14946c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 14954ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 14966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tc_next = sec->tc; 14976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt_n_inuse = 0; 1498fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1499fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 15005d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 15015d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj { Bool sane = sanity_check_sector_search_order(); 15025d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj vg_assert(sane); 15035d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 15046c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1505de4a1d01951937632098a6cda45859afa587a06fsewardj 1506de4a1d01951937632098a6cda45859afa587a06fsewardj 1507fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC. The translation is temporarily 1508fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj in code[0 .. code_len-1]. 1509de4a1d01951937632098a6cda45859afa587a06fsewardj 1510fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj pre: youngest_sector points to a valid (although possibly full) 1511fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. 1512fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 1513518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid VG_(add_to_transtab)( const VexGuestExtents* vge, 1514ddd61ff058f02059064e083a8accaefed23d5548florian Addr entry, 151544bd4465581ff28cef83bb39e684a489297d7b71florian Addr code, 151626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj UInt code_len, 1517291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool is_self_checking, 1518291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int offs_profInc, 1519597314210494248b4fbefd45525a748439629218sewardj UInt n_guest_instrs ) 152022854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{ 1521fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int tcAvailQ, reqdQ, y, i; 15225f76de086a6d643db51e50a4e623df7dfc9b6161sewardj ULong *tcptr, *tcptr2; 1523fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UChar* srcP; 1524fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UChar* dstP; 1525fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1526663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 1527fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(vge->n_used >= 1 && vge->n_used <= 3); 1528e808930793aeddc4cfd3e7a94b665913bec2566csewardj 1529e808930793aeddc4cfd3e7a94b665913bec2566csewardj /* 60000: should agree with N_TMPBUF in m_translate.c. */ 1530e808930793aeddc4cfd3e7a94b665913bec2566csewardj vg_assert(code_len > 0 && code_len < 60000); 1531fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1532b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj /* Generally stay sane */ 1533b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj vg_assert(n_guest_instrs < 200); /* it can be zero, tho */ 1534b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj 15353a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 1536ddd61ff058f02059064e083a8accaefed23d5548florian VG_(printf)("add_to_transtab(entry = 0x%lx, len = %u) ...\n", 1537fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj entry, code_len); 1538fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1539fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_count++; 1540fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_tsize += code_len; 1541fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_osize += vge_osize(vge); 154226412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj if (is_self_checking) 154326412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj n_in_sc_count++; 1544fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1545fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj y = youngest_sector; 1546fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(isValidSector(y)); 1547fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1548fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[y].tc == NULL) 1549fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj initialiseSector(y); 1550fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1551fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Try putting the translation in this sector. */ 15525f76de086a6d643db51e50a4e623df7dfc9b6161sewardj reqdQ = (code_len + 7) >> 3; 1553fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1554fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Will it fit in tc? */ 1555fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tcAvailQ = ((ULong*)(§ors[y].tc[tc_sector_szQ])) 1556fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - ((ULong*)(sectors[y].tc_next)); 1557fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= 0); 1558fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ <= tc_sector_szQ); 1559fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1560fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (tcAvailQ < reqdQ 1561fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR_USABLE) { 1562fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* No. So move on to the next sector. Either it's never been 1563fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj used before, in which case it will get its tt/tc allocated 1564fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj now, or it has been used before, in which case it is set to be 1565fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj empty, hence throwing out the oldest sector. */ 1566a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj vg_assert(tc_sector_szQ > 0); 1567059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj Int tt_loading_pct = (100 * sectors[y].tt_n_inuse) 1568059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj / N_TTES_PER_SECTOR; 1569059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj Int tc_loading_pct = (100 * (tc_sector_szQ - tcAvailQ)) 1570059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj / tc_sector_szQ; 15715e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1) { 1572059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj VG_(dmsg)("transtab: " 15731bb648db3172e70b73a8ca3a3f3c12ffc1dcd263sewardj "declare sector %d full " 15745e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe "(TT loading %2d%%, TC loading %2d%%, avg tce size %d)\n", 15755e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe y, tt_loading_pct, tc_loading_pct, 15765e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe 8 * (tc_sector_szQ - tcAvailQ)/sectors[y].tt_n_inuse); 1577059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj } 1578fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector++; 15798e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe if (youngest_sector >= n_sectors) 1580fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector = 0; 1581fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj y = youngest_sector; 1582fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj initialiseSector(y); 1583fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 158422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 1585fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Be sure ... */ 1586fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tcAvailQ = ((ULong*)(§ors[y].tc[tc_sector_szQ])) 1587fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - ((ULong*)(sectors[y].tc_next)); 1588fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= 0); 1589fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ <= tc_sector_szQ); 1590fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= reqdQ); 1591fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR_USABLE); 1592fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[y].tt_n_inuse >= 0); 1593fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Copy into tc. */ 15955f76de086a6d643db51e50a4e623df7dfc9b6161sewardj tcptr = sectors[y].tc_next; 15965f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr >= §ors[y].tc[0]); 15975f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr <= §ors[y].tc[tc_sector_szQ]); 1598fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 15995f76de086a6d643db51e50a4e623df7dfc9b6161sewardj dstP = (UChar*)tcptr; 1600fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj srcP = (UChar*)code; 1601291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(memcpy)(dstP, srcP, code_len); 1602fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tc_next += reqdQ; 1603fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt_n_inuse++; 1604fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1605fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* more paranoia */ 16065f76de086a6d643db51e50a4e623df7dfc9b6161sewardj tcptr2 = sectors[y].tc_next; 16075f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr2 >= §ors[y].tc[0]); 16085f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr2 <= §ors[y].tc[tc_sector_szQ]); 1609fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1610fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find an empty tt slot, and use it. There must be such a slot 1611fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj since tt is never allowed to get completely full. */ 1612fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i = HASH_TT(entry); 1613fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(i >= 0 && i < N_TTES_PER_SECTOR); 161422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj while (True) { 1615fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[y].tt[i].status == Empty 1616fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj || sectors[y].tt[i].status == Deleted) 1617fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 1618fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i++; 1619fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (i >= N_TTES_PER_SECTOR) 1620fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj i = 0; 162122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj } 1622fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1623291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry__init(§ors[y].tt[i]); 1624fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].status = InUse; 16255f76de086a6d643db51e50a4e623df7dfc9b6161sewardj sectors[y].tt[i].tcptr = tcptr; 1626fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].count = 0; 1627b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj sectors[y].tt[i].weight = n_guest_instrs == 0 ? 1 : n_guest_instrs; 1628fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].vge = *vge; 1629fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt[i].entry = entry; 1630fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1631291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Patch in the profile counter location, if necessary. */ 1632291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (offs_profInc != -1) { 1633291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(offs_profInc >= 0 && offs_profInc < code_len); 1634597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host = VexArch_INVALID; 1635597314210494248b4fbefd45525a748439629218sewardj VexArchInfo archinfo_host; 1636597314210494248b4fbefd45525a748439629218sewardj VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host)); 1637597314210494248b4fbefd45525a748439629218sewardj VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host ); 1638597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host = archinfo_host.endness; 1639291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexInvalRange vir 1640597314210494248b4fbefd45525a748439629218sewardj = LibVEX_PatchProfInc( arch_host, endness_host, 1641291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj dstP + offs_profInc, 1642291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj §ors[y].tt[i].count ); 1643291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( (void*)vir.start, vir.len ); 1644291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 1645291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 1646291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( dstP, code_len ); 1647291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 1648291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Add this entry to the host_extents map, checking that we're 1649291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj adding in order. */ 1650291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj { HostExtent hx; 1651291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj hx.start = (UChar*)tcptr; 1652291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj hx.len = code_len; 1653291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj hx.tteNo = i; 1654291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(hx.len > 0); /* bsearch fails w/ zero length entries */ 1655291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* hx_array = sectors[y].host_extents; 1656291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(hx_array); 1657291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Word n = VG_(sizeXA)(hx_array); 1658291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (n > 0) { 1659291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent* hx_prev = (HostExtent*)VG_(indexXA)(hx_array, n-1); 1660291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(hx_prev->start + hx_prev->len <= hx.start); 1661291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 1662291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(hx_array, &hx); 16633a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 16643a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf)("... hx.start 0x%p hx.len %u sector %d ttslot %d\n", 16653a5322057616d0da214b9e0f897866e203c03e40philippe hx.start, hx.len, y, i); 1666291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 1667291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 16686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Update the fast-cache. */ 1669291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj setFastCacheEntry( entry, tcptr ); 16706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 16716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Note the eclass numbers for this translation. */ 16726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj upd_eclasses_after_add( §ors[y], i ); 167322854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj} 167422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 1675fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1676fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address. If 1677fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj requested, a successful search can also cause the fast-caches to be 1678fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj updated. 1679fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 168044bd4465581ff28cef83bb39e684a489297d7b71florianBool VG_(search_transtab) ( /*OUT*/Addr* res_hcode, 1681291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /*OUT*/UInt* res_sNo, 1682291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /*OUT*/UInt* res_tteNo, 1683ddd61ff058f02059064e083a8accaefed23d5548florian Addr guest_addr, 1684fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Bool upd_cache ) 16856c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1686fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int i, j, k, kstart, sno; 1687663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 1688663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 1689fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find the initial probe point just once. It will be the same in 1690fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj all sectors and avoids multiple expensive % operations. */ 1691fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_full_lookups++; 1692fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = -1; 1693fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj kstart = HASH_TT(guest_addr); 1694fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(kstart >= 0 && kstart < N_TTES_PER_SECTOR); 1695fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 16965d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Search in all the sectors,using sector_search_order[] as a 16975d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj heuristic guide as to what order to visit the sectors. */ 16988e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 1699fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 17005d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sno = sector_search_order[i]; 17015d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (UNLIKELY(sno == -1)) 17025d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; /* run out of sectors to search */ 1703fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1704fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = kstart; 1705fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (j = 0; j < N_TTES_PER_SECTOR; j++) { 1706fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_lookup_probes++; 1707fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[k].status == InUse 1708fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj && sectors[sno].tt[k].entry == guest_addr) { 1709fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* found it */ 1710fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (upd_cache) 1711fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj setFastCacheEntry( 1712291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj guest_addr, sectors[sno].tt[k].tcptr ); 1713291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (res_hcode) 171444bd4465581ff28cef83bb39e684a489297d7b71florian *res_hcode = (Addr)sectors[sno].tt[k].tcptr; 1715291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (res_sNo) 1716291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *res_sNo = sno; 1717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (res_tteNo) 1718291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *res_tteNo = k; 17195d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* pull this one one step closer to the front. For large 17205d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj apps this more or less halves the number of required 17215d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj probes. */ 17225d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (i > 0) { 17235d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj Int tmp = sector_search_order[i-1]; 17245d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i-1] = sector_search_order[i]; 17255d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i] = tmp; 17265d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 1727fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1728fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 1729fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[k].status == Empty) 1730fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; /* not found in this sector */ 1731fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k++; 1732fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (k == N_TTES_PER_SECTOR) 1733fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = 0; 17346c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 1735fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1736fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* If we fall off the end, all entries are InUse and not 1737fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj matching, or Deleted. In any case we did not find it in this 1738fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. */ 17396c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 1740fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1741fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Not found in any sector. */ 1742fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 17436c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1744de4a1d01951937632098a6cda45859afa587a06fsewardj 1745de4a1d01951937632098a6cda45859afa587a06fsewardj 17466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 17476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Delete translations. ---*/ 17486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 17496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 17500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* forward */ 1751ddd61ff058f02059064e083a8accaefed23d5548florianstatic void unredir_discard_translations( Addr, ULong ); 17520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 17536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Stuff for deleting translations which intersect with a given 17546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range. Unfortunately, to make this run at a reasonable 17556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj speed, it is complex. */ 1756fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1757fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline 1758ddd61ff058f02059064e083a8accaefed23d5548florianBool overlap1 ( Addr s1, ULong r1, Addr s2, ULong r2 ) 17596c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1760ddd61ff058f02059064e083a8accaefed23d5548florian Addr e1 = s1 + r1 - 1; 1761ddd61ff058f02059064e083a8accaefed23d5548florian Addr e2 = s2 + r2 - 1; 1762fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (e1 < s2 || e2 < s1) 1763fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1764fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 17656c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1766de4a1d01951937632098a6cda45859afa587a06fsewardj 1767fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline 1768ddd61ff058f02059064e083a8accaefed23d5548florianBool overlaps ( Addr start, ULong range, const VexGuestExtents* vge ) 17696c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1770ddd61ff058f02059064e083a8accaefed23d5548florian if (overlap1(start, range, vge->base[0], vge->len[0])) 1771fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1772fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (vge->n_used < 2) 1773fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1774ddd61ff058f02059064e083a8accaefed23d5548florian if (overlap1(start, range, vge->base[1], vge->len[1])) 1775fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1776fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (vge->n_used < 3) 1777fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1778ddd61ff058f02059064e083a8accaefed23d5548florian if (overlap1(start, range, vge->base[2], vge->len[2])) 1779fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1780fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 17816c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1782de4a1d01951937632098a6cda45859afa587a06fsewardj 1783de4a1d01951937632098a6cda45859afa587a06fsewardj 17846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete a tt entry, and update all the eclass data accordingly. */ 17856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1786291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void delete_tte ( /*MOD*/Sector* sec, UInt secNo, Int tteno, 1787597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host, VexEndness endness_host ) 17886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 17896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i, ec_num, ec_idx; 17906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 17916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1792291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* sec and secNo are mutually redundant; cross-check. */ 1793291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec == §ors[secNo]); 1794291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 17956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR); 17966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 17976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 17986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->n_tte2ec >= 1 && tte->n_tte2ec <= 3); 17996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1800291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Unchain .. */ 1801597314210494248b4fbefd45525a748439629218sewardj unchain_in_preparation_for_deletion(arch_host, endness_host, secNo, tteno); 1802291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 18036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Deal with the ec-to-tte links first. */ 18046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < tte->n_tte2ec; i++) { 18056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = (Int)tte->tte2ec_ec[i]; 18066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[i]; 18076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_num >= 0 && ec_num < ECLASS_N); 18086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_idx >= 0); 18096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_idx < sec->ec2tte_used[ec_num]); 18106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Assert that the two links point at each other. */ 18116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte[ec_num][ec_idx] == (UShort)tteno); 18126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* "delete" the pointer back to here. */ 18136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec_num][ec_idx] = EC2TTE_DELETED; 18146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Now fix up this TTEntry. */ 18176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->status = Deleted; 18186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->n_tte2ec = 0; 18196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Stats .. */ 18216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt_n_inuse--; 18226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_disc_count++; 18236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_disc_osize += vge_osize(&tte->vge); 18246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Tell the tool too. */ 18260b9d74abd0a663b530d290b2b788ddeda46e5400sewardj if (VG_(needs).superblock_discards) { 18270b9d74abd0a663b530d290b2b788ddeda46e5400sewardj VG_TDICT_CALL( tool_discard_superblock_info, 18284ba057cce1d81a949f5a899b5abb99e90a731bccsewardj tte->entry, 18296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->vge ); 18306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 18326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, but 18356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj only consider translations in the specified eclass. */ 18366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 1838291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool delete_translations_in_sector_eclass ( /*MOD*/Sector* sec, UInt secNo, 1839ddd61ff058f02059064e083a8accaefed23d5548florian Addr guest_start, ULong range, 1840291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int ec, 1841597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host, 1842597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host ) 18436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 18446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 18456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort tteno; 18466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeld = False; 18476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 18486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_N); 18506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < sec->ec2tte_used[ec]; i++) { 18526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tteno = sec->ec2tte[ec][i]; 18546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno == EC2TTE_DELETED) { 18556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* already deleted */ 18566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 18576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno < N_TTES_PER_SECTOR); 18606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 18626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 18636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (overlaps( guest_start, range, &tte->vge )) { 18656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeld = True; 1866597314210494248b4fbefd45525a748439629218sewardj delete_tte( sec, secNo, (Int)tteno, arch_host, endness_host ); 18676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return anyDeld; 18726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 18736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, the 18766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj slow way, by inspecting all translations in sec. */ 18776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 1879291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool delete_translations_in_sector ( /*MOD*/Sector* sec, UInt secNo, 1880ddd61ff058f02059064e083a8accaefed23d5548florian Addr guest_start, ULong range, 1881597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host, 1882597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host ) 18836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 18846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 18856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeld = False; 18866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 18886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tt[i].status == InUse 18896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj && overlaps( guest_start, range, &sec->tt[i].vge )) { 18906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeld = True; 1891597314210494248b4fbefd45525a748439629218sewardj delete_tte( sec, secNo, i, arch_host, endness_host ); 18926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 18946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return anyDeld; 18966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 18976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1899ddd61ff058f02059064e083a8accaefed23d5548florianvoid VG_(discard_translations) ( Addr guest_start, ULong range, 19001636d33c13958b9c0e7d3059cdd5005746418eb2florian const HChar* who ) 19016c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 19026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 19036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int sno, ec; 19046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeleted = False; 19056c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 1906663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 1907663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 1908a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj VG_(debugLog)(2, "transtab", 1909ddd61ff058f02059064e083a8accaefed23d5548florian "discard_translations(0x%lx, %llu) req by %s\n", 191045f4e7c91119c7d01a59f5e827c67841632c9314sewardj guest_start, range, who ); 191145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 19126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Pre-deletion sanity check */ 19136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (VG_(clo_sanity_level >= 4)) { 19146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane = sanity_check_all_sectors(); 19156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sane); 19166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (range == 0) 19196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return; 19206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1921597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host = VexArch_INVALID; 1922597314210494248b4fbefd45525a748439629218sewardj VexArchInfo archinfo_host; 1923597314210494248b4fbefd45525a748439629218sewardj VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host)); 1924597314210494248b4fbefd45525a748439629218sewardj VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host ); 1925597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host = archinfo_host.endness; 1926291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 19276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* There are two different ways to do this. 19286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj If the range fits within a single address-range equivalence 19306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class, as will be the case for a cache line sized invalidation, 19316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj then we only have to inspect the set of translations listed in 19326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj that equivalence class, and also in the "sin-bin" equivalence 19336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class ECLASS_MISC. 19346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Otherwise, the invalidation is of a larger range and probably 19366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj results from munmap. In this case it's (probably!) faster just 19376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj to inspect all translations, dump those we don't want, and 19386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj regenerate the equivalence class information (since modifying it 19396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj in-situ is even more expensive). 19406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj */ 19416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* First off, figure out if the range falls within a single class, 19436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj and if so which one. */ 19446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec = ECLASS_MISC; 19466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (range < (1ULL << ECLASS_SHIFT)) 19476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec = range_to_eclass( guest_start, (UInt)range ); 19486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* if ec is ECLASS_MISC then we aren't looking at just a single 19506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class, so use the slow scheme. Else use the fast scheme, 19516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj examining 'ec' and ECLASS_MISC. */ 19526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec != ECLASS_MISC) { 19546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(2, "transtab", 19566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj " FAST, ec = %d\n", ec); 19576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Fast scheme */ 19596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_MISC); 19606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19618e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 19626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 19636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 19646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 19656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector_eclass( 1966291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sec, sno, guest_start, range, ec, 1967597314210494248b4fbefd45525a748439629218sewardj arch_host, endness_host 1968291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 19696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector_eclass( 1970291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sec, sno, guest_start, range, ECLASS_MISC, 1971597314210494248b4fbefd45525a748439629218sewardj arch_host, endness_host 1972291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 19736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 19766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* slow scheme */ 19786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(2, "transtab", 19806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj " SLOW, ec = %d\n", ec); 19816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19828e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 19836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 19846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 19856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 19866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector( 1987597314210494248b4fbefd45525a748439629218sewardj sec, sno, guest_start, range, 1988597314210494248b4fbefd45525a748439629218sewardj arch_host, endness_host 1989597314210494248b4fbefd45525a748439629218sewardj ); 19906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1992de4a1d01951937632098a6cda45859afa587a06fsewardj } 1993de4a1d01951937632098a6cda45859afa587a06fsewardj 1994fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (anyDeleted) 1995fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 19966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* don't forget the no-redir cache */ 19980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_discard_translations( guest_start, range ); 19990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Post-deletion sanity check */ 20016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (VG_(clo_sanity_level >= 4)) { 20026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 20036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 20046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane = sanity_check_all_sectors(); 20056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sane); 20066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* But now, also check the requested address range isn't 20076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj present anywhere. */ 20088e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 20096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 20106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 20116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 20126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 20136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[i]; 20146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != InUse) 20156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 20166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(!overlaps( guest_start, range, &tte->vge )); 20176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 20186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 20196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 2020fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 20216c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 20225f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian/* Whether or not tools may discard translations. */ 20235f1aeb620eb5a3aab662f8b949b031a77a0d14feflorianBool VG_(ok_to_discard_translations) = False; 20245f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian 20255f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian/* This function is exported to tools which can use it to discard 20265f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian translations, provided it is safe to do so. */ 20275f1aeb620eb5a3aab662f8b949b031a77a0d14feflorianvoid VG_(discard_translations_safely) ( Addr start, SizeT len, 20285f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian const HChar* who ) 20295f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian{ 20305f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian vg_assert(VG_(ok_to_discard_translations)); 20315f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian VG_(discard_translations)(start, len, who); 20325f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian} 20336c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 2034fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 20350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*--- AUXILIARY: the unredirected TT/TC ---*/ 20360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/ 20370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* A very simple translation cache which holds a small number of 20390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredirected translations. This is completely independent of the 20400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj main tt/tc structures. When unredir_tc or unredir_tt becomes full, 20410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj both structures are simply dumped and we start over. 20420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Since these translations are unredirected, the search key is (by 20440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj definition) the first address entry in the .vge field. */ 20450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Sized to hold 500 translations of average size 1000 bytes. */ 20470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define UNREDIR_SZB 1000 20490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TT 500 20510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TCQ (N_UNREDIR_TT * UNREDIR_SZB / sizeof(ULong)) 20520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20530ec07f32bbbb209d749b9974408e6f025ad40b31sewardjtypedef 20540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj struct { 20550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj VexGuestExtents vge; 20560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Addr hcode; 20570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Bool inUse; 20580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 20590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj UTCEntry; 20600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* We just allocate forwards in _tc, never deleting. */ 206278c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic ULong *unredir_tc; 206378c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic Int unredir_tc_used = N_UNREDIR_TCQ; 20640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Slots in _tt can come into use and out again (.inUse). 20660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Nevertheless _tt_highwater is maintained so that invalidations 20670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj don't have to scan all the slots when only a few are in use. 20680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj _tt_highwater holds the index of the highest ever allocated 20690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj slot. */ 20700ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic UTCEntry unredir_tt[N_UNREDIR_TT]; 20710ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Int unredir_tt_highwater; 20720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20740ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void init_unredir_tt_tc ( void ) 20750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 20760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 207778c0c09d429c95115e826ef769ecaa6cff2ac338tom if (unredir_tc == NULL) { 2078cda2f0fbda4c4b2644babc830244be8aed95de1dnjn SysRes sres = VG_(am_mmap_anon_float_valgrind) 2079cda2f0fbda4c4b2644babc830244be8aed95de1dnjn ( N_UNREDIR_TT * UNREDIR_SZB ); 2080cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 2081cda2f0fbda4c4b2644babc830244be8aed95de1dnjn VG_(out_of_memory_NORETURN)("init_unredir_tt_tc", 2082cda2f0fbda4c4b2644babc830244be8aed95de1dnjn N_UNREDIR_TT * UNREDIR_SZB); 208378c0c09d429c95115e826ef769ecaa6cff2ac338tom /*NOTREACHED*/ 208478c0c09d429c95115e826ef769ecaa6cff2ac338tom } 208544bd4465581ff28cef83bb39e684a489297d7b71florian unredir_tc = (ULong *)(Addr)sr_Res(sres); 208678c0c09d429c95115e826ef769ecaa6cff2ac338tom } 20870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tc_used = 0; 20880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) 20890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = False; 20900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt_highwater = -1; 20910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 20920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 20930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Do a sanity check; return False on failure. */ 20940ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void ) 20950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 20960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 20970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt_highwater < -1) return False; 20980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt_highwater >= N_UNREDIR_TT) return False; 20990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = unredir_tt_highwater+1; i < N_UNREDIR_TT; i++) 21010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].inUse) 21020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return False; 21030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tc_used < 0) return False; 21050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tc_used > N_UNREDIR_TCQ) return False; 21060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return True; 21080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 21090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Add an UNREDIRECTED translation of vge to TT/TC. The translation 21120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj is temporarily in code[0 .. code_len-1]. 21130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj*/ 2114518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid VG_(add_to_unredir_transtab)( const VexGuestExtents* vge, 2115ddd61ff058f02059064e083a8accaefed23d5548florian Addr entry, 211644bd4465581ff28cef83bb39e684a489297d7b71florian Addr code, 21171dcee097db02f9ef3ba355162c4373d90d0e895cnjn UInt code_len ) 21180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 21190ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i, j, code_szQ; 21200ec07f32bbbb209d749b9974408e6f025ad40b31sewardj HChar *srcP, *dstP; 21210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(sanity_check_redir_tt_tc()); 21230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* This is the whole point: it's not redirected! */ 21250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(entry == vge->base[0]); 21260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* How many unredir_tt slots are needed */ 21280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj code_szQ = (code_len + 7) / 8; 21290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* Look for an empty unredir_tc slot */ 21310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) 21320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (!unredir_tt[i].inUse) 21330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj break; 21340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (i >= N_UNREDIR_TT || code_szQ > (N_UNREDIR_TCQ - unredir_tc_used)) { 21360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* It's full; dump everything we currently have */ 21370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj init_unredir_tt_tc(); 21380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj i = 0; 21390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 21400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used >= 0); 21420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used <= N_UNREDIR_TCQ); 21430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(code_szQ > 0); 21440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(code_szQ + unredir_tc_used <= N_UNREDIR_TCQ); 21450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(i >= 0 && i < N_UNREDIR_TT); 21460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tt[i].inUse == False); 21470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (i > unredir_tt_highwater) 21490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt_highwater = i; 21500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj dstP = (HChar*)&unredir_tc[unredir_tc_used]; 21520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj srcP = (HChar*)code; 21530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (j = 0; j < code_len; j++) 21540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj dstP[j] = srcP[j]; 21550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 2156291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( dstP, code_len ); 2157c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj 21580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = True; 21590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].vge = *vge; 21600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].hcode = (Addr)dstP; 21610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tc_used += code_szQ; 21630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used >= 0); 21640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used <= N_UNREDIR_TCQ); 21650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(&dstP[code_len] <= (HChar*)&unredir_tc[unredir_tc_used]); 21670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 21680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 216944bd4465581ff28cef83bb39e684a489297d7b71florianBool VG_(search_unredir_transtab) ( /*OUT*/Addr* result, 2170ddd61ff058f02059064e083a8accaefed23d5548florian Addr guest_addr ) 21710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 21720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 21730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) { 21740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (!unredir_tt[i].inUse) 21750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj continue; 21760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].vge.base[0] == guest_addr) { 2177ddd61ff058f02059064e083a8accaefed23d5548florian *result = unredir_tt[i].hcode; 21780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return True; 21790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 21800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 21810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return False; 21820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 21830ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 2184ddd61ff058f02059064e083a8accaefed23d5548florianstatic void unredir_discard_translations( Addr guest_start, ULong range ) 21850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 21860ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 21870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(sanity_check_redir_tt_tc()); 21890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i <= unredir_tt_highwater; i++) { 21910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].inUse 21920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj && overlaps( guest_start, range, &unredir_tt[i].vge)) 21930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = False; 21940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 21950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 21960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/ 2199fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation. ---*/ 2200fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2201fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2202fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void ) 22036c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 2204a11ec17946cdbafb336e9121b64961c0633af2e7sewardj Int i, avg_codeszQ; 2205de4a1d01951937632098a6cda45859afa587a06fsewardj 2206663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(!init_done); 2207663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj init_done = True; 2208663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 2209fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Otherwise lots of things go wrong... */ 2210fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sizeof(ULong) == 8); 22115f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache entries really are 2 words long */ 22125f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof(Addr) == sizeof(void*)); 22135f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof(FastCacheEntry) == 2 * sizeof(Addr)); 22145f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache entries are packed back-to-back with no spaces */ 22155f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof( VG_(tt_fast) ) == VG_TT_FAST_SIZE * sizeof(FastCacheEntry)); 22165f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache is aligned as we requested. Not fatal if it 22175f76de086a6d643db51e50a4e623df7dfc9b6161sewardj isn't, but we might as well make sure. */ 22185f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_IS_16_ALIGNED( ((Addr) & VG_(tt_fast)[0]) )); 2219de4a1d01951937632098a6cda45859afa587a06fsewardj 2220fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 2221fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2222fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "TT/TC: VG_(init_tt_tc) " 2223738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "(startup of code management)\n"); 2224fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2225fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Figure out how big each tc area should be. */ 222643b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn avg_codeszQ = (VG_(details).avg_translation_sizeB + 7) / 8; 222743b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn tc_sector_szQ = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ); 2228fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2229fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Ensure the calculated value is not way crazy. */ 2230fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR_USABLE); 22311e0fff690e9c571275e8025eb2dcff7bf29b53afsewardj vg_assert(tc_sector_szQ <= 100 * N_TTES_PER_SECTOR_USABLE); 2232fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 22338e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe n_sectors = VG_(clo_num_transtab_sectors); 22348e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(n_sectors >= MIN_N_SECTORS); 22358e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(n_sectors <= MAX_N_SECTORS); 22368e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe 2237a11ec17946cdbafb336e9121b64961c0633af2e7sewardj /* Initialise the sectors, even the ones we aren't going to use. 2238a11ec17946cdbafb336e9121b64961c0633af2e7sewardj Set all fields to zero. */ 2239fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector = 0; 2240a11ec17946cdbafb336e9121b64961c0633af2e7sewardj for (i = 0; i < MAX_N_SECTORS; i++) 2241a11ec17946cdbafb336e9121b64961c0633af2e7sewardj VG_(memset)(§ors[i], 0, sizeof(sectors[i])); 22424ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 2243a11ec17946cdbafb336e9121b64961c0633af2e7sewardj /* Initialise the sector_search_order hint table, including the 2244a11ec17946cdbafb336e9121b64961c0633af2e7sewardj entries we aren't going to use. */ 2245a11ec17946cdbafb336e9121b64961c0633af2e7sewardj for (i = 0; i < MAX_N_SECTORS; i++) 22465d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i] = -1; 22475d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 2248291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Initialise the fast cache. */ 2249fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 2250fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 22510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* and the unredir tt/tc */ 22520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj init_unredir_tt_tc(); 22530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22548e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe if (VG_(clo_verbosity) > 2 || VG_(clo_stats) 22558e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe || VG_(debugLog_getLevel) () >= 2) { 2256fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2257738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "TT/TC: cache: %d sectors of %d bytes each = %d total\n", 22588e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe n_sectors, 8 * tc_sector_szQ, 22598e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe n_sectors * 8 * tc_sector_szQ ); 2260fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 22618e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe "TT/TC: table: %d tables of %d bytes each = %d total\n", 22628e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe n_sectors, (int)(N_TTES_PER_SECTOR * sizeof(TTEntry)), 22638e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe (int)(n_sectors * N_TTES_PER_SECTOR * sizeof(TTEntry))); 22648e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe VG_(message)(Vg_DebugMsg, 22658e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe "TT/TC: table: %d entries each = %d total entries" 22668e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe " max occupancy %d (%d%%)\n", 22678e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe N_TTES_PER_SECTOR, 22688e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe n_sectors * N_TTES_PER_SECTOR, 22698e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe n_sectors * N_TTES_PER_SECTOR_USABLE, 2270fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj SECTOR_TT_LIMIT_PERCENT ); 2271fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2272de4a1d01951937632098a6cda45859afa587a06fsewardj} 2273de4a1d01951937632098a6cda45859afa587a06fsewardj 22744ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 2275fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2276fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics. ---*/ 2277fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2278fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2279fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong safe_idiv( ULong a, ULong b ) 228092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{ 228192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote return (b == 0 ? 0 : a / b); 228292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote} 228392e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote 2284fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void ) 2285fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 2286fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return n_in_count; 2287fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 2288fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2289fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void ) 229092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{ 229192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 2292738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " tt/tc: %'llu tt lookups requiring %'llu probes\n", 2293fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_full_lookups, n_lookup_probes ); 229492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 2295738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " tt/tc: %'llu fast-cache updates, %'llu flushes\n", 2296fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_updates, n_fast_flushes ); 2297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 229892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 2299a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart " transtab: new %'lld " 23005e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe "(%'llu -> %'llu; ratio %'llu:10) [%'llu scs] " 23015e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe "avg tce size %d\n", 2302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_count, n_in_osize, n_in_tsize, 230326412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj safe_idiv(10*n_in_tsize, n_in_osize), 23045e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe n_in_sc_count, 23055e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe n_in_tsize / n_in_count); 230692e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 23075e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe " transtab: dumped %'llu (%'llu -> ?" "?) " 23085e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe "(sectors recycled %'llu)\n", 23095e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe n_dump_count, n_dump_osize, n_sectors_recycled ); 2310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2311738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " transtab: discarded %'llu (%'llu -> ?" "?)\n", 2312fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_disc_count, n_disc_osize ); 23136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 23143a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) { 23156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 23166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n"); 23176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 23186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)(" %4d", sectors[0].ec2tte_used[i]); 23196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (i % 16 == 15) 23206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n"); 23216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 23226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n\n"); 23236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 232492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote} 2325de4a1d01951937632098a6cda45859afa587a06fsewardj 2326fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2327fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results. ---*/ 2328fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 23294ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 2330518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic ULong score ( const TTEntry* tte ) 2331fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 2332fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return ((ULong)tte->weight) * ((ULong)tte->count); 2333de4a1d01951937632098a6cda45859afa587a06fsewardj} 2334de4a1d01951937632098a6cda45859afa587a06fsewardj 233517c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardjULong VG_(get_SB_profile) ( SBProfEntry tops[], UInt n_tops ) 2336de4a1d01951937632098a6cda45859afa587a06fsewardj{ 2337fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int sno, i, r, s; 23382025cf98a3210c175a90fc77cb599cca1643bd68njn ULong score_total; 2339fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2340fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* First, compute the total weighted count, and find the top N 23412025cf98a3210c175a90fc77cb599cca1643bd68njn ttes. tops contains pointers to the most-used n_tops blocks, in 2342fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj descending order (viz, tops[0] is the highest scorer). */ 23432025cf98a3210c175a90fc77cb599cca1643bd68njn for (i = 0; i < n_tops; i++) { 23442025cf98a3210c175a90fc77cb599cca1643bd68njn tops[i].addr = 0; 23452025cf98a3210c175a90fc77cb599cca1643bd68njn tops[i].score = 0; 23462025cf98a3210c175a90fc77cb599cca1643bd68njn } 2347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_total = 0; 2349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 23508e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 2351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tc == NULL) 235218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj continue; 2353fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 2354fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[i].status != InUse) 2355fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 2356fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_total += score(§ors[sno].tt[i]); 2357fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find the rank for sectors[sno].tt[i]. */ 23582025cf98a3210c175a90fc77cb599cca1643bd68njn r = n_tops-1; 2359fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj while (True) { 2360fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (r == -1) 2361fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 23622025cf98a3210c175a90fc77cb599cca1643bd68njn if (tops[r].addr == 0) { 2363fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r--; 2364fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 2365fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 23662025cf98a3210c175a90fc77cb599cca1643bd68njn if ( score(§ors[sno].tt[i]) > tops[r].score ) { 2367fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r--; 2368fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 2369fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2370fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 2371fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2372fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r++; 23732025cf98a3210c175a90fc77cb599cca1643bd68njn vg_assert(r >= 0 && r <= n_tops); 2374fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This bb should be placed at r, and bbs above it shifted 2375fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj upwards one slot. */ 23762025cf98a3210c175a90fc77cb599cca1643bd68njn if (r < n_tops) { 23772025cf98a3210c175a90fc77cb599cca1643bd68njn for (s = n_tops-1; s > r; s--) 2378fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tops[s] = tops[s-1]; 23792025cf98a3210c175a90fc77cb599cca1643bd68njn tops[r].addr = sectors[sno].tt[i].entry; 23802025cf98a3210c175a90fc77cb599cca1643bd68njn tops[r].score = score( §ors[sno].tt[i] ); 2381fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2382de4a1d01951937632098a6cda45859afa587a06fsewardj } 2383de4a1d01951937632098a6cda45859afa587a06fsewardj } 2384de4a1d01951937632098a6cda45859afa587a06fsewardj 238517c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj /* Now zero out all the counter fields, so that we can make 238617c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj multiple calls here and just get the values since the last call, 238717c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj each time, rather than values accumulated for the whole run. */ 23888e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 238917c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj if (sectors[sno].tc == NULL) 239017c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj continue; 239117c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 239217c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj if (sectors[sno].tt[i].status != InUse) 239317c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj continue; 239417c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj sectors[sno].tt[i].count = 0; 239517c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj } 239617c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj } 239717c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj 23982025cf98a3210c175a90fc77cb599cca1643bd68njn return score_total; 2399c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj} 2400c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 2401de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 24028bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end ---*/ 2403de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 2404