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