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 = &sectors[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 = &sectors[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 = &sectors[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 = &sectors[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*)(&sectors[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*)(&sectors[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 >= &sectors[y].tc[0]);
16815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr <= &sectors[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 >= &sectors[y].tc[0]);
16925f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 <= &sectors[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(&sectors[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                                &sectors[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( &sectors[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 == &sectors[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 = &sectors[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 = &sectors[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 = &sectors[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)(&sectors[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(&sectors[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(&sectors[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( &sectors[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