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). */ 60523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic SECno n_sectors = 0; 61de4a1d01951937632098a6cda45859afa587a06fsewardj 62924c852b5883a7b42298dc8c7542116bd9a8a485philippe/* Average size of a transtab code entry. 0 means to use the tool 63924c852b5883a7b42298dc8c7542116bd9a8a485philippe provided default. */ 64924c852b5883a7b42298dc8c7542116bd9a8a485philippeUInt VG_(clo_avg_transtab_entry_size) = 0; 65924c852b5883a7b42298dc8c7542116bd9a8a485philippe 668e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe/*------------------ CONSTANTS ------------------*/ 67bece82eba7ba26398a673def2fa326341c4f8ef7philippe/* Number of entries in hash table of each sector. This needs to be a prime 68bece82eba7ba26398a673def2fa326341c4f8ef7philippe number to work properly, it must be <= 65535 (so that a TTE index 69bece82eba7ba26398a673def2fa326341c4f8ef7philippe fits in a UShort, leaving room for 0xFFFF(EC2TTE_DELETED, HTT_DELETED) 70bece82eba7ba26398a673def2fa326341c4f8ef7philippe to denote 'deleted') and 0xFFFE (HTT_EMPTY) to denote 'Empty' in the 71bece82eba7ba26398a673def2fa326341c4f8ef7philippe hash table. 72bece82eba7ba26398a673def2fa326341c4f8ef7philippe It is strongly recommended not to change this. 736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 65521 is the largest prime <= 65535. */ 74bece82eba7ba26398a673def2fa326341c4f8ef7philippe#define N_HTTES_PER_SECTOR /*10007*/ /*30011*/ /*40009*/ 65521 75bece82eba7ba26398a673def2fa326341c4f8ef7philippe 76bece82eba7ba26398a673def2fa326341c4f8ef7philippe#define EC2TTE_DELETED 0xFFFF /* 16-bit special value */ 77bece82eba7ba26398a673def2fa326341c4f8ef7philippe#define HTT_DELETED EC2TTE_DELETED 78bece82eba7ba26398a673def2fa326341c4f8ef7philippe#define HTT_EMPTY 0XFFFE 79de4a1d01951937632098a6cda45859afa587a06fsewardj 80523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe// HTTno is the Sector->htt hash table index. Must be the same type as TTEno. 81523b5b8ca67d2063afd02342d0138b0dc0ed6706philippetypedef UShort HTTno; 82523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe 83fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to 84fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj specify the maximum allowable loading, after which the sector is 85fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj deemed full. */ 865d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj#define SECTOR_TT_LIMIT_PERCENT 65 87de4a1d01951937632098a6cda45859afa587a06fsewardj 88fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */ 89bece82eba7ba26398a673def2fa326341c4f8ef7philippe#define N_TTES_PER_SECTOR \ 90bece82eba7ba26398a673def2fa326341c4f8ef7philippe ((N_HTTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100) 916c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Equivalence classes for fast address range deletion. There are 1 + 936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 2^ECLASS_WIDTH bins. The highest one, ECLASS_MISC, describes an 946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range which does not fall cleanly within any specific bin. 95d28615ccace5f9c79fca7713c73c19e0767f8f47philippe Note that ECLASS_SHIFT + ECLASS_WIDTH must be < 32. 96d28615ccace5f9c79fca7713c73c19e0767f8f47philippe ECLASS_N must fit in a EclassNo. */ 976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_SHIFT 11 986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_WIDTH 8 996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_MISC (1 << ECLASS_WIDTH) 1006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_N (1 + ECLASS_MISC) 101d28615ccace5f9c79fca7713c73c19e0767f8f47philippeSTATIC_ASSERT(ECLASS_SHIFT + ECLASS_WIDTH < 32); 1026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 103d28615ccace5f9c79fca7713c73c19e0767f8f47philippetypedef UShort EClassNo; 104de4a1d01951937632098a6cda45859afa587a06fsewardj 1056c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/ 106de4a1d01951937632098a6cda45859afa587a06fsewardj 107291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* In edges ("to-me") in the graph created by chaining. */ 108291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 109291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 110523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno from_sNo; /* sector number */ 111523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno from_tteNo; /* TTE number in given sector */ 112d28615ccace5f9c79fca7713c73c19e0767f8f47philippe UInt from_offs: (sizeof(UInt)*8)-1; /* code offset from TCEntry::tcptr 113d28615ccace5f9c79fca7713c73c19e0767f8f47philippe where the patch is */ 114d28615ccace5f9c79fca7713c73c19e0767f8f47philippe Bool to_fastEP:1; /* Is the patch to a fast or slow entry point? */ 115291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 116291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge; 117291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 118291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 119291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Out edges ("from-me") in the graph created by chaining. */ 120291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 121291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 122523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno to_sNo; /* sector number */ 123523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno to_tteNo; /* TTE number in given sector */ 124523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe UInt from_offs; /* code offset in owning translation where patch is */ 125291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 126291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge; 127291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 128291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 129291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_IN_EDGE_ARR 3 130291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 131291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 132d28615ccace5f9c79fca7713c73c19e0767f8f47philippe Bool has_var:1; /* True if var is used (then n_fixed must be 0) */ 133d28615ccace5f9c79fca7713c73c19e0767f8f47philippe UInt n_fixed: (sizeof(UInt)*8)-1; /* 0 .. N_FIXED_IN_EDGE_ARR */ 134d28615ccace5f9c79fca7713c73c19e0767f8f47philippe union { 135d28615ccace5f9c79fca7713c73c19e0767f8f47philippe InEdge fixed[N_FIXED_IN_EDGE_ARR]; /* if !has_var */ 136d28615ccace5f9c79fca7713c73c19e0767f8f47philippe XArray* var; /* XArray* of InEdgeArr */ /* if has_var */ 137d28615ccace5f9c79fca7713c73c19e0767f8f47philippe } edges; 138291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 139291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr; 140291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 141291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_OUT_EDGE_ARR 2 142291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 143291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 144d28615ccace5f9c79fca7713c73c19e0767f8f47philippe Bool has_var:1; /* True if var is used (then n_fixed must be 0) */ 145d28615ccace5f9c79fca7713c73c19e0767f8f47philippe UInt n_fixed: (sizeof(UInt)*8)-1; /* 0 .. N_FIXED_OUT_EDGE_ARR */ 146d28615ccace5f9c79fca7713c73c19e0767f8f47philippe union { 147d28615ccace5f9c79fca7713c73c19e0767f8f47philippe OutEdge fixed[N_FIXED_OUT_EDGE_ARR]; /* if !has_var */ 148d28615ccace5f9c79fca7713c73c19e0767f8f47philippe XArray* var; /* XArray* of OutEdgeArr */ /* if has_var */ 149d28615ccace5f9c79fca7713c73c19e0767f8f47philippe } edges; 150291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 151291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr; 152291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 153291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 154fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry. This indicates precisely which areas of 155fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj guest code are included in the translation, and contains all other 156fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj auxiliary info too. */ 1576c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef 1586c3769f487145a08c01b58d6e5db3ba274062ad4sewardj struct { 159bece82eba7ba26398a673def2fa326341c4f8ef7philippe union { 160bece82eba7ba26398a673def2fa326341c4f8ef7philippe struct { 161bece82eba7ba26398a673def2fa326341c4f8ef7philippe /* Profiling only: the count and weight (arbitrary meaning) for 162bece82eba7ba26398a673def2fa326341c4f8ef7philippe this translation. Weight is a property of the translation 163bece82eba7ba26398a673def2fa326341c4f8ef7philippe itself and computed once when the translation is created. 164bece82eba7ba26398a673def2fa326341c4f8ef7philippe Count is an entry count for the translation and is 165bece82eba7ba26398a673def2fa326341c4f8ef7philippe incremented by 1 every time the translation is used, if we 166bece82eba7ba26398a673def2fa326341c4f8ef7philippe are profiling. */ 167bece82eba7ba26398a673def2fa326341c4f8ef7philippe ULong count; 168bece82eba7ba26398a673def2fa326341c4f8ef7philippe UShort weight; 169bece82eba7ba26398a673def2fa326341c4f8ef7philippe } prof; // if status == InUse 170523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno next_empty_tte; // if status != InUse 171bece82eba7ba26398a673def2fa326341c4f8ef7philippe } usage; 172fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 173fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Status of the slot. Note, we need to be able to do lazy 174fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj deletion, hence the Deleted state. */ 175fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj enum { InUse, Deleted, Empty } status; 176fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1775f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* 64-bit aligned pointer to one or more 64-bit words containing 1785f76de086a6d643db51e50a4e623df7dfc9b6161sewardj the corresponding host code (must be in the same sector!) 1795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj This is a pointer into the sector's tc (code) area. */ 1805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj ULong* tcptr; 181fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 182fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This is the original guest address that purportedly is the 183fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj entry point of the translation. You might think that .entry 184fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj should be the same as .vge->base[0], and most of the time it 185fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj is. However, when doing redirections, that is not the case. 186fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj .vge must always correctly describe the guest code sections 187fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj from which this translation was made. However, .entry may or 188fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj may not be a lie, depending on whether or not we're doing 189fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj redirection. */ 190ddd61ff058f02059064e083a8accaefed23d5548florian Addr entry; 191fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 192fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This structure describes precisely what ranges of guest code 193fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj the translation covers, so we can decide whether or not to 194fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj delete it when translations of a given address range are 195fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidated. */ 196fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VexGuestExtents vge; 1976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Address range summary info: these are pointers back to 1996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclass[] entries in the containing Sector. Those entries in 2006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj turn point back here -- the two structures are mutually 2016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj redundant but both necessary to make fast deletions work. 2026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj The eclass info is similar to, and derived from, this entry's 2036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 'vge' field, but it is not the same */ 2046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UShort n_tte2ec; // # tte2ec pointers (1 to 3) 205d28615ccace5f9c79fca7713c73c19e0767f8f47philippe EClassNo tte2ec_ec[3]; // for each, the eclass # 206d28615ccace5f9c79fca7713c73c19e0767f8f47philippe UInt tte2ec_ix[3]; // and the index within the eclass. 2076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // for i in 0 .. n_tte2ec-1 2086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // sec->ec2tte[ tte2ec_ec[i] ][ tte2ec_ix[i] ] 2096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // should be the index 2106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj // of this TTEntry in the containing Sector's tt array. 211291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 212291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Admin information for chaining. 'in_edges' is a set of the 213291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj patch points which jump to this translation -- hence are 214291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj predecessors in the control flow graph. 'out_edges' points 215291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj to successors in the control flow graph -- translations to 216291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj which this one has a patched jump. In short these are just 217291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj backwards and forwards edges in the graph of patched-together 218291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj blocks. The 'in_edges' contain slightly more info, enough 219291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj that we can undo the chaining of each mentioned patch point. 220291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The 'out_edges' list exists only so that we can visit the 221291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 'in_edges' entries of all blocks we're patched through to, in 222291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj order to remove ourselves from then when we're deleted. */ 223291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 224291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* A translation can disappear for two reasons: 225291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 1. erased (as part of the oldest sector cleanup) when the 226291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj youngest sector is full. 227291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 2. discarded due to calls to VG_(discard_translations). 228291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(discard_translations) sets the status of the 229291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation to 'Deleted'. 230291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj A.o., the gdbserver discards one or more translations 231291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj when a breakpoint is inserted or removed at an Addr, 232291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj or when single stepping mode is enabled/disabled 233291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj or when a translation is instrumented for gdbserver 234291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (all the target jumps of this translation are 235291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj invalidated). 236291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 237291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj So, it is possible that the translation A to be patched 238291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (to obtain a patched jump from A to B) is invalidated 239291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj after B is translated and before A is patched. 240291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj In case a translation is erased or discarded, the patching 241291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj cannot be done. VG_(tt_tc_do_chaining) and find_TTEntry_from_hcode 242291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj are checking the 'from' translation still exists before 243291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj doing the patching. 244291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 245291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Is it safe to erase or discard the current translation E being 246291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj executed ? Amazing, but yes, it is safe. 247291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Here is the explanation: 248291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 249291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The translation E being executed can only be erased if a new 250291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation N is being done. A new translation is done only 251291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if the host addr is a not yet patched jump to another 252291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation. In such a case, the guest address of N is 253291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj assigned to the PC in the VEX state. Control is returned 254291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj to the scheduler. N will be translated. This can erase the 255291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj translation E (in case of sector full). VG_(tt_tc_do_chaining) 256291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj will not do the chaining to a non found translation E. 257291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The execution will continue at the current guest PC 258291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (i.e. the translation N). 259291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj => it is safe to erase the current translation being executed. 260291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 261291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj The current translation E being executed can also be discarded 262291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (e.g. by gdbserver). VG_(discard_translations) will mark 263291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj this translation E as Deleted, but the translation itself 264291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj is not erased. In particular, its host code can only 265291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj be overwritten or erased in case a new translation is done. 266291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj A new translation will only be done if a not yet translated 267291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj jump is to be executed. The execution of the Deleted translation 268291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj E will continue till a non patched jump is encountered. 269291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj This situation is then similar to the 'erasing' case above : 270291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj the current translation E can be erased or overwritten, as the 271291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj execution will continue at the new translation N. 272291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 273291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj */ 274291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 275291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* It is possible, although very unlikely, that a block A has 276291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj more than one patched jump to block B. This could happen if 277291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (eg) A finishes "jcond B; jmp B". 278291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 279291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj This means in turn that B's in_edges set can list A more than 280291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj once (twice in this example). However, each such entry must 281291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj have a different from_offs, since a patched jump can only 282291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj jump to one place at once (it's meaningless for it to have 283291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj multiple destinations.) IOW, the successor and predecessor 284291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj edges in the graph are not uniquely determined by a 285291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry --> TTEntry pair, but rather by a 286291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (TTEntry,offset) --> TTEntry triple. 287291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 288291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj If A has multiple edges to B then B will mention A multiple 289291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj times in its in_edges. To make things simpler, we then 290291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj require that A mentions B exactly the same number of times in 291291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj its out_edges. Furthermore, a matching out-in pair must have 292291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj the same offset (from_offs). This facilitates sanity 293291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj checking, and it facilitates establishing the invariant that 294291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj a out_edges set may not have duplicates when using the 295291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj equality defined by (TTEntry,offset). Hence the out_edges 296291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj and in_edges sets really do have both have set semantics. 297291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 298291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj eg if A has been patched to B at offsets 42 and 87 (in A) 299291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj then A.out_edges = { (B,42), (B,87) } (in any order) 300291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj and B.in_edges = { (A,42), (A,87) } (in any order) 301291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 302291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Hence for each node pair P->Q in the graph, there's a 1:1 303291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj mapping between P.out_edges and Q.in_edges. 304291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj */ 305291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr in_edges; 306291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr out_edges; 3076c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 3086c3769f487145a08c01b58d6e5db3ba274062ad4sewardj TTEntry; 3096c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 3104ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 311291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* A structure used for mapping host code addresses back to the 312291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj relevant TTEntry. Used when doing chaining, for finding the 313291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry to which some arbitrary patch address belongs. */ 314291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef 315291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj struct { 316291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* start; 317291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UInt len; 318523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno tteNo; 319291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 320291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent; 321291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 322fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself. Each sector contains an array of 323fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TCEntries, which hold code, and an array of TTEntries, containing 324fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj all required administrative info. Profiling is supported using the 325bece82eba7ba26398a673def2fa326341c4f8ef7philippe TTEntry usage.prof.count and usage.prof.weight fields, if required. 3264ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 327fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj If the sector is not in use, all three pointers are NULL and 328fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tt_n_inuse is zero. 329fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 330fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef 331fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj struct { 332fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The TCEntry area. Size of this depends on the average 333fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj translation size. We try and size it so it becomes full 334fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj precisely when this sector's translation table (tt) reaches 335fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj its load limit (SECTOR_TT_LIMIT_PERCENT). */ 336fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tc; 3374ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 338523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe /* An hash table, mapping guest address to an index in the tt array. 339bece82eba7ba26398a673def2fa326341c4f8ef7philippe htt is a fixed size, always containing 340bece82eba7ba26398a673def2fa326341c4f8ef7philippe exactly N_HTTES_PER_SECTOR entries. */ 341523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno* htt; 342bece82eba7ba26398a673def2fa326341c4f8ef7philippe 343fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The TTEntry array. This is a fixed size, always containing 344fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj exactly N_TTES_PER_SECTOR entries. */ 345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj TTEntry* tt; 3466c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This points to the current allocation point in tc. */ 348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj ULong* tc_next; 349de4a1d01951937632098a6cda45859afa587a06fsewardj 350fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* The count of tt entries with state InUse. */ 351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Int tt_n_inuse; 3526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 353bece82eba7ba26398a673def2fa326341c4f8ef7philippe /* A list of Empty/Deleted entries, chained by tte->next_empty_tte */ 354523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno empty_tt_list; 355bece82eba7ba26398a673def2fa326341c4f8ef7philippe 3566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Expandable arrays of tt indices for each of the ECLASS_N 3576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range equivalence classes. These hold indices into 3586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj the containing sector's tt array, which in turn should point 3596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj back here. */ 3606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int ec2tte_size[ECLASS_N]; 3616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int ec2tte_used[ECLASS_N]; 362523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno* ec2tte[ECLASS_N]; 363291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 364291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* The host extents. The [start, +len) ranges are constructed 365291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj in strictly non-overlapping order, so we can binary search 366291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj them at any time. */ 367291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* host_extents; /* XArray* of HostExtent */ 368fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 369fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Sector; 370de4a1d01951937632098a6cda45859afa587a06fsewardj 371de4a1d01951937632098a6cda45859afa587a06fsewardj 3726c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/ 3736c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 374fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors. The index of the 375fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest sector is recorded, and new translations are put into that 376fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. When it fills up, we move along to the next sector and 377fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj start to fill that up, wrapping around at the end of the array. 378fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj That way, once all N_TC_SECTORS have been bought into use for the 379fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj first time, and are full, we then re-use the oldest sector, 380fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj endlessly. 381fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 382fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj When running, youngest sector should be between >= 0 and < 383523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe N_TC_SECTORS. The initial value indicates the TT/TC system is 384fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj not yet initialised. 385fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 3868e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippestatic Sector sectors[MAX_N_SECTORS]; 387523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic Int youngest_sector = INV_SNO; 3886c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 389fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area. This is computed once 390fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj at startup and does not change. */ 391a11ec17946cdbafb336e9121b64961c0633af2e7sewardjstatic Int tc_sector_szQ = 0; 3926c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 3936c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 3945d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj/* A list of sector numbers, in the order which they should be 3955d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj searched to find translations. This is an optimisation to be used 3965d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj when searching for translations and should not affect 397523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe correctness. INV_SNO denotes "no entry". */ 398523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic SECno sector_search_order[MAX_N_SECTORS]; 3995d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 4005d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 4015f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Fast helper for the TC. A direct-mapped cache which holds a set of 4025f76de086a6d643db51e50a4e623df7dfc9b6161sewardj recently used (guest address, host address) pairs. This array is 4035f76de086a6d643db51e50a4e623df7dfc9b6161sewardj referred to directly from m_dispatch/dispatch-<platform>.S. 4046c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 4055f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Entries in tt_fast may refer to any valid TC entry, regardless of 406fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj which sector it's in. Consequently we must be very careful to 407fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidate this cache when TC entries are changed or disappear. 408c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 4095f76de086a6d643db51e50a4e623df7dfc9b6161sewardj A special .guest address - TRANSTAB_BOGUS_GUEST_ADDR -- must be 4105f76de086a6d643db51e50a4e623df7dfc9b6161sewardj pointed at to cause that cache entry to miss. This relies on the 4115f76de086a6d643db51e50a4e623df7dfc9b6161sewardj assumption that no guest code actually has that address, hence a 4125f76de086a6d643db51e50a4e623df7dfc9b6161sewardj value 0x1 seems good. m_translate gives the client a synthetic 4135f76de086a6d643db51e50a4e623df7dfc9b6161sewardj segfault if it tries to execute at this address. 4145f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/ 4155f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* 4165f76de086a6d643db51e50a4e623df7dfc9b6161sewardjtypedef 4175f76de086a6d643db51e50a4e623df7dfc9b6161sewardj struct { 4185f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Addr guest; 4195f76de086a6d643db51e50a4e623df7dfc9b6161sewardj Addr host; 4205f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 4215f76de086a6d643db51e50a4e623df7dfc9b6161sewardj FastCacheEntry; 4225f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/ 4235f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*global*/ __attribute__((aligned(16))) 4245f76de086a6d643db51e50a4e623df7dfc9b6161sewardj FastCacheEntry VG_(tt_fast)[VG_TT_FAST_SIZE]; 425de4a1d01951937632098a6cda45859afa587a06fsewardj 426663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */ 427663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False; 428663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 429663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 430fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/ 431de4a1d01951937632098a6cda45859afa587a06fsewardj 432fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */ 433291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_flushes = 0; 434291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_updates = 0; 43522854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 436fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */ 437291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_full_lookups = 0; 438291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_lookup_probes = 0; 43922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 44026412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj/* Number/osize/tsize of translations entered; also the number of 44126412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj those for which self-checking was requested. */ 442291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_count = 0; 443291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_osize = 0; 444291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_tsize = 0; 445291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_sc_count = 0; 446de4a1d01951937632098a6cda45859afa587a06fsewardj 447fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */ 448291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_count = 0; 449291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_osize = 0; 4505e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippestatic ULong n_sectors_recycled = 0; 451fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 452fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */ 453291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_count = 0; 454291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_osize = 0; 455291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 456291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 457291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 458291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Misc ---*/ 459291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 460291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 46154fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorianstatic void* ttaux_malloc ( const HChar* tag, SizeT n ) 462291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 463291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return VG_(arena_malloc)(VG_AR_TTAUX, tag, n); 464291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 465291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 466291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void ttaux_free ( void* p ) 467291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 468291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(arena_free)(VG_AR_TTAUX, p); 469291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 470291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 471291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 472291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 473291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Chaining support ---*/ 474291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/ 475291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 476523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic inline TTEntry* index_tte ( SECno sNo, TTEno tteNo ) 477291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 4788e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(sNo < n_sectors); 479291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(tteNo < N_TTES_PER_SECTOR); 480291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Sector* s = §ors[sNo]; 481291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(s->tt); 482291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* tte = &s->tt[tteNo]; 483291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(tte->status == InUse); 484291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return tte; 485291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 486291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 487291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdge__init ( InEdge* ie ) 488291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 489523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe ie->from_sNo = INV_SNO; /* invalid */ 490291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->from_tteNo = 0; 491291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->from_offs = 0; 492291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->to_fastEP = False; 493291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 494291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 495291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdge__init ( OutEdge* oe ) 496291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 497523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe oe->to_sNo = INV_SNO; /* invalid */ 498291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe->to_tteNo = 0; 499291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe->from_offs = 0; 500291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 501291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 502291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void TTEntry__init ( TTEntry* tte ) 503291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 504291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(memset)(tte, 0, sizeof(*tte)); 505291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 506291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 507518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UWord InEdgeArr__size ( const InEdgeArr* iea ) 508291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 509d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (iea->has_var) { 510291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 511d28615ccace5f9c79fca7713c73c19e0767f8f47philippe return VG_(sizeXA)(iea->edges.var); 512291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 513291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR); 514291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return iea->n_fixed; 515291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 516291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 517291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 518291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdgeArr__makeEmpty ( InEdgeArr* iea ) 519291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 520d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (iea->has_var) { 521291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 522d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(deleteXA)(iea->edges.var); 523d28615ccace5f9c79fca7713c73c19e0767f8f47philippe iea->edges.var = NULL; 524d28615ccace5f9c79fca7713c73c19e0767f8f47philippe iea->has_var = False; 525291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 526291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR); 527291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->n_fixed = 0; 528291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 529291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 530291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 531291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 532291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjInEdge* InEdgeArr__index ( InEdgeArr* iea, UWord i ) 533291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 534d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (iea->has_var) { 535291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 536d28615ccace5f9c79fca7713c73c19e0767f8f47philippe return (InEdge*)VG_(indexXA)(iea->edges.var, i); 537291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 538291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < iea->n_fixed); 539d28615ccace5f9c79fca7713c73c19e0767f8f47philippe return &iea->edges.fixed[i]; 540291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 541291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 542291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 543291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 544291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__deleteIndex ( InEdgeArr* iea, UWord i ) 545291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 546d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (iea->has_var) { 547291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 548d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(removeIndexXA)(iea->edges.var, i); 549291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 550291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < iea->n_fixed); 551291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (; i+1 < iea->n_fixed; i++) { 552d28615ccace5f9c79fca7713c73c19e0767f8f47philippe iea->edges.fixed[i] = iea->edges.fixed[i+1]; 553291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 554291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->n_fixed--; 555291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 556291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 557291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 558291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 559291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__add ( InEdgeArr* iea, InEdge* ie ) 560291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 561d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (iea->has_var) { 562291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed == 0); 563d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(addToXA)(iea->edges.var, ie); 564291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 565291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR); 566291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (iea->n_fixed == N_FIXED_IN_EDGE_ARR) { 567291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* The fixed array is full, so we have to initialise an 568291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray and copy the fixed array into it. */ 569d28615ccace5f9c79fca7713c73c19e0767f8f47philippe XArray *var = VG_(newXA)(ttaux_malloc, "transtab.IEA__add", 570d28615ccace5f9c79fca7713c73c19e0767f8f47philippe ttaux_free, 571d28615ccace5f9c79fca7713c73c19e0767f8f47philippe sizeof(InEdge)); 572d4dc5fc0e4091cead54ebbcdfddc60e0f3ff8081philippe VG_(hintSizeXA) (var, iea->n_fixed + 1); 573291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UWord i; 574291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < iea->n_fixed; i++) { 575d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(addToXA)(var, &iea->edges.fixed[i]); 576291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 577d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(addToXA)(var, ie); 578291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj iea->n_fixed = 0; 579d28615ccace5f9c79fca7713c73c19e0767f8f47philippe iea->has_var = True; 580d28615ccace5f9c79fca7713c73c19e0767f8f47philippe iea->edges.var = var; 581291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 582291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Just add to the fixed array. */ 583d28615ccace5f9c79fca7713c73c19e0767f8f47philippe iea->edges.fixed[iea->n_fixed++] = *ie; 584291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 585291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 586291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 587291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 588518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UWord OutEdgeArr__size ( const OutEdgeArr* oea ) 589291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 590d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (oea->has_var) { 591291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 592d28615ccace5f9c79fca7713c73c19e0767f8f47philippe return VG_(sizeXA)(oea->edges.var); 593291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 594291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR); 595291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return oea->n_fixed; 596291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 597291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 598291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 599291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdgeArr__makeEmpty ( OutEdgeArr* oea ) 600291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 601d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (oea->has_var) { 602291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 603d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(deleteXA)(oea->edges.var); 604d28615ccace5f9c79fca7713c73c19e0767f8f47philippe oea->edges.var = NULL; 605d28615ccace5f9c79fca7713c73c19e0767f8f47philippe oea->has_var = False; 606291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 607291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR); 608291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->n_fixed = 0; 609291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 610291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 611291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 612291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 613291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjOutEdge* OutEdgeArr__index ( OutEdgeArr* oea, UWord i ) 614291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 615d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (oea->has_var) { 616291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 617d28615ccace5f9c79fca7713c73c19e0767f8f47philippe return (OutEdge*)VG_(indexXA)(oea->edges.var, i); 618291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 619291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < oea->n_fixed); 620d28615ccace5f9c79fca7713c73c19e0767f8f47philippe return &oea->edges.fixed[i]; 621291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 622291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 623291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 624291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 625291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__deleteIndex ( OutEdgeArr* oea, UWord i ) 626291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 627d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (oea->has_var) { 628291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 629d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(removeIndexXA)(oea->edges.var, i); 630291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 631291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(i < oea->n_fixed); 632291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (; i+1 < oea->n_fixed; i++) { 633d28615ccace5f9c79fca7713c73c19e0767f8f47philippe oea->edges.fixed[i] = oea->edges.fixed[i+1]; 634291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 635291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->n_fixed--; 636291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 637291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 638291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 639291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 640291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__add ( OutEdgeArr* oea, OutEdge* oe ) 641291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 642d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (oea->has_var) { 643291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed == 0); 644d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(addToXA)(oea->edges.var, oe); 645291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 646291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR); 647291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oea->n_fixed == N_FIXED_OUT_EDGE_ARR) { 648291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* The fixed array is full, so we have to initialise an 649291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray and copy the fixed array into it. */ 650d28615ccace5f9c79fca7713c73c19e0767f8f47philippe XArray *var = VG_(newXA)(ttaux_malloc, "transtab.OEA__add", 651d28615ccace5f9c79fca7713c73c19e0767f8f47philippe ttaux_free, 652d28615ccace5f9c79fca7713c73c19e0767f8f47philippe sizeof(OutEdge)); 653d4dc5fc0e4091cead54ebbcdfddc60e0f3ff8081philippe VG_(hintSizeXA) (var, oea->n_fixed+1); 654291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UWord i; 655291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < oea->n_fixed; i++) { 656d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(addToXA)(var, &oea->edges.fixed[i]); 657291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 658d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(addToXA)(var, oe); 659291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oea->n_fixed = 0; 660d28615ccace5f9c79fca7713c73c19e0767f8f47philippe oea->has_var = True; 661d28615ccace5f9c79fca7713c73c19e0767f8f47philippe oea->edges.var = var; 662291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } else { 663291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Just add to the fixed array. */ 664d28615ccace5f9c79fca7713c73c19e0767f8f47philippe oea->edges.fixed[oea->n_fixed++] = *oe; 665291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 666291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 667291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 668291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 669291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 6706bd9dc18c043927c1196caba20a327238a179c42florianInt HostExtent__cmpOrd ( const void* v1, const void* v2 ) 671291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 6726bd9dc18c043927c1196caba20a327238a179c42florian const HostExtent* hx1 = v1; 6736bd9dc18c043927c1196caba20a327238a179c42florian const HostExtent* hx2 = v2; 674291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (hx1->start + hx1->len <= hx2->start) return -1; 675291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (hx2->start + hx2->len <= hx1->start) return 1; 676291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return 0; /* partial overlap */ 677291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 678291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 6793a5322057616d0da214b9e0f897866e203c03e40philippe/* True if hx is a dead host extent, i.e. corresponds to host code 6803a5322057616d0da214b9e0f897866e203c03e40philippe of an entry that was invalidated. */ 6813a5322057616d0da214b9e0f897866e203c03e40philippestatic 6823a5322057616d0da214b9e0f897866e203c03e40philippeBool HostExtent__is_dead (const HostExtent* hx, const Sector* sec) 6833a5322057616d0da214b9e0f897866e203c03e40philippe{ 684523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe const TTEno tteNo = hx->tteNo; 6853a5322057616d0da214b9e0f897866e203c03e40philippe#define LDEBUG(m) if (DEBUG_TRANSTAB) \ 6863a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf) (m \ 6873a5322057616d0da214b9e0f897866e203c03e40philippe " start 0x%p len %u sector %d ttslot %u" \ 688ddd61ff058f02059064e083a8accaefed23d5548florian " tt.entry 0x%lu tt.tcptr 0x%p\n", \ 6893a5322057616d0da214b9e0f897866e203c03e40philippe hx->start, hx->len, (int)(sec - sectors), \ 6903a5322057616d0da214b9e0f897866e203c03e40philippe hx->tteNo, \ 6913a5322057616d0da214b9e0f897866e203c03e40philippe sec->tt[tteNo].entry, sec->tt[tteNo].tcptr) 6923a5322057616d0da214b9e0f897866e203c03e40philippe 6933a5322057616d0da214b9e0f897866e203c03e40philippe /* Entry might have been invalidated and not re-used yet.*/ 6943a5322057616d0da214b9e0f897866e203c03e40philippe if (sec->tt[tteNo].status == Deleted) { 6953a5322057616d0da214b9e0f897866e203c03e40philippe LDEBUG("found deleted entry"); 6963a5322057616d0da214b9e0f897866e203c03e40philippe return True; 6973a5322057616d0da214b9e0f897866e203c03e40philippe } 6983a5322057616d0da214b9e0f897866e203c03e40philippe /* Maybe we found this entry via a host_extents which was 6993a5322057616d0da214b9e0f897866e203c03e40philippe inserted for an entry which was changed to Deleted then 7003a5322057616d0da214b9e0f897866e203c03e40philippe re-used after. If this entry was re-used, then its tcptr 7013a5322057616d0da214b9e0f897866e203c03e40philippe is >= to host_extents start (i.e. the previous tcptr) + len. 7023a5322057616d0da214b9e0f897866e203c03e40philippe This is the case as there is no re-use of host code: a new 7033a5322057616d0da214b9e0f897866e203c03e40philippe entry or re-used entry always gets "higher value" host code. */ 7043a5322057616d0da214b9e0f897866e203c03e40philippe if ((UChar*) sec->tt[tteNo].tcptr >= hx->start + hx->len) { 7053a5322057616d0da214b9e0f897866e203c03e40philippe LDEBUG("found re-used entry"); 7063a5322057616d0da214b9e0f897866e203c03e40philippe return True; 7073a5322057616d0da214b9e0f897866e203c03e40philippe } 7083a5322057616d0da214b9e0f897866e203c03e40philippe 7093a5322057616d0da214b9e0f897866e203c03e40philippe return False; 7103a5322057616d0da214b9e0f897866e203c03e40philippe#undef LDEBUG 7113a5322057616d0da214b9e0f897866e203c03e40philippe} 7123a5322057616d0da214b9e0f897866e203c03e40philippe 713291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic __attribute__((noinline)) 714523b5b8ca67d2063afd02342d0138b0dc0ed6706philippeBool find_TTEntry_from_hcode( /*OUT*/SECno* from_sNo, 715523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe /*OUT*/TTEno* from_tteNo, 716291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj void* hcode ) 717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 718523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno i; 719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 720291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Search order logic copied from VG_(search_transtab). */ 7218e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 722523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno sno = sector_search_order[i]; 723523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (UNLIKELY(sno == INV_SNO)) 724291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; /* run out of sectors to search */ 725291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 726518850bf0da07ed3e2244e307268ae0fd80e93a8florian const Sector* sec = §ors[sno]; 727518850bf0da07ed3e2244e307268ae0fd80e93a8florian const XArray* /* of HostExtent */ host_extents = sec->host_extents; 728291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(host_extents); 729291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 730291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent key; 731291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(memset)(&key, 0, sizeof(key)); 732291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj key.start = hcode; 733291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj key.len = 1; 734291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Word firstW = -1, lastW = -1; 735291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool found = VG_(lookupXA_UNSAFE)( 736291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj host_extents, &key, &firstW, &lastW, 7376bd9dc18c043927c1196caba20a327238a179c42florian HostExtent__cmpOrd ); 738291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(firstW == lastW); // always true, even if not found 739291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (found) { 740291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent* hx = VG_(indexXA)(host_extents, firstW); 741523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno tteNo = hx->tteNo; 742291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Do some additional sanity checks. */ 743bece82eba7ba26398a673def2fa326341c4f8ef7philippe vg_assert(tteNo < N_TTES_PER_SECTOR); 7443a5322057616d0da214b9e0f897866e203c03e40philippe 7453a5322057616d0da214b9e0f897866e203c03e40philippe /* if this hx entry corresponds to dead host code, we must 7463a5322057616d0da214b9e0f897866e203c03e40philippe tell this code has not been found, as it cannot be patched. */ 7473a5322057616d0da214b9e0f897866e203c03e40philippe if (HostExtent__is_dead (hx, sec)) 748291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; 7493a5322057616d0da214b9e0f897866e203c03e40philippe 750291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec->tt[tteNo].status == InUse); 751291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Can only half check that the found TTEntry contains hcode, 752291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj due to not having a length value for the hcode in the 753291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry. */ 754291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert((UChar*)sec->tt[tteNo].tcptr <= (UChar*)hcode); 755291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Looks plausible */ 756291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *from_sNo = sno; 757523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe *from_tteNo = tteNo; 758291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return True; 759291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 760291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 761291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; 762291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 763291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 764291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 765291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Figure out whether or not hcode is jitted code present in the main 766291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj code cache (but not in the no-redir cache). Used for sanity 767291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj checking. */ 768518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool is_in_the_main_TC ( const void* hcode ) 769291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 770523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno i, sno; 7718e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 772291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sno = sector_search_order[i]; 773523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (sno == INV_SNO) 774291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj break; /* run out of sectors to search */ 775518850bf0da07ed3e2244e307268ae0fd80e93a8florian if ((const UChar*)hcode >= (const UChar*)sectors[sno].tc 776518850bf0da07ed3e2244e307268ae0fd80e93a8florian && (const UChar*)hcode <= (const UChar*)sectors[sno].tc_next 777291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj + sizeof(ULong) - 1) 778291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return True; 779291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 780291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return False; 781291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 782291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 783291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 784291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Fulfill a chaining request, and record admin info so we 785291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj can undo it later, if required. 786291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj*/ 787291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid VG_(tt_tc_do_chaining) ( void* from__patch_addr, 788523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno to_sNo, 789523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno to_tteNo, 790291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool to_fastEP ) 791291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 792291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Get the CPU info established at startup. */ 793597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host = VexArch_INVALID; 794597314210494248b4fbefd45525a748439629218sewardj VexArchInfo archinfo_host; 795597314210494248b4fbefd45525a748439629218sewardj VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host)); 796597314210494248b4fbefd45525a748439629218sewardj VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host ); 797597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host = archinfo_host.endness; 798291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 799291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // host_code is where we're patching to. So it needs to 800291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // take into account, whether we're jumping to the slow 801291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // or fast entry point. By definition, the fast entry point 802291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // is exactly one event check's worth of code along from 803291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // the slow (tcptr) entry point. 804291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* to_tte = index_tte(to_sNo, to_tteNo); 805291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj void* host_code = ((UChar*)to_tte->tcptr) 8065f8ced84fdd6ebd260cece49b51477c68437e8caflorian + (to_fastEP ? LibVEX_evCheckSzB(arch_host) : 0); 807291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 808291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // stay sane -- the patch point (dst) is in this sector's code cache 809291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( (UChar*)host_code >= (UChar*)sectors[to_sNo].tc ); 810291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( (UChar*)host_code <= (UChar*)sectors[to_sNo].tc_next 811291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj + sizeof(ULong) - 1 ); 812291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 813291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Find the TTEntry for the from__ code. This isn't simple since 814291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj we only know the patch address, which is going to be somewhere 815291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj inside the from_ block. */ 816523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno from_sNo = INV_SNO; 817523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno from_tteNo = INV_TTE; 818291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool from_found 819291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = find_TTEntry_from_hcode( &from_sNo, &from_tteNo, 820291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj from__patch_addr ); 821291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (!from_found) { 822291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // The from code might have been discarded due to sector re-use 823291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // or marked Deleted due to translation invalidation. 824291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // In such a case, don't do the chaining. 825291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(debugLog)(1,"transtab", 826291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj "host code %p not found (discarded? sector recycled?)" 827291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj " => no chaining done\n", 828291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj from__patch_addr); 829291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj return; 830291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 831291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 832291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* from_tte = index_tte(from_sNo, from_tteNo); 833291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 834291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Get VEX to do the patching itself. We have to hand it off 835291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj since it is host-dependent. */ 836291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexInvalRange vir 837291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = LibVEX_Chain( 838597314210494248b4fbefd45525a748439629218sewardj arch_host, endness_host, 839291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj from__patch_addr, 840291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(fnptr_to_fnentry)( 841291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP) 842291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj : &VG_(disp_cp_chain_me_to_slowEP)), 843291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj (void*)host_code 844291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 845291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( (void*)vir.start, vir.len ); 846291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 847291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Now do the tricky bit -- update the ch_succs and ch_preds info 848291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for the two translations involved, so we can undo the chaining 849291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj later, which we will have to do if the to_ block gets removed 850291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for whatever reason. */ 851291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 852291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* This is the new from_ -> to_ link to add. */ 853291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge ie; 854291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge__init(&ie); 855291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.from_sNo = from_sNo; 856291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.from_tteNo = from_tteNo; 857291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.to_fastEP = to_fastEP; 858291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HWord from_offs = (HWord)( (UChar*)from__patch_addr 859291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj - (UChar*)from_tte->tcptr ); 860291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(from_offs < 100000/* let's say */); 861291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie.from_offs = (UInt)from_offs; 862291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 863291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* This is the new to_ -> from_ backlink to add. */ 864291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge oe; 865291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge__init(&oe); 866291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe.to_sNo = to_sNo; 867291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe.to_tteNo = to_tteNo; 868291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj oe.from_offs = (UInt)from_offs; 869291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 870291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Add .. */ 871291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr__add(&to_tte->in_edges, &ie); 872291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr__add(&from_tte->out_edges, &oe); 873291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 874291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 875291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 876291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Unchain one patch, as described by the specified InEdge. For 877291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sanity check purposes only (to check that the patched location is 878291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj as expected) it also requires the fast and slow entry point 879291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj addresses of the destination block (that is, the block that owns 880291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj this InEdge). */ 881291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj__attribute__((noinline)) 882597314210494248b4fbefd45525a748439629218sewardjstatic void unchain_one ( VexArch arch_host, VexEndness endness_host, 883291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge* ie, 884291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj void* to_fastEPaddr, void* to_slowEPaddr ) 885291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 886291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(ie); 887291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* tte 888291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = index_tte(ie->from_sNo, ie->from_tteNo); 889291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* place_to_patch 89019f91bbaedb4caef8a60ce94b0f507193cc0bc10florian = ((UChar*)tte->tcptr) + ie->from_offs; 891291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* disp_cp_chain_me 892291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = VG_(fnptr_to_fnentry)( 893291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ie->to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP) 894291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj : &VG_(disp_cp_chain_me_to_slowEP) 895291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 896291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* place_to_jump_to_EXPECTED 897291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = ie->to_fastEP ? to_fastEPaddr : to_slowEPaddr; 898291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 899291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // stay sane: both src and dst for this unchaining are 900291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // in the main code cache 901291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( is_in_the_main_TC(place_to_patch) ); // src 902291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert( is_in_the_main_TC(place_to_jump_to_EXPECTED) ); // dst 903291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // dst check is ok because LibVEX_UnChain checks that 904291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // place_to_jump_to_EXPECTED really is the current dst, and 905291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // asserts if it isn't. 906291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexInvalRange vir 907597314210494248b4fbefd45525a748439629218sewardj = LibVEX_UnChain( arch_host, endness_host, place_to_patch, 908291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj place_to_jump_to_EXPECTED, disp_cp_chain_me ); 909291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( (void*)vir.start, vir.len ); 910291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 911291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 912291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 913291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* The specified block is about to be deleted. Update the preds and 914291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj succs of its associated blocks accordingly. This includes undoing 915291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj any chained jumps to this block. */ 916291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic 917597314210494248b4fbefd45525a748439629218sewardjvoid unchain_in_preparation_for_deletion ( VexArch arch_host, 918597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host, 919523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno here_sNo, TTEno here_tteNo ) 920291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{ 9213a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 9223a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf)("QQQ unchain_in_prep %u.%u...\n", here_sNo, here_tteNo); 923291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UWord i, j, n, m; 9245f8ced84fdd6ebd260cece49b51477c68437e8caflorian Int evCheckSzB = LibVEX_evCheckSzB(arch_host); 925291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* here_tte = index_tte(here_sNo, here_tteNo); 9263a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 927ddd61ff058f02059064e083a8accaefed23d5548florian VG_(printf)("... QQQ tt.entry 0x%lu tt.tcptr 0x%p\n", 9283a5322057616d0da214b9e0f897866e203c03e40philippe here_tte->entry, here_tte->tcptr); 929291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(here_tte->status == InUse); 930291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 931291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Visit all InEdges owned by here_tte. */ 932291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj n = InEdgeArr__size(&here_tte->in_edges); 933291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < n; i++) { 934291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge* ie = InEdgeArr__index(&here_tte->in_edges, i); 935291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // Undo the chaining. 936291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* here_slow_EP = (UChar*)here_tte->tcptr; 937291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj UChar* here_fast_EP = here_slow_EP + evCheckSzB; 938597314210494248b4fbefd45525a748439629218sewardj unchain_one(arch_host, endness_host, ie, here_fast_EP, here_slow_EP); 939291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // Find the corresponding entry in the "from" node's out_edges, 940291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // and remove it. 941291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* from_tte = index_tte(ie->from_sNo, ie->from_tteNo); 942291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj m = OutEdgeArr__size(&from_tte->out_edges); 943291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(m > 0); // it must have at least one entry 944291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (j = 0; j < m; j++) { 945291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge* oe = OutEdgeArr__index(&from_tte->out_edges, j); 946291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (oe->to_sNo == here_sNo && oe->to_tteNo == here_tteNo 947291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj && oe->from_offs == ie->from_offs) 948291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj break; 949291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 950291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(j < m); // "oe must be findable" 951291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr__deleteIndex(&from_tte->out_edges, j); 952291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 953291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 954291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Visit all OutEdges owned by here_tte. */ 955291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj n = OutEdgeArr__size(&here_tte->out_edges); 956291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (i = 0; i < n; i++) { 957291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdge* oe = OutEdgeArr__index(&here_tte->out_edges, i); 958291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // Find the corresponding entry in the "to" node's in_edges, 959291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj // and remove it. 960291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj TTEntry* to_tte = index_tte(oe->to_sNo, oe->to_tteNo); 961291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj m = InEdgeArr__size(&to_tte->in_edges); 962291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(m > 0); // it must have at least one entry 963291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj for (j = 0; j < m; j++) { 964291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdge* ie = InEdgeArr__index(&to_tte->in_edges, j); 965291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (ie->from_sNo == here_sNo && ie->from_tteNo == here_tteNo 966291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj && ie->from_offs == oe->from_offs) 967291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj break; 968291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 969291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(j < m); // "ie must be findable" 970291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr__deleteIndex(&to_tte->in_edges, j); 971291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 972291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 973291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj InEdgeArr__makeEmpty(&here_tte->in_edges); 974291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj OutEdgeArr__makeEmpty(&here_tte->out_edges); 975291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj} 976fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 977fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 9786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 9796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Address-range equivalence class stuff ---*/ 9806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 9816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Return equivalence class number for a range. */ 9836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 984d28615ccace5f9c79fca7713c73c19e0767f8f47philippestatic EClassNo range_to_eclass ( Addr start, UInt len ) 9856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 9866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt mask = (1 << ECLASS_WIDTH) - 1; 9876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt lo = (UInt)start; 9886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt hi = lo + len - 1; 9896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt loBits = (lo >> ECLASS_SHIFT) & mask; 9906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt hiBits = (hi >> ECLASS_SHIFT) & mask; 9916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (loBits == hiBits) { 9926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(loBits < ECLASS_N-1); 9936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return loBits; 9946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 9956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return ECLASS_MISC; 9966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 9976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 9986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 9996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Calculates the equivalence class numbers for any VexGuestExtent. 10016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj These are written in *eclasses, which must be big enough to hold 3 10026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Ints. The number written, between 1 and 3, is returned. The 10036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses are presented in order, and any duplicates are removed. 10046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj*/ 10056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 1007d28615ccace5f9c79fca7713c73c19e0767f8f47philippeInt vexGuestExtents_to_eclasses ( /*OUT*/EClassNo* eclasses, 1008518850bf0da07ed3e2244e307268ae0fd80e93a8florian const VexGuestExtents* vge ) 10096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 1010518850bf0da07ed3e2244e307268ae0fd80e93a8florian 10116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# define SWAP(_lv1,_lv2) \ 10126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj do { Int t = _lv1; _lv1 = _lv2; _lv2 = t; } while (0) 10136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1014d28615ccace5f9c79fca7713c73c19e0767f8f47philippe Int i, j, n_ec; 1015d28615ccace5f9c79fca7713c73c19e0767f8f47philippe EClassNo r; 10166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(vge->n_used >= 1 && vge->n_used <= 3); 10186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_ec = 0; 10206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < vge->n_used; i++) { 1021ddd61ff058f02059064e083a8accaefed23d5548florian r = range_to_eclass( vge->base[i], vge->len[i] ); 10226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (r == ECLASS_MISC) 10236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj goto bad; 10246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* only add if we haven't already seen it */ 10256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < n_ec; j++) 10266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[j] == r) 10276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj break; 10286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (j == n_ec) 10296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses[n_ec++] = r; 10306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 1) 10336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 1; 10346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 2) { 10366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* sort */ 10376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[1]) 10386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[1]); 10396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 2; 10406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n_ec == 3) { 10436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* sort */ 10446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[2]) 10456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[2]); 10466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[0] > eclasses[1]) 10476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[0], eclasses[1]); 10486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (eclasses[1] > eclasses[2]) 10496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj SWAP(eclasses[1], eclasses[2]); 10506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 3; 10516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* NOTREACHED */ 10546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(0); 10556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bad: 10576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclasses[0] = ECLASS_MISC; 10586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return 1; 10596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# undef SWAP 10616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 10626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Add tteno to the set of entries listed for equivalence class ec in 10656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj this sector. Returns used location in eclass array. */ 10666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 1068d28615ccace5f9c79fca7713c73c19e0767f8f47philippeUInt addEClassNo ( /*MOD*/Sector* sec, EClassNo ec, TTEno tteno ) 10696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 10706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int old_sz, new_sz, i, r; 1071523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno *old_ar, *new_ar; 10726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_N); 10746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno < N_TTES_PER_SECTOR); 10756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10763a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("ec %d gets %d\n", ec, (Int)tteno); 10776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[ec] >= sec->ec2tte_size[ec]) { 10796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->ec2tte_used[ec] == sec->ec2tte_size[ec]); 10816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj old_sz = sec->ec2tte_size[ec]; 10836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj old_ar = sec->ec2tte[ec]; 10846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj new_sz = old_sz==0 ? 8 : old_sz<64 ? 2*old_sz : (3*old_sz)/2; 1085291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj new_ar = ttaux_malloc("transtab.aECN.1", 1086523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe new_sz * sizeof(TTEno)); 10876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < old_sz; i++) 10886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj new_ar[i] = old_ar[i]; 10896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (old_ar) 1090291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free(old_ar); 10916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte_size[ec] = new_sz; 10926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec] = new_ar; 10936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10943a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("expand ec %d to %d\n", ec, new_sz); 10956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 10966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 10976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Common case */ 10986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj r = sec->ec2tte_used[ec]++; 10996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(r >= 0 && r < sec->ec2tte_size[ec]); 11006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec][r] = tteno; 11016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return (UInt)r; 11026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 11036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* 'vge' is being added to 'sec' at TT entry 'tteno'. Add appropriate 11066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj eclass entries to 'sec'. */ 11076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 1109523b5b8ca67d2063afd02342d0138b0dc0ed6706philippevoid upd_eclasses_after_add ( /*MOD*/Sector* sec, TTEno tteno ) 11106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 1111d28615ccace5f9c79fca7713c73c19e0767f8f47philippe Int i, r; 1112d28615ccace5f9c79fca7713c73c19e0767f8f47philippe EClassNo eclasses[3]; 11136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 11146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR); 11156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 11176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj r = vexGuestExtents_to_eclasses( eclasses, &tte->vge ); 11186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(r >= 1 && r <= 3); 11206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->n_tte2ec = r; 11216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < r; i++) { 11236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->tte2ec_ec[i] = eclasses[i]; 1124523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe tte->tte2ec_ix[i] = addEClassNo( sec, eclasses[i], tteno ); 11256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 11276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Check the eclass info in 'sec' to ensure it is consistent. Returns 11306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj True if OK, False if something's not right. Expensive. */ 11316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1132518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool sanity_check_eclasses_in_sector ( const Sector* sec ) 11336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 11346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# define BAD(_str) do { whassup = (_str); goto bad; } while (0) 11356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11366bd9dc18c043927c1196caba20a327238a179c42florian const HChar* whassup = NULL; 1137d28615ccace5f9c79fca7713c73c19e0767f8f47philippe Int j, k, n, ec_idx; 1138d28615ccace5f9c79fca7713c73c19e0767f8f47philippe EClassNo i; 1139d28615ccace5f9c79fca7713c73c19e0767f8f47philippe EClassNo ec_num; 11406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 1141523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno tteno; 11426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ULong* tce; 11436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Basic checks on this sector */ 1145bece82eba7ba26398a673def2fa326341c4f8ef7philippe if (sec->tt_n_inuse < 0 || sec->tt_n_inuse > N_TTES_PER_SECTOR) 11466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("invalid sec->tt_n_inuse"); 11476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tce = sec->tc_next; 11486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tce < &sec->tc[0] || tce > &sec->tc[tc_sector_szQ]) 11496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("sec->tc_next points outside tc"); 11506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* For each eclass ... */ 11526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < ECLASS_N; i++) { 11536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] == 0 && sec->ec2tte[i] != NULL) 11546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte_size/ec2tte mismatch(1)"); 11556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_size[i] != 0 && sec->ec2tte[i] == NULL) 11566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte_size/ec2tte mismatch(2)"); 11576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[i] < 0 11586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj || sec->ec2tte_used[i] > sec->ec2tte_size[i]) 11596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("implausible ec2tte_used"); 11606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->ec2tte_used[i] == 0) 11616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* For each tt reference in each eclass .. ensure the reference 11646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj is to a valid tt entry, and that the entry's address ranges 11656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj really include this eclass. */ 11666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 11676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < sec->ec2tte_used[i]; j++) { 11686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tteno = sec->ec2tte[i][j]; 11696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno == EC2TTE_DELETED) 11706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno >= N_TTES_PER_SECTOR) 11726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("implausible tteno"); 11736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 11746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != InUse) 11756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tteno points to non-inuse tte"); 11766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3) 11776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_tte2ec out of range"); 11786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Exactly least one of tte->eclasses[0 .. tte->n_eclasses-1] 11796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj must equal i. Inspect tte's eclass info. */ 11806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n = 0; 11816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (k = 0; k < tte->n_tte2ec; k++) { 11826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (k < tte->n_tte2ec-1 11836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj && tte->tte2ec_ec[k] >= tte->tte2ec_ec[k+1]) 11846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ec[..] out of order"); 11856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = tte->tte2ec_ec[k]; 11866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num < 0 || ec_num >= ECLASS_N) 11876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ec[..] out of range"); 11886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num != i) 11896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 11906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[k]; 11916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[i]) 11926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->tte2ec_ix[..] out of range"); 11936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx == j) 11946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n++; 11956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (n != 1) 11976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tteno does not point back at eclass"); 11986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 11996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* That establishes that for each forward pointer from TTEntrys 12026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj there is a corresponding backward pointer from the eclass[] 12036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj arrays. However, it doesn't rule out the possibility of other, 12046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bogus pointers in the eclass[] arrays. So do those similarly: 12056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj scan through them and check the TTEntryies they point at point 12066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj back. */ 12076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1208523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe for (tteno = 0; tteno < N_TTES_PER_SECTOR; tteno++) { 12096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1210523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe tte = &sec->tt[tteno]; 12116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status == Empty || tte->status == Deleted) { 12126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec != 0) 12136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_eclasses nonzero for unused tte"); 12146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 12156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 12186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3) 12206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->n_eclasses out of range(2)"); 12216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (j = 0; j < tte->n_tte2ec; j++) { 12236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_num = tte->tte2ec_ec[j]; 12246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_num < 0 || ec_num >= ECLASS_N) 12256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->eclass[..] out of range"); 12266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[j]; 12276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[ec_num]) 12286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("tte->ec_idx[..] out of range(2)"); 1229523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (sec->ec2tte[ec_num][ec_idx] != tteno) 12306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj BAD("ec2tte does not point back to tte"); 12316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return True; 12356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj bad: 12376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (whassup) 12386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(0, "transtab", "eclass sanity fail: %s\n", whassup); 12396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# if 0 12416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("eclass = %d\n", i); 12426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("tteno = %d\n", (Int)tteno); 12436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj switch (tte->status) { 12446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case InUse: VG_(printf)("InUse\n"); break; 12456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case Deleted: VG_(printf)("Deleted\n"); break; 12466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj case Empty: VG_(printf)("Empty\n"); break; 12476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != Empty) { 12496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (k = 0; k < tte->vge.n_used; k++) 1250ddd61ff058f02059064e083a8accaefed23d5548florian VG_(printf)("0x%lx %u\n", tte->vge.base[k], (UInt)tte->vge.len[k]); 12516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 12526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# endif 12536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return False; 12556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj# undef BAD 12576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 12586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Sanity check absolutely everything. True == check passed. */ 12616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 12625f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* forwards */ 12630ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void ); 12640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 12655d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardjstatic Bool sanity_check_sector_search_order ( void ) 12665d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj{ 1267523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno i, j, nListed; 12685d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* assert the array is the right size */ 12698e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(MAX_N_SECTORS == (sizeof(sector_search_order) 12708e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe / sizeof(sector_search_order[0]))); 1271523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe /* Check it's of the form valid_sector_numbers ++ [INV_SNO, INV_SNO, ..] */ 12728e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 1273523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (sector_search_order[i] == INV_SNO 1274523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe || sector_search_order[i] >= n_sectors) 12755d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 12765d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12775d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj nListed = i; 12788e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (/* */; i < n_sectors; i++) { 1279523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (sector_search_order[i] != INV_SNO) 12805d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 12815d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12828e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe if (i != n_sectors) 12835d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 12845d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Check each sector number only appears once */ 12858e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 1286523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (sector_search_order[i] == INV_SNO) 12875d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj continue; 12888e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (j = i+1; j < n_sectors; j++) { 12895d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sector_search_order[j] == sector_search_order[i]) 12905d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 12915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12925d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12935d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Check that the number of listed sectors equals the number 12945d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj in use, by counting nListed back down. */ 12958e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 12965d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (sectors[i].tc != NULL) 12975d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj nListed--; 12985d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 12995d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (nListed != 0) 13005d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 13015d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return True; 13025d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj} 13035d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 13046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_all_sectors ( void ) 13056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 1306523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno sno; 13076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane; 13086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 13098e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 13103a5322057616d0da214b9e0f897866e203c03e40philippe Int i; 13113a5322057616d0da214b9e0f897866e203c03e40philippe Int nr_not_dead_hx = 0; 13123a5322057616d0da214b9e0f897866e203c03e40philippe Int szhxa; 13136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 13146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 13156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 13166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sane = sanity_check_eclasses_in_sector( sec ); 13176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (!sane) 13186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return False; 13193a5322057616d0da214b9e0f897866e203c03e40philippe szhxa = VG_(sizeXA)(sec->host_extents); 13203a5322057616d0da214b9e0f897866e203c03e40philippe for (i = 0; i < szhxa; i++) { 13213a5322057616d0da214b9e0f897866e203c03e40philippe const HostExtent* hx = VG_(indexXA)(sec->host_extents, i); 13223a5322057616d0da214b9e0f897866e203c03e40philippe if (!HostExtent__is_dead (hx, sec)) 13233a5322057616d0da214b9e0f897866e203c03e40philippe nr_not_dead_hx++; 13243a5322057616d0da214b9e0f897866e203c03e40philippe } 13253a5322057616d0da214b9e0f897866e203c03e40philippe if (nr_not_dead_hx != sec->tt_n_inuse) { 13263a5322057616d0da214b9e0f897866e203c03e40philippe VG_(debugLog)(0, "transtab", 1327523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe "nr_not_dead_hx %d sanity fail " 1328523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe "(expected == in use %d)\n", 13293a5322057616d0da214b9e0f897866e203c03e40philippe nr_not_dead_hx, sec->tt_n_inuse); 13303a5322057616d0da214b9e0f897866e203c03e40philippe return False; 13313a5322057616d0da214b9e0f897866e203c03e40philippe } 13326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 13333a5322057616d0da214b9e0f897866e203c03e40philippe 13345f76de086a6d643db51e50a4e623df7dfc9b6161sewardj if ( !sanity_check_redir_tt_tc() ) 13355f76de086a6d643db51e50a4e623df7dfc9b6161sewardj return False; 13365d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if ( !sanity_check_sector_search_order() ) 13375d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; 13386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return True; 13396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 13406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1341fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 13425d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 1343fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/ 13446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Add/find translations ---*/ 1345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/ 1346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1347518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UInt vge_osize ( const VexGuestExtents* vge ) 1348c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{ 1349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt i, n = 0; 1350fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < vge->n_used; i++) 1351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n += (UInt)vge->len[i]; 1352fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return n; 1353c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj} 1354c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 1355523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic Bool isValidSector ( SECno sector ) 13566c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1357523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (sector == INV_SNO || sector >= n_sectors) 1358fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1359fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 13606c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1361de4a1d01951937632098a6cda45859afa587a06fsewardj 1362523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic inline HTTno HASH_TT ( Addr key ) 1363de4a1d01951937632098a6cda45859afa587a06fsewardj{ 1364ddd61ff058f02059064e083a8accaefed23d5548florian UInt kHi = sizeof(Addr) == 4 ? 0 : (key >> 32); 1365fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UInt kLo = (UInt)key; 13666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt k32 = kHi ^ kLo; 13676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj UInt ror = 7; 13686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ror > 0) 13696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj k32 = (k32 >> ror) | (k32 << (32-ror)); 1370523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe return (HTTno)(k32 % N_HTTES_PER_SECTOR); 1371de4a1d01951937632098a6cda45859afa587a06fsewardj} 1372de4a1d01951937632098a6cda45859afa587a06fsewardj 1373ddd61ff058f02059064e083a8accaefed23d5548florianstatic void setFastCacheEntry ( Addr key, ULong* tcptr ) 1374de4a1d01951937632098a6cda45859afa587a06fsewardj{ 13753387dda4479102751d544c176a7bfc24f3766669sewardj UInt cno = (UInt)VG_TT_FAST_HASH(key); 1376ddd61ff058f02059064e083a8accaefed23d5548florian VG_(tt_fast)[cno].guest = key; 13775f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[cno].host = (Addr)tcptr; 1378fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_updates++; 13795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* This shouldn't fail. It should be assured by m_translate 13805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj which should reject any attempt to make translation of code 13815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj starting at TRANSTAB_BOGUS_GUEST_ADDR. */ 13825f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_(tt_fast)[cno].guest != TRANSTAB_BOGUS_GUEST_ADDR); 13836c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1384de4a1d01951937632098a6cda45859afa587a06fsewardj 1385291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Invalidate the fast cache VG_(tt_fast). */ 13865f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastCache ( void ) 13875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{ 13885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj UInt j; 13895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* This loop is popular enough to make it worth unrolling a 13905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj bit, at least on ppc32. */ 13915f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0); 13925f76de086a6d643db51e50a4e623df7dfc9b6161sewardj for (j = 0; j < VG_TT_FAST_SIZE; j += 4) { 13935f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+0].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13945f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+1].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13955f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+2].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13965f76de086a6d643db51e50a4e623df7dfc9b6161sewardj VG_(tt_fast)[j+3].guest = TRANSTAB_BOGUS_GUEST_ADDR; 13975f76de086a6d643db51e50a4e623df7dfc9b6161sewardj } 13985f76de086a6d643db51e50a4e623df7dfc9b6161sewardj 13995f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(j == VG_TT_FAST_SIZE); 1400fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_flushes++; 14016c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1402de4a1d01951937632098a6cda45859afa587a06fsewardj 1403bece82eba7ba26398a673def2fa326341c4f8ef7philippe 1404523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic TTEno get_empty_tt_slot(SECno sNo) 1405bece82eba7ba26398a673def2fa326341c4f8ef7philippe{ 1406523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno i; 1407bece82eba7ba26398a673def2fa326341c4f8ef7philippe 1408bece82eba7ba26398a673def2fa326341c4f8ef7philippe i = sectors[sNo].empty_tt_list; 1409bece82eba7ba26398a673def2fa326341c4f8ef7philippe sectors[sNo].empty_tt_list = sectors[sNo].tt[i].usage.next_empty_tte; 1410bece82eba7ba26398a673def2fa326341c4f8ef7philippe 1411bece82eba7ba26398a673def2fa326341c4f8ef7philippe vg_assert (i >= 0 && i < N_TTES_PER_SECTOR); 1412bece82eba7ba26398a673def2fa326341c4f8ef7philippe 1413bece82eba7ba26398a673def2fa326341c4f8ef7philippe return i; 1414bece82eba7ba26398a673def2fa326341c4f8ef7philippe} 1415bece82eba7ba26398a673def2fa326341c4f8ef7philippe 1416523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic void add_in_empty_tt_list (SECno sNo, TTEno tteno) 1417bece82eba7ba26398a673def2fa326341c4f8ef7philippe{ 1418bece82eba7ba26398a673def2fa326341c4f8ef7philippe sectors[sNo].tt[tteno].usage.next_empty_tte = sectors[sNo].empty_tt_list; 1419bece82eba7ba26398a673def2fa326341c4f8ef7philippe sectors[sNo].empty_tt_list = tteno; 1420bece82eba7ba26398a673def2fa326341c4f8ef7philippe} 1421bece82eba7ba26398a673def2fa326341c4f8ef7philippe 1422523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic void initialiseSector ( SECno sno ) 14236c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1424523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe UInt i; 1425291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj SysRes sres; 14266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 1427fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(isValidSector(sno)); 1428fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 14295d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj { Bool sane = sanity_check_sector_search_order(); 14305d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj vg_assert(sane); 14315d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 14326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 14336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 14346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) { 14356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1436fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Sector has never been used before. Need to allocate tt and 1437fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tc. */ 14386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt == NULL); 14396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tc_next == NULL); 14406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt_n_inuse == 0); 1441d28615ccace5f9c79fca7713c73c19e0767f8f47philippe for (EClassNo e = 0; e < ECLASS_N; e++) { 1442d28615ccace5f9c79fca7713c73c19e0767f8f47philippe vg_assert(sec->ec2tte_size[e] == 0); 1443d28615ccace5f9c79fca7713c73c19e0767f8f47philippe vg_assert(sec->ec2tte_used[e] == 0); 1444d28615ccace5f9c79fca7713c73c19e0767f8f47philippe vg_assert(sec->ec2tte[e] == NULL); 14456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 1446291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec->host_extents == NULL); 144745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 14485e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1) 1449059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj VG_(dmsg)("transtab: " "allocate sector %d\n", sno); 145045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 145145f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ ); 1452cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 145345f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(out_of_memory_NORETURN)("initialiseSector(TC)", 145445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 8 * tc_sector_szQ ); 145545f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*NOTREACHED*/ 145645f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 145744bd4465581ff28cef83bb39e684a489297d7b71florian sec->tc = (ULong*)(Addr)sr_Res(sres); 145845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 145945f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_mmap_anon_float_valgrind) 146045f4e7c91119c7d01a59f5e827c67841632c9314sewardj ( N_TTES_PER_SECTOR * sizeof(TTEntry) ); 1461cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 146245f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(out_of_memory_NORETURN)("initialiseSector(TT)", 146345f4e7c91119c7d01a59f5e827c67841632c9314sewardj N_TTES_PER_SECTOR * sizeof(TTEntry) ); 146445f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*NOTREACHED*/ 146545f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 146644bd4465581ff28cef83bb39e684a489297d7b71florian sec->tt = (TTEntry*)(Addr)sr_Res(sres); 1467bece82eba7ba26398a673def2fa326341c4f8ef7philippe sec->empty_tt_list = HTT_EMPTY; 1468523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe for (TTEno ei = 0; ei < N_TTES_PER_SECTOR; ei++) { 1469523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sec->tt[ei].status = Empty; 1470523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sec->tt[ei].n_tte2ec = 0; 1471523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe add_in_empty_tt_list(sno, ei); 14726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 1473523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe 1474523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sres = VG_(am_mmap_anon_float_valgrind) 1475523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe ( N_HTTES_PER_SECTOR * sizeof(TTEno) ); 1476523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (sr_isError(sres)) { 1477523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe VG_(out_of_memory_NORETURN)("initialiseSector(HTT)", 1478523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe N_HTTES_PER_SECTOR * sizeof(TTEno) ); 1479523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe /*NOTREACHED*/ 1480523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe } 1481523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sec->htt = (TTEno*)(Addr)sr_Res(sres); 1482523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe for (HTTno hi = 0; hi < N_HTTES_PER_SECTOR; hi++) 1483523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sec->htt[hi] = HTT_EMPTY; 148445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1485291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Set up the host_extents array. */ 1486291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sec->host_extents 1487291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj = VG_(newXA)(ttaux_malloc, "transtab.initialiseSector(host_extents)", 1488291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ttaux_free, 1489291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sizeof(HostExtent)); 1490291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 14915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Add an entry in the sector_search_order */ 14928e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 1493523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (sector_search_order[i] == INV_SNO) 14945d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 14955d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 14968e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(i >= 0 && i < n_sectors); 14975d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i] = sno; 14985d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 1499fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 1500738856f99eea33d86ce91dcb1d6cd5b151e307casewardj VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d\n", sno); 15016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1502fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } else { 15036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 15046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Sector has been used before. Dump the old contents. */ 15055e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1) 15061bb648db3172e70b73a8ca3a3f3c12ffc1dcd263sewardj VG_(dmsg)("transtab: " "recycle sector %d\n", sno); 15075e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe n_sectors_recycled++; 1508059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj 15096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tt != NULL); 15106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sec->tc_next != NULL); 15116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_dump_count += sec->tt_n_inuse; 15126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1513597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host = VexArch_INVALID; 1514597314210494248b4fbefd45525a748439629218sewardj VexArchInfo archinfo_host; 1515597314210494248b4fbefd45525a748439629218sewardj VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host)); 1516597314210494248b4fbefd45525a748439629218sewardj VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host ); 1517597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host = archinfo_host.endness; 1518291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 15196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Visit each just-about-to-be-abandoned translation. */ 15203a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("QQQ unlink-entire-sector: %d START\n", 15213a5322057616d0da214b9e0f897866e203c03e40philippe sno); 1522bece82eba7ba26398a673def2fa326341c4f8ef7philippe sec->empty_tt_list = HTT_EMPTY; 1523523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe for (TTEno ei = 0; ei < N_TTES_PER_SECTOR; ei++) { 1524523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (sec->tt[ei].status == InUse) { 1525523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(sec->tt[ei].n_tte2ec >= 1); 1526523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(sec->tt[ei].n_tte2ec <= 3); 1527523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe n_dump_osize += vge_osize(&sec->tt[ei].vge); 15283786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj /* Tell the tool too. */ 15290b9d74abd0a663b530d290b2b788ddeda46e5400sewardj if (VG_(needs).superblock_discards) { 15300b9d74abd0a663b530d290b2b788ddeda46e5400sewardj VG_TDICT_CALL( tool_discard_superblock_info, 1531523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sec->tt[ei].entry, 1532523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sec->tt[ei].vge ); 15333786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj } 1534597314210494248b4fbefd45525a748439629218sewardj unchain_in_preparation_for_deletion(arch_host, 1535523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe endness_host, sno, ei); 15366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 1537523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(sec->tt[ei].n_tte2ec == 0); 15386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 1539523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sec->tt[ei].status = Empty; 1540523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sec->tt[ei].n_tte2ec = 0; 1541523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe add_in_empty_tt_list(sno, ei); 15426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 1543523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe for (HTTno hi = 0; hi < N_HTTES_PER_SECTOR; hi++) 1544523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sec->htt[hi] = HTT_EMPTY; 1545bece82eba7ba26398a673def2fa326341c4f8ef7philippe 15463a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) VG_(printf)("QQQ unlink-entire-sector: %d END\n", 15473a5322057616d0da214b9e0f897866e203c03e40philippe sno); 15486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 15496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Free up the eclass structures. */ 1550aa29de28d79933eaa0a9c16ced4c52c6c1d54738philippe for (EClassNo e = 0; e < ECLASS_N; e++) { 1551d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (sec->ec2tte_size[e] == 0) { 1552d28615ccace5f9c79fca7713c73c19e0767f8f47philippe vg_assert(sec->ec2tte_used[e] == 0); 1553d28615ccace5f9c79fca7713c73c19e0767f8f47philippe vg_assert(sec->ec2tte[e] == NULL); 15546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 1555d28615ccace5f9c79fca7713c73c19e0767f8f47philippe vg_assert(sec->ec2tte[e] != NULL); 1556d28615ccace5f9c79fca7713c73c19e0767f8f47philippe ttaux_free(sec->ec2tte[e]); 1557d28615ccace5f9c79fca7713c73c19e0767f8f47philippe sec->ec2tte[e] = NULL; 1558d28615ccace5f9c79fca7713c73c19e0767f8f47philippe sec->ec2tte_size[e] = 0; 1559d28615ccace5f9c79fca7713c73c19e0767f8f47philippe sec->ec2tte_used[e] = 0; 1560fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 1561fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 15626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1563291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Empty out the host extents array. */ 1564291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec->host_extents != NULL); 1565291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(dropTailXA)(sec->host_extents, VG_(sizeXA)(sec->host_extents)); 1566291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(VG_(sizeXA)(sec->host_extents) == 0); 1567291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 15685d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Sanity check: ensure it is already in 15695d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[]. */ 1570523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno ix; 1571523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe for (ix = 0; ix < n_sectors; ix++) { 1572523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (sector_search_order[ix] == sno) 15735d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj break; 15745d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 1575523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(ix >= 0 && ix < n_sectors); 15765d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 1577fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 1578738856f99eea33d86ce91dcb1d6cd5b151e307casewardj VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d\n", sno); 15796c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 15804ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 15816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tc_next = sec->tc; 15826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt_n_inuse = 0; 1583fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1584fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 15855d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 15865d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj { Bool sane = sanity_check_sector_search_order(); 15875d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj vg_assert(sane); 15885d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 15896c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1590de4a1d01951937632098a6cda45859afa587a06fsewardj 1591fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC. The translation is temporarily 1592fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj in code[0 .. code_len-1]. 1593de4a1d01951937632098a6cda45859afa587a06fsewardj 1594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj pre: youngest_sector points to a valid (although possibly full) 1595fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. 1596fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 1597518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid VG_(add_to_transtab)( const VexGuestExtents* vge, 1598ddd61ff058f02059064e083a8accaefed23d5548florian Addr entry, 159944bd4465581ff28cef83bb39e684a489297d7b71florian Addr code, 160026412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj UInt code_len, 1601291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Bool is_self_checking, 1602291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Int offs_profInc, 1603597314210494248b4fbefd45525a748439629218sewardj UInt n_guest_instrs ) 160422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{ 1605523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe Int tcAvailQ, reqdQ, y; 16065f76de086a6d643db51e50a4e623df7dfc9b6161sewardj ULong *tcptr, *tcptr2; 1607fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UChar* srcP; 1608fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj UChar* dstP; 1609fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1610663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 1611fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(vge->n_used >= 1 && vge->n_used <= 3); 1612e808930793aeddc4cfd3e7a94b665913bec2566csewardj 1613e808930793aeddc4cfd3e7a94b665913bec2566csewardj /* 60000: should agree with N_TMPBUF in m_translate.c. */ 1614e808930793aeddc4cfd3e7a94b665913bec2566csewardj vg_assert(code_len > 0 && code_len < 60000); 1615fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1616b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj /* Generally stay sane */ 1617b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj vg_assert(n_guest_instrs < 200); /* it can be zero, tho */ 1618b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj 16193a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 1620ddd61ff058f02059064e083a8accaefed23d5548florian VG_(printf)("add_to_transtab(entry = 0x%lx, len = %u) ...\n", 1621fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj entry, code_len); 1622fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1623fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_count++; 1624fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_tsize += code_len; 1625fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_osize += vge_osize(vge); 162626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj if (is_self_checking) 162726412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj n_in_sc_count++; 1628fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1629fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj y = youngest_sector; 1630fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(isValidSector(y)); 1631fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1632fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[y].tc == NULL) 1633fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj initialiseSector(y); 1634fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1635fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Try putting the translation in this sector. */ 16365f76de086a6d643db51e50a4e623df7dfc9b6161sewardj reqdQ = (code_len + 7) >> 3; 1637fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1638fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Will it fit in tc? */ 1639fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tcAvailQ = ((ULong*)(§ors[y].tc[tc_sector_szQ])) 1640fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - ((ULong*)(sectors[y].tc_next)); 1641fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= 0); 1642fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ <= tc_sector_szQ); 1643fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1644fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (tcAvailQ < reqdQ 1645bece82eba7ba26398a673def2fa326341c4f8ef7philippe || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR) { 1646fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* No. So move on to the next sector. Either it's never been 1647fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj used before, in which case it will get its tt/tc allocated 1648fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj now, or it has been used before, in which case it is set to be 1649fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj empty, hence throwing out the oldest sector. */ 1650a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj vg_assert(tc_sector_szQ > 0); 1651059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj Int tt_loading_pct = (100 * sectors[y].tt_n_inuse) 1652bece82eba7ba26398a673def2fa326341c4f8ef7philippe / N_HTTES_PER_SECTOR; 1653059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj Int tc_loading_pct = (100 * (tc_sector_szQ - tcAvailQ)) 1654059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj / tc_sector_szQ; 16555e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1) { 1656059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj VG_(dmsg)("transtab: " 16571bb648db3172e70b73a8ca3a3f3c12ffc1dcd263sewardj "declare sector %d full " 16585e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe "(TT loading %2d%%, TC loading %2d%%, avg tce size %d)\n", 16595e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe y, tt_loading_pct, tc_loading_pct, 16605e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe 8 * (tc_sector_szQ - tcAvailQ)/sectors[y].tt_n_inuse); 1661059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj } 1662fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector++; 16638e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe if (youngest_sector >= n_sectors) 1664fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector = 0; 1665fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj y = youngest_sector; 1666fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj initialiseSector(y); 1667fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 166822854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 1669fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Be sure ... */ 1670fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tcAvailQ = ((ULong*)(§ors[y].tc[tc_sector_szQ])) 1671fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj - ((ULong*)(sectors[y].tc_next)); 1672fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= 0); 1673fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ <= tc_sector_szQ); 1674fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(tcAvailQ >= reqdQ); 1675bece82eba7ba26398a673def2fa326341c4f8ef7philippe vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR); 1676fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sectors[y].tt_n_inuse >= 0); 1677fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1678fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Copy into tc. */ 16795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj tcptr = sectors[y].tc_next; 16805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr >= §ors[y].tc[0]); 16815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr <= §ors[y].tc[tc_sector_szQ]); 1682fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 16835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj dstP = (UChar*)tcptr; 1684fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj srcP = (UChar*)code; 1685291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(memcpy)(dstP, srcP, code_len); 1686fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tc_next += reqdQ; 1687fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sectors[y].tt_n_inuse++; 1688fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1689fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* more paranoia */ 16905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj tcptr2 = sectors[y].tc_next; 16915f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr2 >= §ors[y].tc[0]); 16925f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(tcptr2 <= §ors[y].tc[tc_sector_szQ]); 1693fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1694fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find an empty tt slot, and use it. There must be such a slot 1695fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj since tt is never allowed to get completely full. */ 1696523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno tteix = get_empty_tt_slot(y); 1697523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEntry__init(§ors[y].tt[tteix]); 1698523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sectors[y].tt[tteix].status = InUse; 1699523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sectors[y].tt[tteix].tcptr = tcptr; 1700523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sectors[y].tt[tteix].usage.prof.count = 0; 1701523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sectors[y].tt[tteix].usage.prof.weight = 1702bece82eba7ba26398a673def2fa326341c4f8ef7philippe n_guest_instrs == 0 ? 1 : n_guest_instrs; 1703523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sectors[y].tt[tteix].vge = *vge; 1704523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sectors[y].tt[tteix].entry = entry; 1705fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1706bece82eba7ba26398a673def2fa326341c4f8ef7philippe // Point an htt entry to the tt slot 1707523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe HTTno htti = HASH_TT(entry); 1708bece82eba7ba26398a673def2fa326341c4f8ef7philippe vg_assert(htti >= 0 && htti < N_HTTES_PER_SECTOR); 1709bece82eba7ba26398a673def2fa326341c4f8ef7philippe while (True) { 1710bece82eba7ba26398a673def2fa326341c4f8ef7philippe if (sectors[y].htt[htti] == HTT_EMPTY 1711bece82eba7ba26398a673def2fa326341c4f8ef7philippe || sectors[y].htt[htti] == HTT_DELETED) 1712bece82eba7ba26398a673def2fa326341c4f8ef7philippe break; 1713bece82eba7ba26398a673def2fa326341c4f8ef7philippe htti++; 1714bece82eba7ba26398a673def2fa326341c4f8ef7philippe if (htti >= N_HTTES_PER_SECTOR) 1715bece82eba7ba26398a673def2fa326341c4f8ef7philippe htti = 0; 1716bece82eba7ba26398a673def2fa326341c4f8ef7philippe } 1717523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sectors[y].htt[htti] = tteix; 1718bece82eba7ba26398a673def2fa326341c4f8ef7philippe 1719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Patch in the profile counter location, if necessary. */ 1720291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (offs_profInc != -1) { 1721291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(offs_profInc >= 0 && offs_profInc < code_len); 1722597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host = VexArch_INVALID; 1723597314210494248b4fbefd45525a748439629218sewardj VexArchInfo archinfo_host; 1724597314210494248b4fbefd45525a748439629218sewardj VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host)); 1725597314210494248b4fbefd45525a748439629218sewardj VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host ); 1726597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host = archinfo_host.endness; 1727291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VexInvalRange vir 1728597314210494248b4fbefd45525a748439629218sewardj = LibVEX_PatchProfInc( arch_host, endness_host, 1729291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj dstP + offs_profInc, 1730523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe §ors[y].tt[tteix].usage.prof.count ); 1731291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( (void*)vir.start, vir.len ); 1732291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 1733291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 1734291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( dstP, code_len ); 1735291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 1736291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Add this entry to the host_extents map, checking that we're 1737291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj adding in order. */ 1738291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj { HostExtent hx; 1739291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj hx.start = (UChar*)tcptr; 1740291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj hx.len = code_len; 1741523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe hx.tteNo = tteix; 1742291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(hx.len > 0); /* bsearch fails w/ zero length entries */ 1743291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj XArray* hx_array = sectors[y].host_extents; 1744291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(hx_array); 1745291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj Word n = VG_(sizeXA)(hx_array); 1746291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (n > 0) { 1747291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj HostExtent* hx_prev = (HostExtent*)VG_(indexXA)(hx_array, n-1); 1748291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(hx_prev->start + hx_prev->len <= hx.start); 1749291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 1750291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(addToXA)(hx_array, &hx); 17513a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) 17523a5322057616d0da214b9e0f897866e203c03e40philippe VG_(printf)("... hx.start 0x%p hx.len %u sector %d ttslot %d\n", 1753523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe hx.start, hx.len, y, tteix); 1754291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj } 1755291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 17566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Update the fast-cache. */ 1757291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj setFastCacheEntry( entry, tcptr ); 17586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 17596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Note the eclass numbers for this translation. */ 1760523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe upd_eclasses_after_add( §ors[y], tteix ); 176122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj} 176222854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj 1763fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1764fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address. If 1765fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj requested, a successful search can also cause the fast-caches to be 1766523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe updated. 1767fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/ 176844bd4465581ff28cef83bb39e684a489297d7b71florianBool VG_(search_transtab) ( /*OUT*/Addr* res_hcode, 1769523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe /*OUT*/SECno* res_sNo, 1770523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe /*OUT*/TTEno* res_tteNo, 1771ddd61ff058f02059064e083a8accaefed23d5548florian Addr guest_addr, 1772fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj Bool upd_cache ) 17736c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1774523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno i, sno; 1775523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe HTTno j, k, kstart; 1776523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno tti; 1777663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 1778663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 1779fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find the initial probe point just once. It will be the same in 1780fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj all sectors and avoids multiple expensive % operations. */ 1781fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_full_lookups++; 1782fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj kstart = HASH_TT(guest_addr); 1783bece82eba7ba26398a673def2fa326341c4f8ef7philippe vg_assert(kstart >= 0 && kstart < N_HTTES_PER_SECTOR); 1784fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 17855d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* Search in all the sectors,using sector_search_order[] as a 17865d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj heuristic guide as to what order to visit the sectors. */ 17878e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (i = 0; i < n_sectors; i++) { 1788fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 17895d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sno = sector_search_order[i]; 1790523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe if (UNLIKELY(sno == INV_SNO)) 17915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj return False; /* run out of sectors to search */ 1792fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1793fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = kstart; 1794bece82eba7ba26398a673def2fa326341c4f8ef7philippe for (j = 0; j < N_HTTES_PER_SECTOR; j++) { 1795fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_lookup_probes++; 1796bece82eba7ba26398a673def2fa326341c4f8ef7philippe tti = sectors[sno].htt[k]; 1797bece82eba7ba26398a673def2fa326341c4f8ef7philippe if (tti < N_TTES_PER_SECTOR 1798bece82eba7ba26398a673def2fa326341c4f8ef7philippe && sectors[sno].tt[tti].entry == guest_addr) { 1799fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* found it */ 1800fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (upd_cache) 1801fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj setFastCacheEntry( 1802bece82eba7ba26398a673def2fa326341c4f8ef7philippe guest_addr, sectors[sno].tt[tti].tcptr ); 1803291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (res_hcode) 1804bece82eba7ba26398a673def2fa326341c4f8ef7philippe *res_hcode = (Addr)sectors[sno].tt[tti].tcptr; 1805291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (res_sNo) 1806291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj *res_sNo = sno; 1807291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj if (res_tteNo) 1808bece82eba7ba26398a673def2fa326341c4f8ef7philippe *res_tteNo = tti; 18095d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj /* pull this one one step closer to the front. For large 18105d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj apps this more or less halves the number of required 18115d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj probes. */ 18125d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj if (i > 0) { 18135d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj Int tmp = sector_search_order[i-1]; 18145d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i-1] = sector_search_order[i]; 18155d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj sector_search_order[i] = tmp; 18165d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj } 1817fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1818fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 1819bece82eba7ba26398a673def2fa326341c4f8ef7philippe // tti is HTT_EMPTY or HTT_DELETED or not the entry of guest_addr 1820bece82eba7ba26398a673def2fa326341c4f8ef7philippe if (sectors[sno].htt[k] == HTT_EMPTY) 1821fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; /* not found in this sector */ 1822fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k++; 1823bece82eba7ba26398a673def2fa326341c4f8ef7philippe if (k == N_HTTES_PER_SECTOR) 1824fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj k = 0; 18256c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 1826fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1827fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* If we fall off the end, all entries are InUse and not 1828fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj matching, or Deleted. In any case we did not find it in this 1829fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj sector. */ 18306c3769f487145a08c01b58d6e5db3ba274062ad4sewardj } 1831fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1832fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Not found in any sector. */ 1833fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 18346c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1835de4a1d01951937632098a6cda45859afa587a06fsewardj 1836de4a1d01951937632098a6cda45859afa587a06fsewardj 18376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 18386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Delete translations. ---*/ 18396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/ 18406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 18410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* forward */ 1842ddd61ff058f02059064e083a8accaefed23d5548florianstatic void unredir_discard_translations( Addr, ULong ); 18430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 18446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Stuff for deleting translations which intersect with a given 18456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj address range. Unfortunately, to make this run at a reasonable 18466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj speed, it is complex. */ 1847fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 1848fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline 1849ddd61ff058f02059064e083a8accaefed23d5548florianBool overlap1 ( Addr s1, ULong r1, Addr s2, ULong r2 ) 18506c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1851ddd61ff058f02059064e083a8accaefed23d5548florian Addr e1 = s1 + r1 - 1; 1852ddd61ff058f02059064e083a8accaefed23d5548florian Addr e2 = s2 + r2 - 1; 1853fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (e1 < s2 || e2 < s1) 1854fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1855fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 18566c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1857de4a1d01951937632098a6cda45859afa587a06fsewardj 1858fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline 1859ddd61ff058f02059064e083a8accaefed23d5548florianBool overlaps ( Addr start, ULong range, const VexGuestExtents* vge ) 18606c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 1861ddd61ff058f02059064e083a8accaefed23d5548florian if (overlap1(start, range, vge->base[0], vge->len[0])) 1862fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1863fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (vge->n_used < 2) 1864fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1865ddd61ff058f02059064e083a8accaefed23d5548florian if (overlap1(start, range, vge->base[1], vge->len[1])) 1866fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1867fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (vge->n_used < 3) 1868fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 1869ddd61ff058f02059064e083a8accaefed23d5548florian if (overlap1(start, range, vge->base[2], vge->len[2])) 1870fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return True; 1871fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return False; 18726c3769f487145a08c01b58d6e5db3ba274062ad4sewardj} 1873de4a1d01951937632098a6cda45859afa587a06fsewardj 1874de4a1d01951937632098a6cda45859afa587a06fsewardj 18756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete a tt entry, and update all the eclass data accordingly. */ 18766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1877523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic void delete_tte ( /*MOD*/Sector* sec, SECno secNo, TTEno tteno, 1878597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host, VexEndness endness_host ) 18796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 1880d28615ccace5f9c79fca7713c73c19e0767f8f47philippe Int i, ec_idx; 1881d28615ccace5f9c79fca7713c73c19e0767f8f47philippe EClassNo ec_num; 18826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 18836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1884291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* sec and secNo are mutually redundant; cross-check. */ 1885291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj vg_assert(sec == §ors[secNo]); 1886291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 18876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR); 18886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 18896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 18906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->n_tte2ec >= 1 && tte->n_tte2ec <= 3); 18916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 1892291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Unchain .. */ 1893597314210494248b4fbefd45525a748439629218sewardj unchain_in_preparation_for_deletion(arch_host, endness_host, secNo, tteno); 1894291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 18956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Deal with the ec-to-tte links first. */ 18966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < tte->n_tte2ec; i++) { 1897d28615ccace5f9c79fca7713c73c19e0767f8f47philippe ec_num = tte->tte2ec_ec[i]; 18986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec_idx = tte->tte2ec_ix[i]; 18996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_num >= 0 && ec_num < ECLASS_N); 19006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_idx >= 0); 19016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec_idx < sec->ec2tte_used[ec_num]); 19026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Assert that the two links point at each other. */ 1903523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(sec->ec2tte[ec_num][ec_idx] == tteno); 19046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* "delete" the pointer back to here. */ 19056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->ec2tte[ec_num][ec_idx] = EC2TTE_DELETED; 19066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Now fix up this TTEntry. */ 1909bece82eba7ba26398a673def2fa326341c4f8ef7philippe /* Mark the entry as deleted in htt. 1910bece82eba7ba26398a673def2fa326341c4f8ef7philippe Note: we could avoid the below hash table search by 1911bece82eba7ba26398a673def2fa326341c4f8ef7philippe adding a reference from tte to its hash position in tt. */ 1912523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe HTTno j; 1913523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe HTTno k = HASH_TT(tte->entry); 1914523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(k >= 0 && k < N_HTTES_PER_SECTOR); 1915bece82eba7ba26398a673def2fa326341c4f8ef7philippe for (j = 0; j < N_HTTES_PER_SECTOR; j++) { 1916bece82eba7ba26398a673def2fa326341c4f8ef7philippe if (sec->htt[k] == tteno) 1917bece82eba7ba26398a673def2fa326341c4f8ef7philippe break; 1918bece82eba7ba26398a673def2fa326341c4f8ef7philippe k++; 1919bece82eba7ba26398a673def2fa326341c4f8ef7philippe if (k == N_HTTES_PER_SECTOR) 1920bece82eba7ba26398a673def2fa326341c4f8ef7philippe k = 0; 1921bece82eba7ba26398a673def2fa326341c4f8ef7philippe } 1922bece82eba7ba26398a673def2fa326341c4f8ef7philippe vg_assert(j < N_HTTES_PER_SECTOR); 1923bece82eba7ba26398a673def2fa326341c4f8ef7philippe sec->htt[k] = HTT_DELETED; 19246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->status = Deleted; 19256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->n_tte2ec = 0; 1926bece82eba7ba26398a673def2fa326341c4f8ef7philippe add_in_empty_tt_list(secNo, tteno); 19276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Stats .. */ 19296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec->tt_n_inuse--; 19306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_disc_count++; 19316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj n_disc_osize += vge_osize(&tte->vge); 19326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Tell the tool too. */ 19340b9d74abd0a663b530d290b2b788ddeda46e5400sewardj if (VG_(needs).superblock_discards) { 19350b9d74abd0a663b530d290b2b788ddeda46e5400sewardj VG_TDICT_CALL( tool_discard_superblock_info, 19364ba057cce1d81a949f5a899b5abb99e90a731bccsewardj tte->entry, 19376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte->vge ); 19386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 19406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, but 19436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj only consider translations in the specified eclass. */ 19446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 1946523b5b8ca67d2063afd02342d0138b0dc0ed6706philippeBool delete_translations_in_sector_eclass ( /*MOD*/Sector* sec, SECno secNo, 1947ddd61ff058f02059064e083a8accaefed23d5548florian Addr guest_start, ULong range, 1948d28615ccace5f9c79fca7713c73c19e0767f8f47philippe EClassNo ec, 1949597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host, 1950597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host ) 19516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 19526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Int i; 1953523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno tteno; 19546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeld = False; 19556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 19566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_N); 19586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < sec->ec2tte_used[ec]; i++) { 19606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tteno = sec->ec2tte[ec][i]; 19626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tteno == EC2TTE_DELETED) { 19636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* already deleted */ 19646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 19656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tteno < N_TTES_PER_SECTOR); 19686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[tteno]; 19706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(tte->status == InUse); 19716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (overlaps( guest_start, range, &tte->vge )) { 19736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeld = True; 1974523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe delete_tte( sec, secNo, tteno, arch_host, endness_host ); 19756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 19786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return anyDeld; 19806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 19816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, the 19846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj slow way, by inspecting all translations in sec. */ 19856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic 1987523b5b8ca67d2063afd02342d0138b0dc0ed6706philippeBool delete_translations_in_sector ( /*MOD*/Sector* sec, SECno secNo, 1988ddd61ff058f02059064e083a8accaefed23d5548florian Addr guest_start, ULong range, 1989597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host, 1990597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host ) 19916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{ 1992523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno i; 1993523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe Bool anyDeld = False; 19946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 19956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 19966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tt[i].status == InUse 19976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj && overlaps( guest_start, range, &sec->tt[i].vge )) { 19986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeld = True; 1999597314210494248b4fbefd45525a748439629218sewardj delete_tte( sec, secNo, i, arch_host, endness_host ); 20006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 20016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 20026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return anyDeld; 20046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj} 20056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 2007ddd61ff058f02059064e083a8accaefed23d5548florianvoid VG_(discard_translations) ( Addr guest_start, ULong range, 20081636d33c13958b9c0e7d3059cdd5005746418eb2florian const HChar* who ) 20096c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 20106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Sector* sec; 2011523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno sno; 2012d28615ccace5f9c79fca7713c73c19e0767f8f47philippe EClassNo ec; 20136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool anyDeleted = False; 20146c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 2015663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(init_done); 2016663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 2017a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj VG_(debugLog)(2, "transtab", 2018ddd61ff058f02059064e083a8accaefed23d5548florian "discard_translations(0x%lx, %llu) req by %s\n", 201945f4e7c91119c7d01a59f5e827c67841632c9314sewardj guest_start, range, who ); 202045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 20216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Pre-deletion sanity check */ 20226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (VG_(clo_sanity_level >= 4)) { 20236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane = sanity_check_all_sectors(); 20246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sane); 20256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 20266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (range == 0) 20286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj return; 20296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 2030597314210494248b4fbefd45525a748439629218sewardj VexArch arch_host = VexArch_INVALID; 2031597314210494248b4fbefd45525a748439629218sewardj VexArchInfo archinfo_host; 2032597314210494248b4fbefd45525a748439629218sewardj VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host)); 2033597314210494248b4fbefd45525a748439629218sewardj VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host ); 2034597314210494248b4fbefd45525a748439629218sewardj VexEndness endness_host = archinfo_host.endness; 2035291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj 20366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* There are two different ways to do this. 20376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj If the range fits within a single address-range equivalence 20396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class, as will be the case for a cache line sized invalidation, 20406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj then we only have to inspect the set of translations listed in 20416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj that equivalence class, and also in the "sin-bin" equivalence 20426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class ECLASS_MISC. 20436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Otherwise, the invalidation is of a larger range and probably 20456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj results from munmap. In this case it's (probably!) faster just 20466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj to inspect all translations, dump those we don't want, and 20476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj regenerate the equivalence class information (since modifying it 20486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj in-situ is even more expensive). 20496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj */ 20506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* First off, figure out if the range falls within a single class, 20526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj and if so which one. */ 20536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec = ECLASS_MISC; 20556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (range < (1ULL << ECLASS_SHIFT)) 20566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj ec = range_to_eclass( guest_start, (UInt)range ); 20576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* if ec is ECLASS_MISC then we aren't looking at just a single 20596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj class, so use the slow scheme. Else use the fast scheme, 20606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj examining 'ec' and ECLASS_MISC. */ 20616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (ec != ECLASS_MISC) { 20636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(2, "transtab", 20656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj " FAST, ec = %d\n", ec); 20666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Fast scheme */ 20686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(ec >= 0 && ec < ECLASS_MISC); 20696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20708e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 20716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 20726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 20736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 20746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector_eclass( 2075291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sec, sno, guest_start, range, ec, 2076597314210494248b4fbefd45525a748439629218sewardj arch_host, endness_host 2077291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 20786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector_eclass( 2079291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj sec, sno, guest_start, range, ECLASS_MISC, 2080597314210494248b4fbefd45525a748439629218sewardj arch_host, endness_host 2081291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj ); 20826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 20836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } else { 20856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* slow scheme */ 20876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(debugLog)(2, "transtab", 20896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj " SLOW, ec = %d\n", ec); 20906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 20918e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 20926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 20936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 20946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 20956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj anyDeleted |= delete_translations_in_sector( 2096597314210494248b4fbefd45525a748439629218sewardj sec, sno, guest_start, range, 2097597314210494248b4fbefd45525a748439629218sewardj arch_host, endness_host 2098597314210494248b4fbefd45525a748439629218sewardj ); 20996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 21006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 2101de4a1d01951937632098a6cda45859afa587a06fsewardj } 2102de4a1d01951937632098a6cda45859afa587a06fsewardj 2103fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (anyDeleted) 2104fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 21056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 21060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* don't forget the no-redir cache */ 21070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_discard_translations( guest_start, range ); 21080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* Post-deletion sanity check */ 21106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (VG_(clo_sanity_level >= 4)) { 2111523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno i; 21126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj TTEntry* tte; 21136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj Bool sane = sanity_check_all_sectors(); 21146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(sane); 21156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj /* But now, also check the requested address range isn't 21166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj present anywhere. */ 21178e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 21186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj sec = §ors[sno]; 21196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (sec->tc == NULL) 21206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 21216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 21226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj tte = &sec->tt[i]; 21236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj if (tte->status != InUse) 21246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj continue; 21256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj vg_assert(!overlaps( guest_start, range, &tte->vge )); 21266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 21276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 21286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 2129fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 21306c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 21315f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian/* Whether or not tools may discard translations. */ 21325f1aeb620eb5a3aab662f8b949b031a77a0d14feflorianBool VG_(ok_to_discard_translations) = False; 21335f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian 21345f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian/* This function is exported to tools which can use it to discard 21355f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian translations, provided it is safe to do so. */ 21365f1aeb620eb5a3aab662f8b949b031a77a0d14feflorianvoid VG_(discard_translations_safely) ( Addr start, SizeT len, 21375f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian const HChar* who ) 21385f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian{ 21395f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian vg_assert(VG_(ok_to_discard_translations)); 21405f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian VG_(discard_translations)(start, len, who); 21415f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian} 21426c3769f487145a08c01b58d6e5db3ba274062ad4sewardj 2143fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 21440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*--- AUXILIARY: the unredirected TT/TC ---*/ 21450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/ 21460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* A very simple translation cache which holds a small number of 21480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredirected translations. This is completely independent of the 21490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj main tt/tc structures. When unredir_tc or unredir_tt becomes full, 21500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj both structures are simply dumped and we start over. 21510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Since these translations are unredirected, the search key is (by 21530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj definition) the first address entry in the .vge field. */ 21540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Sized to hold 500 translations of average size 1000 bytes. */ 21560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define UNREDIR_SZB 1000 21580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TT 500 21600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TCQ (N_UNREDIR_TT * UNREDIR_SZB / sizeof(ULong)) 21610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21620ec07f32bbbb209d749b9974408e6f025ad40b31sewardjtypedef 21630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj struct { 21640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj VexGuestExtents vge; 21650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Addr hcode; 21660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Bool inUse; 21670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 21680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj UTCEntry; 21690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* We just allocate forwards in _tc, never deleting. */ 217178c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic ULong *unredir_tc; 217278c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic Int unredir_tc_used = N_UNREDIR_TCQ; 21730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Slots in _tt can come into use and out again (.inUse). 21750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Nevertheless _tt_highwater is maintained so that invalidations 21760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj don't have to scan all the slots when only a few are in use. 21770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj _tt_highwater holds the index of the highest ever allocated 21780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj slot. */ 21790ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic UTCEntry unredir_tt[N_UNREDIR_TT]; 21800ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Int unredir_tt_highwater; 21810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 21830ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void init_unredir_tt_tc ( void ) 21840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 21850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 218678c0c09d429c95115e826ef769ecaa6cff2ac338tom if (unredir_tc == NULL) { 2187cda2f0fbda4c4b2644babc830244be8aed95de1dnjn SysRes sres = VG_(am_mmap_anon_float_valgrind) 2188cda2f0fbda4c4b2644babc830244be8aed95de1dnjn ( N_UNREDIR_TT * UNREDIR_SZB ); 2189cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 2190cda2f0fbda4c4b2644babc830244be8aed95de1dnjn VG_(out_of_memory_NORETURN)("init_unredir_tt_tc", 2191cda2f0fbda4c4b2644babc830244be8aed95de1dnjn N_UNREDIR_TT * UNREDIR_SZB); 219278c0c09d429c95115e826ef769ecaa6cff2ac338tom /*NOTREACHED*/ 219378c0c09d429c95115e826ef769ecaa6cff2ac338tom } 219444bd4465581ff28cef83bb39e684a489297d7b71florian unredir_tc = (ULong *)(Addr)sr_Res(sres); 219578c0c09d429c95115e826ef769ecaa6cff2ac338tom } 21960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tc_used = 0; 21970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) 21980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = False; 21990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt_highwater = -1; 22000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 22010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Do a sanity check; return False on failure. */ 22030ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void ) 22040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 22050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 22060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt_highwater < -1) return False; 22070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt_highwater >= N_UNREDIR_TT) return False; 22080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = unredir_tt_highwater+1; i < N_UNREDIR_TT; i++) 22100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].inUse) 22110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return False; 22120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tc_used < 0) return False; 22140ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tc_used > N_UNREDIR_TCQ) return False; 22150ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22160ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return True; 22170ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 22180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22190ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22200ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Add an UNREDIRECTED translation of vge to TT/TC. The translation 22210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj is temporarily in code[0 .. code_len-1]. 22220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj*/ 2223518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid VG_(add_to_unredir_transtab)( const VexGuestExtents* vge, 2224ddd61ff058f02059064e083a8accaefed23d5548florian Addr entry, 222544bd4465581ff28cef83bb39e684a489297d7b71florian Addr code, 22261dcee097db02f9ef3ba355162c4373d90d0e895cnjn UInt code_len ) 22270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 22280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i, j, code_szQ; 22290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj HChar *srcP, *dstP; 22300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(sanity_check_redir_tt_tc()); 22320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* This is the whole point: it's not redirected! */ 22340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(entry == vge->base[0]); 22350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* How many unredir_tt slots are needed */ 22370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj code_szQ = (code_len + 7) / 8; 22380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* Look for an empty unredir_tc slot */ 22400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) 22410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (!unredir_tt[i].inUse) 22420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj break; 22430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (i >= N_UNREDIR_TT || code_szQ > (N_UNREDIR_TCQ - unredir_tc_used)) { 22450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* It's full; dump everything we currently have */ 22460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj init_unredir_tt_tc(); 22470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj i = 0; 22480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 22490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used >= 0); 22510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used <= N_UNREDIR_TCQ); 22520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(code_szQ > 0); 22530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(code_szQ + unredir_tc_used <= N_UNREDIR_TCQ); 22540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(i >= 0 && i < N_UNREDIR_TT); 22550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tt[i].inUse == False); 22560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (i > unredir_tt_highwater) 22580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt_highwater = i; 22590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj dstP = (HChar*)&unredir_tc[unredir_tc_used]; 22610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj srcP = (HChar*)code; 22620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (j = 0; j < code_len; j++) 22630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj dstP[j] = srcP[j]; 22640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 2265291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj VG_(invalidate_icache)( dstP, code_len ); 2266c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj 22670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = True; 22680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].vge = *vge; 22690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].hcode = (Addr)dstP; 22700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tc_used += code_szQ; 22720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used >= 0); 22730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(unredir_tc_used <= N_UNREDIR_TCQ); 22740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(&dstP[code_len] <= (HChar*)&unredir_tc[unredir_tc_used]); 22760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 22770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 227844bd4465581ff28cef83bb39e684a489297d7b71florianBool VG_(search_unredir_transtab) ( /*OUT*/Addr* result, 2279ddd61ff058f02059064e083a8accaefed23d5548florian Addr guest_addr ) 22800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 22810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 22820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i < N_UNREDIR_TT; i++) { 22830ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (!unredir_tt[i].inUse) 22840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj continue; 22850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].vge.base[0] == guest_addr) { 2286ddd61ff058f02059064e083a8accaefed23d5548florian *result = unredir_tt[i].hcode; 22870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return True; 22880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 22890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 22900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj return False; 22910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 22920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 2293ddd61ff058f02059064e083a8accaefed23d5548florianstatic void unredir_discard_translations( Addr guest_start, ULong range ) 22940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{ 22950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj Int i; 22960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj vg_assert(sanity_check_redir_tt_tc()); 22980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 22990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj for (i = 0; i <= unredir_tt_highwater; i++) { 23000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj if (unredir_tt[i].inUse 23010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj && overlaps( guest_start, range, &unredir_tt[i].vge)) 23020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj unredir_tt[i].inUse = False; 23030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj } 23040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj} 23050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 23060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 23070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/ 2308fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation. ---*/ 2309fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2311fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void ) 23126c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{ 2313a11ec17946cdbafb336e9121b64961c0633af2e7sewardj Int i, avg_codeszQ; 2314de4a1d01951937632098a6cda45859afa587a06fsewardj 2315663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj vg_assert(!init_done); 2316663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj init_done = True; 2317663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj 2318fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Otherwise lots of things go wrong... */ 2319fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj vg_assert(sizeof(ULong) == 8); 2320523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(sizeof(TTEno) == sizeof(HTTno)); 2321523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(sizeof(TTEno) == 2); 2322523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(N_TTES_PER_SECTOR <= N_HTTES_PER_SECTOR); 2323523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(N_HTTES_PER_SECTOR < INV_TTE); 2324523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(N_HTTES_PER_SECTOR < EC2TTE_DELETED); 2325523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(N_HTTES_PER_SECTOR < HTT_EMPTY); 23265f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache entries really are 2 words long */ 23275f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof(Addr) == sizeof(void*)); 23285f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(sizeof(FastCacheEntry) == 2 * sizeof(Addr)); 23295f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache entries are packed back-to-back with no spaces */ 2330523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe vg_assert(sizeof( VG_(tt_fast) ) 2331523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe == VG_TT_FAST_SIZE * sizeof(FastCacheEntry)); 23325f76de086a6d643db51e50a4e623df7dfc9b6161sewardj /* check fast cache is aligned as we requested. Not fatal if it 23335f76de086a6d643db51e50a4e623df7dfc9b6161sewardj isn't, but we might as well make sure. */ 23345f76de086a6d643db51e50a4e623df7dfc9b6161sewardj vg_assert(VG_IS_16_ALIGNED( ((Addr) & VG_(tt_fast)[0]) )); 2335de4a1d01951937632098a6cda45859afa587a06fsewardj 2336fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (VG_(clo_verbosity) > 2) 2337fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2338fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj "TT/TC: VG_(init_tt_tc) " 2339738856f99eea33d86ce91dcb1d6cd5b151e307casewardj "(startup of code management)\n"); 2340fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2341fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Figure out how big each tc area should be. */ 2342924c852b5883a7b42298dc8c7542116bd9a8a485philippe if (VG_(clo_avg_transtab_entry_size) == 0) 2343924c852b5883a7b42298dc8c7542116bd9a8a485philippe avg_codeszQ = (VG_(details).avg_translation_sizeB + 7) / 8; 2344924c852b5883a7b42298dc8c7542116bd9a8a485philippe else 2345924c852b5883a7b42298dc8c7542116bd9a8a485philippe avg_codeszQ = (VG_(clo_avg_transtab_entry_size) + 7) / 8; 2346bece82eba7ba26398a673def2fa326341c4f8ef7philippe tc_sector_szQ = N_TTES_PER_SECTOR * (1 + avg_codeszQ); 2347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Ensure the calculated value is not way crazy. */ 2349bece82eba7ba26398a673def2fa326341c4f8ef7philippe vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR); 2350bece82eba7ba26398a673def2fa326341c4f8ef7philippe vg_assert(tc_sector_szQ <= 100 * N_TTES_PER_SECTOR); 2351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 23528e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe n_sectors = VG_(clo_num_transtab_sectors); 23538e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(n_sectors >= MIN_N_SECTORS); 23548e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe vg_assert(n_sectors <= MAX_N_SECTORS); 23558e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe 2356a11ec17946cdbafb336e9121b64961c0633af2e7sewardj /* Initialise the sectors, even the ones we aren't going to use. 2357a11ec17946cdbafb336e9121b64961c0633af2e7sewardj Set all fields to zero. */ 2358fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj youngest_sector = 0; 2359a11ec17946cdbafb336e9121b64961c0633af2e7sewardj for (i = 0; i < MAX_N_SECTORS; i++) 2360a11ec17946cdbafb336e9121b64961c0633af2e7sewardj VG_(memset)(§ors[i], 0, sizeof(sectors[i])); 23614ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 2362a11ec17946cdbafb336e9121b64961c0633af2e7sewardj /* Initialise the sector_search_order hint table, including the 2363a11ec17946cdbafb336e9121b64961c0633af2e7sewardj entries we aren't going to use. */ 2364a11ec17946cdbafb336e9121b64961c0633af2e7sewardj for (i = 0; i < MAX_N_SECTORS; i++) 2365523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe sector_search_order[i] = INV_SNO; 23665d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj 2367291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj /* Initialise the fast cache. */ 2368fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj invalidateFastCache(); 2369fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 23700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj /* and the unredir tt/tc */ 23710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj init_unredir_tt_tc(); 23720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj 23738e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe if (VG_(clo_verbosity) > 2 || VG_(clo_stats) 23748e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe || VG_(debugLog_getLevel) () >= 2) { 2375fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2376924c852b5883a7b42298dc8c7542116bd9a8a485philippe "TT/TC: cache: %s--avg-transtab-entry-size=%d, " 2377924c852b5883a7b42298dc8c7542116bd9a8a485philippe "%stool provided default %d\n", 2378924c852b5883a7b42298dc8c7542116bd9a8a485philippe VG_(clo_avg_transtab_entry_size) == 0 ? "ignoring " : "using ", 2379924c852b5883a7b42298dc8c7542116bd9a8a485philippe VG_(clo_avg_transtab_entry_size), 2380924c852b5883a7b42298dc8c7542116bd9a8a485philippe VG_(clo_avg_transtab_entry_size) == 0 ? "using " : "ignoring ", 2381924c852b5883a7b42298dc8c7542116bd9a8a485philippe VG_(details).avg_translation_sizeB); 2382924c852b5883a7b42298dc8c7542116bd9a8a485philippe VG_(message)(Vg_DebugMsg, 2383bece82eba7ba26398a673def2fa326341c4f8ef7philippe "TT/TC: cache: %d sectors of %d bytes each = %d total TC\n", 23848e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe n_sectors, 8 * tc_sector_szQ, 23858e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe n_sectors * 8 * tc_sector_szQ ); 2386fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2387bece82eba7ba26398a673def2fa326341c4f8ef7philippe "TT/TC: table: %d tables[%d] of %d bytes each = %d total TT\n", 2388bece82eba7ba26398a673def2fa326341c4f8ef7philippe n_sectors, N_TTES_PER_SECTOR, 2389bece82eba7ba26398a673def2fa326341c4f8ef7philippe (int)(N_TTES_PER_SECTOR * sizeof(TTEntry)), 23908e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe (int)(n_sectors * N_TTES_PER_SECTOR * sizeof(TTEntry))); 23918e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe VG_(message)(Vg_DebugMsg, 2392bece82eba7ba26398a673def2fa326341c4f8ef7philippe "TT/TC: table: %d tt entries each = %d total tt entries\n", 2393bece82eba7ba26398a673def2fa326341c4f8ef7philippe N_TTES_PER_SECTOR, n_sectors * N_TTES_PER_SECTOR); 2394bece82eba7ba26398a673def2fa326341c4f8ef7philippe VG_(message)(Vg_DebugMsg, 2395bece82eba7ba26398a673def2fa326341c4f8ef7philippe "TT/TC: table: %d htt[%d] of %d bytes each = %d total HTT" 2396bece82eba7ba26398a673def2fa326341c4f8ef7philippe " (htt[%d] %d%% max occup)\n", 2397bece82eba7ba26398a673def2fa326341c4f8ef7philippe n_sectors, N_HTTES_PER_SECTOR, 2398523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe (int)(N_HTTES_PER_SECTOR * sizeof(TTEno)), 2399523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe (int)(n_sectors * N_HTTES_PER_SECTOR * sizeof(TTEno)), 2400bece82eba7ba26398a673def2fa326341c4f8ef7philippe N_HTTES_PER_SECTOR, SECTOR_TT_LIMIT_PERCENT); 2401fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2402de4a1d01951937632098a6cda45859afa587a06fsewardj} 2403de4a1d01951937632098a6cda45859afa587a06fsewardj 24044ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 2405fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2406fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics. ---*/ 2407fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2408fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 240924f33d792e877ceedd68d6f74f40bba34fd72ce5philippestatic Double safe_idiv( ULong a, ULong b ) 241092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{ 241124f33d792e877ceedd68d6f74f40bba34fd72ce5philippe return (b == 0 ? 0 : (Double)a / (Double)b); 241292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote} 241392e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote 2414fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void ) 2415fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 2416fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj return n_in_count; 2417fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj} 2418fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2419fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void ) 242092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{ 242192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 2422738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " tt/tc: %'llu tt lookups requiring %'llu probes\n", 2423fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_full_lookups, n_lookup_probes ); 242492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 2425738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " tt/tc: %'llu fast-cache updates, %'llu flushes\n", 2426fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_fast_updates, n_fast_flushes ); 2427fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 242892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 2429a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart " transtab: new %'lld " 243024f33d792e877ceedd68d6f74f40bba34fd72ce5philippe "(%'llu -> %'llu; ratio %3.1f) [%'llu scs] " 24315e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe "avg tce size %d\n", 2432fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_in_count, n_in_osize, n_in_tsize, 243324f33d792e877ceedd68d6f74f40bba34fd72ce5philippe safe_idiv(n_in_tsize, n_in_osize), 24345e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe n_in_sc_count, 2435900c5357f377ae0cf0dba255e660b1c2df5d93bcphilippe (int) (n_in_tsize / (n_in_count ? n_in_count : 1))); 243692e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote VG_(message)(Vg_DebugMsg, 24375e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe " transtab: dumped %'llu (%'llu -> ?" "?) " 24385e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe "(sectors recycled %'llu)\n", 24395e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe n_dump_count, n_dump_osize, n_sectors_recycled ); 2440fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj VG_(message)(Vg_DebugMsg, 2441738856f99eea33d86ce91dcb1d6cd5b151e307casewardj " transtab: discarded %'llu (%'llu -> ?" "?)\n", 2442fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj n_disc_count, n_disc_osize ); 24436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj 24443a5322057616d0da214b9e0f897866e203c03e40philippe if (DEBUG_TRANSTAB) { 24456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n"); 2446d28615ccace5f9c79fca7713c73c19e0767f8f47philippe for (EClassNo e = 0; e < ECLASS_N; e++) { 2447d28615ccace5f9c79fca7713c73c19e0767f8f47philippe VG_(printf)(" %4d", sectors[0].ec2tte_used[e]); 2448d28615ccace5f9c79fca7713c73c19e0767f8f47philippe if (e % 16 == 15) 24496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n"); 24506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 24516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj VG_(printf)("\n\n"); 24526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj } 245392e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote} 2454de4a1d01951937632098a6cda45859afa587a06fsewardj 2455fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 2456fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results. ---*/ 2457fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/ 24584ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj 2459518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic ULong score ( const TTEntry* tte ) 2460fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{ 2461bece82eba7ba26398a673def2fa326341c4f8ef7philippe return ((ULong)tte->usage.prof.weight) * ((ULong)tte->usage.prof.count); 2462de4a1d01951937632098a6cda45859afa587a06fsewardj} 2463de4a1d01951937632098a6cda45859afa587a06fsewardj 246417c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardjULong VG_(get_SB_profile) ( SBProfEntry tops[], UInt n_tops ) 2465de4a1d01951937632098a6cda45859afa587a06fsewardj{ 2466523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe SECno sno; 2467523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe Int r, s; 24682025cf98a3210c175a90fc77cb599cca1643bd68njn ULong score_total; 2469523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe TTEno i; 2470fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2471fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* First, compute the total weighted count, and find the top N 24722025cf98a3210c175a90fc77cb599cca1643bd68njn ttes. tops contains pointers to the most-used n_tops blocks, in 2473fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj descending order (viz, tops[0] is the highest scorer). */ 2474523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe for (s = 0; s < n_tops; s++) { 2475523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe tops[s].addr = 0; 2476523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe tops[s].score = 0; 24772025cf98a3210c175a90fc77cb599cca1643bd68njn } 2478fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 2479fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_total = 0; 2480fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj 24818e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 2482fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tc == NULL) 248318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj continue; 2484fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 2485fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (sectors[sno].tt[i].status != InUse) 2486fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 2487fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj score_total += score(§ors[sno].tt[i]); 2488fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* Find the rank for sectors[sno].tt[i]. */ 24892025cf98a3210c175a90fc77cb599cca1643bd68njn r = n_tops-1; 2490fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj while (True) { 2491fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj if (r == -1) 2492fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 24932025cf98a3210c175a90fc77cb599cca1643bd68njn if (tops[r].addr == 0) { 2494fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r--; 2495fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 2496fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 24972025cf98a3210c175a90fc77cb599cca1643bd68njn if ( score(§ors[sno].tt[i]) > tops[r].score ) { 2498fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r--; 2499fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj continue; 2500fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2501fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj break; 2502fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2503fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj r++; 25042025cf98a3210c175a90fc77cb599cca1643bd68njn vg_assert(r >= 0 && r <= n_tops); 2505fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj /* This bb should be placed at r, and bbs above it shifted 2506fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj upwards one slot. */ 25072025cf98a3210c175a90fc77cb599cca1643bd68njn if (r < n_tops) { 25082025cf98a3210c175a90fc77cb599cca1643bd68njn for (s = n_tops-1; s > r; s--) 2509fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj tops[s] = tops[s-1]; 25102025cf98a3210c175a90fc77cb599cca1643bd68njn tops[r].addr = sectors[sno].tt[i].entry; 25112025cf98a3210c175a90fc77cb599cca1643bd68njn tops[r].score = score( §ors[sno].tt[i] ); 2512fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj } 2513de4a1d01951937632098a6cda45859afa587a06fsewardj } 2514de4a1d01951937632098a6cda45859afa587a06fsewardj } 2515de4a1d01951937632098a6cda45859afa587a06fsewardj 251617c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj /* Now zero out all the counter fields, so that we can make 251717c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj multiple calls here and just get the values since the last call, 251817c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj each time, rather than values accumulated for the whole run. */ 25198e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe for (sno = 0; sno < n_sectors; sno++) { 252017c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj if (sectors[sno].tc == NULL) 252117c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj continue; 252217c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj for (i = 0; i < N_TTES_PER_SECTOR; i++) { 252317c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj if (sectors[sno].tt[i].status != InUse) 252417c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj continue; 2525bece82eba7ba26398a673def2fa326341c4f8ef7philippe sectors[sno].tt[i].usage.prof.count = 0; 252617c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj } 252717c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj } 252817c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj 25292025cf98a3210c175a90fc77cb599cca1643bd68njn return score_total; 2530c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj} 2531c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj 2532de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 25338bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end ---*/ 2534de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 2535