m_transtab.c revision 291849fb0285e0998b4c9e33eb153eb3373c4a88
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
11ec062e8d96a361af9905b5447027819dfbfee01asewardj   Copyright (C) 2000-2011 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
4918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* #define DEBUG_TRANSTAB */
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. */
676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define N_TTES_PER_SECTOR /*30011*/ /*40009*/ 65521
68291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj//DEBUG-ONLY: #define N_TTES_PER_SECTOR 10007
69de4a1d01951937632098a6cda45859afa587a06fsewardj
70fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to
71fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   specify the maximum allowable loading, after which the sector is
72fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   deemed full. */
735d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj#define SECTOR_TT_LIMIT_PERCENT 65
74de4a1d01951937632098a6cda45859afa587a06fsewardj
75fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */
76fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_TTES_PER_SECTOR_USABLE \
77fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj           ((N_TTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100)
786c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Equivalence classes for fast address range deletion.  There are 1 +
806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   2^ECLASS_WIDTH bins.  The highest one, ECLASS_MISC, describes an
816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   address range which does not fall cleanly within any specific bin.
826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Note that ECLASS_SHIFT + ECLASS_WIDTH must be < 32. */
836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_SHIFT 11
846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_WIDTH 8
856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_MISC  (1 << ECLASS_WIDTH)
866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_N     (1 + ECLASS_MISC)
876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define EC2TTE_DELETED  0xFFFF /* 16-bit special value */
896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
90de4a1d01951937632098a6cda45859afa587a06fsewardj
916c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/
92de4a1d01951937632098a6cda45859afa587a06fsewardj
93291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* In edges ("to-me") in the graph created by chaining. */
94291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
95291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
96291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_sNo;   /* sector number */
97291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_tteNo; /* TTE number in given sector */
98291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_offs;  /* code offset from TCEntry::tcptr where the patch is */
99291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Bool to_fastEP;  /* Is the patch to a fast or slow entry point? */
100291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
101291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge;
102291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
103291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
104291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Out edges ("from-me") in the graph created by chaining. */
105291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
106291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
107291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt to_sNo;    /* sector number */
108291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt to_tteNo;  /* TTE number in given sector */
109291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_offs; /* code offset in owning translation where patch is */
110291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
111291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge;
112291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
113291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
114291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_IN_EDGE_ARR 3
115291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
116291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
117291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt     n_fixed; /* 0 .. N_FIXED_IN_EDGE_ARR */
118291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdge   fixed[N_FIXED_IN_EDGE_ARR];
119291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray*  var; /* XArray* of InEdgeArr */
120291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
121291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr;
122291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
123291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_OUT_EDGE_ARR 2
124291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
125291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
126291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt    n_fixed; /* 0 .. N_FIXED_OUT_EDGE_ARR */
127291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdge fixed[N_FIXED_OUT_EDGE_ARR];
128291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray* var; /* XArray* of OutEdgeArr */
129291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
130291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr;
131291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
132291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
133fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry.  This indicates precisely which areas of
134fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   guest code are included in the translation, and contains all other
135fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   auxiliary info too.  */
1366c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef
1376c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   struct {
138fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Profiling only: the count and weight (arbitrary meaning) for
139fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         this translation.  Weight is a property of the translation
140fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         itself and computed once when the translation is created.
141fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         Count is an entry count for the translation and is
142fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         incremented by 1 every time the translation is used, if we
143fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         are profiling. */
144291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      ULong    count;
145fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      UShort   weight;
146fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
147fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Status of the slot.  Note, we need to be able to do lazy
148fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         deletion, hence the Deleted state. */
149fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      enum { InUse, Deleted, Empty } status;
150fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1515f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      /* 64-bit aligned pointer to one or more 64-bit words containing
1525f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         the corresponding host code (must be in the same sector!)
1535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         This is a pointer into the sector's tc (code) area. */
1545f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      ULong* tcptr;
155fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
156fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This is the original guest address that purportedly is the
157fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         entry point of the translation.  You might think that .entry
158fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         should be the same as .vge->base[0], and most of the time it
159fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         is.  However, when doing redirections, that is not the case.
160fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         .vge must always correctly describe the guest code sections
161fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         from which this translation was made.  However, .entry may or
162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         may not be a lie, depending on whether or not we're doing
163fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         redirection. */
164fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Addr64 entry;
165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
166fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This structure describes precisely what ranges of guest code
167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         the translation covers, so we can decide whether or not to
168fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         delete it when translations of a given address range are
169fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         invalidated. */
170fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VexGuestExtents vge;
1716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Address range summary info: these are pointers back to
1736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         eclass[] entries in the containing Sector.  Those entries in
1746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         turn point back here -- the two structures are mutually
1756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         redundant but both necessary to make fast deletions work.
1766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         The eclass info is similar to, and derived from, this entry's
1776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         'vge' field, but it is not the same */
1786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort n_tte2ec;      // # tte2ec pointers (1 to 3)
1796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort tte2ec_ec[3];  // for each, the eclass #
1806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UInt   tte2ec_ix[3];  // and the index within the eclass.
1816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // for i in 0 .. n_tte2ec-1
1826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      //    sec->ec2tte[ tte2ec_ec[i] ][ tte2ec_ix[i] ]
1836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // should be the index
1846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // of this TTEntry in the containing Sector's tt array.
185291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
186291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Admin information for chaining.  'in_edges' is a set of the
187291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         patch points which jump to this translation -- hence are
188291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         predecessors in the control flow graph.  'out_edges' points
189291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         to successors in the control flow graph -- translations to
190291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         which this one has a patched jump.  In short these are just
191291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         backwards and forwards edges in the graph of patched-together
192291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         blocks.  The 'in_edges' contain slightly more info, enough
193291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         that we can undo the chaining of each mentioned patch point.
194291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The 'out_edges' list exists only so that we can visit the
195291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         'in_edges' entries of all blocks we're patched through to, in
196291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         order to remove ourselves from then when we're deleted. */
197291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
198291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* A translation can disappear for two reasons:
199291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj          1. erased (as part of the oldest sector cleanup) when the
200291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             youngest sector is full.
201291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj          2. discarded due to calls to VG_(discard_translations).
202291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             VG_(discard_translations) sets the status of the
203291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             translation to 'Deleted'.
204291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             A.o., the gdbserver discards one or more translations
205291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             when a breakpoint is inserted or removed at an Addr,
206291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             or when single stepping mode is enabled/disabled
207291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             or when a translation is instrumented for gdbserver
208291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             (all the target jumps of this translation are
209291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj              invalidated).
210291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
211291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         So, it is possible that the translation A to be patched
212291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (to obtain a patched jump from A to B) is invalidated
213291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         after B is translated and before A is patched.
214291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         In case a translation is erased or discarded, the patching
215291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         cannot be done.  VG_(tt_tc_do_chaining) and find_TTEntry_from_hcode
216291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         are checking the 'from' translation still exists before
217291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         doing the patching.
218291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
219291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Is it safe to erase or discard the current translation E being
220291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         executed ? Amazing, but yes, it is safe.
221291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Here is the explanation:
222291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
223291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The translation E being executed can only be erased if a new
224291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation N is being done. A new translation is done only
225291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if the host addr is a not yet patched jump to another
226291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation. In such a case, the guest address of N is
227291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         assigned to the PC in the VEX state. Control is returned
228291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         to the scheduler. N will be translated. This can erase the
229291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation E (in case of sector full). VG_(tt_tc_do_chaining)
230291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         will not do the chaining to a non found translation E.
231291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The execution will continue at the current guest PC
232291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (i.e. the translation N).
233291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         => it is safe to erase the current translation being executed.
234291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
235291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The current translation E being executed can also be discarded
236291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (e.g. by gdbserver). VG_(discard_translations) will mark
237291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         this translation E as Deleted, but the translation itself
238291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         is not erased. In particular, its host code can only
239291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         be overwritten or erased in case a new translation is done.
240291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         A new translation will only be done if a not yet translated
241291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         jump is to be executed. The execution of the Deleted translation
242291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         E will continue till a non patched jump is encountered.
243291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         This situation is then similar to the 'erasing' case above :
244291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         the current translation E can be erased or overwritten, as the
245291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         execution will continue at the new translation N.
246291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
247291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      */
248291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
249291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* It is possible, although very unlikely, that a block A has
250291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         more than one patched jump to block B.  This could happen if
251291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (eg) A finishes "jcond B; jmp B".
252291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
253291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         This means in turn that B's in_edges set can list A more than
254291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         once (twice in this example).  However, each such entry must
255291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         have a different from_offs, since a patched jump can only
256291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         jump to one place at once (it's meaningless for it to have
257291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         multiple destinations.)  IOW, the successor and predecessor
258291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         edges in the graph are not uniquely determined by a
259291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         TTEntry --> TTEntry pair, but rather by a
260291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (TTEntry,offset) --> TTEntry triple.
261291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
262291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         If A has multiple edges to B then B will mention A multiple
263291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         times in its in_edges.  To make things simpler, we then
264291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         require that A mentions B exactly the same number of times in
265291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         its out_edges.  Furthermore, a matching out-in pair must have
266291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         the same offset (from_offs).  This facilitates sanity
267291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         checking, and it facilitates establishing the invariant that
268291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         a out_edges set may not have duplicates when using the
269291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         equality defined by (TTEntry,offset).  Hence the out_edges
270291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         and in_edges sets really do have both have set semantics.
271291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
272291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         eg if  A has been patched to B at offsets 42 and 87 (in A)
273291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         then   A.out_edges = { (B,42), (B,87) }   (in any order)
274291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         and    B.in_edges  = { (A,42), (A,87) }   (in any order)
275291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
276291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Hence for each node pair P->Q in the graph, there's a 1:1
277291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         mapping between P.out_edges and Q.in_edges.
278291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      */
279291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdgeArr  in_edges;
280291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdgeArr out_edges;
2816c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
2826c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   TTEntry;
2836c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
2844ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
285291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* A structure used for mapping host code addresses back to the
286291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   relevant TTEntry.  Used when doing chaining, for finding the
287291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry to which some arbitrary patch address belongs. */
288291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
289291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
290291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* start;
291291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt   len;
292291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt   tteNo;
293291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
294291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HostExtent;
295291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
296fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself.  Each sector contains an array of
297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   TCEntries, which hold code, and an array of TTEntries, containing
298fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   all required administrative info.  Profiling is supported using the
299291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry .count and .weight fields, if required.
3004ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   If the sector is not in use, all three pointers are NULL and
302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tt_n_inuse is zero.
303fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
304fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef
305fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   struct {
306fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TCEntry area.  Size of this depends on the average
307fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         translation size.  We try and size it so it becomes full
308fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         precisely when this sector's translation table (tt) reaches
309fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         its load limit (SECTOR_TT_LIMIT_PERCENT). */
310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc;
3114ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
312fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TTEntry array.  This is a fixed size, always containing
313fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         exactly N_TTES_PER_SECTOR entries. */
314fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      TTEntry* tt;
3156c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
316fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This points to the current allocation point in tc. */
317fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc_next;
318de4a1d01951937632098a6cda45859afa587a06fsewardj
319fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The count of tt entries with state InUse. */
320fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Int tt_n_inuse;
3216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Expandable arrays of tt indices for each of the ECLASS_N
3236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         address range equivalence classes.  These hold indices into
3246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         the containing sector's tt array, which in turn should point
3256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         back here. */
3266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int     ec2tte_size[ECLASS_N];
3276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int     ec2tte_used[ECLASS_N];
3286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort* ec2tte[ECLASS_N];
329291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
330291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* The host extents.  The [start, +len) ranges are constructed
331291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         in strictly non-overlapping order, so we can binary search
332291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         them at any time. */
333291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray* host_extents; /* XArray* of HostExtent */
334fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
335fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Sector;
336de4a1d01951937632098a6cda45859afa587a06fsewardj
337de4a1d01951937632098a6cda45859afa587a06fsewardj
3386c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/
3396c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
340fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors.  The index of the
341fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest sector is recorded, and new translations are put into that
342fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.  When it fills up, we move along to the next sector and
343fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   start to fill that up, wrapping around at the end of the array.
344fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   That way, once all N_TC_SECTORS have been bought into use for the
345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   first time, and are full, we then re-use the oldest sector,
346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   endlessly.
347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   When running, youngest sector should be between >= 0 and <
349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   N_TC_SECTORS.  The initial -1 value indicates the TT/TC system is
350fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   not yet initialised.
351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
352fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Sector sectors[N_SECTORS];
353fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int    youngest_sector = -1;
3546c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
355fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area.  This is computed once
356fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   at startup and does not change. */
357fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int    tc_sector_szQ;
3586c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3596c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3605d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj/* A list of sector numbers, in the order which they should be
3615d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   searched to find translations.  This is an optimisation to be used
3625d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   when searching for translations and should not affect
3635d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   correctness.  -1 denotes "no entry". */
3645d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardjstatic Int sector_search_order[N_SECTORS];
3655d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
3665d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
3675f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Fast helper for the TC.  A direct-mapped cache which holds a set of
3685f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   recently used (guest address, host address) pairs.  This array is
3695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   referred to directly from m_dispatch/dispatch-<platform>.S.
3706c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3715f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   Entries in tt_fast may refer to any valid TC entry, regardless of
372fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   which sector it's in.  Consequently we must be very careful to
373fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidate this cache when TC entries are changed or disappear.
374c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
3755f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   A special .guest address - TRANSTAB_BOGUS_GUEST_ADDR -- must be
3765f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   pointed at to cause that cache entry to miss.  This relies on the
3775f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   assumption that no guest code actually has that address, hence a
3785f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   value 0x1 seems good.  m_translate gives the client a synthetic
3795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   segfault if it tries to execute at this address.
3805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/
3815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*
3825f76de086a6d643db51e50a4e623df7dfc9b6161sewardjtypedef
3835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   struct {
3845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      Addr guest;
3855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      Addr host;
3865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
3875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   FastCacheEntry;
3885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/
3895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*global*/ __attribute__((aligned(16)))
3905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj           FastCacheEntry VG_(tt_fast)[VG_TT_FAST_SIZE];
391de4a1d01951937632098a6cda45859afa587a06fsewardj
392663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */
393663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False;
394663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
395663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
396fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/
397de4a1d01951937632098a6cda45859afa587a06fsewardj
398fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */
399291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_flushes = 0;
400291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_updates = 0;
40122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
402fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */
403291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_full_lookups = 0;
404291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_lookup_probes = 0;
40522854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
40626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj/* Number/osize/tsize of translations entered; also the number of
40726412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   those for which self-checking was requested. */
408291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_count    = 0;
409291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_osize    = 0;
410291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_tsize    = 0;
411291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_sc_count = 0;
412de4a1d01951937632098a6cda45859afa587a06fsewardj
413fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */
414291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_count = 0;
415291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_osize = 0;
416fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
417fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */
418291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_count = 0;
419291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_osize = 0;
420291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
421291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
422291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
423291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Misc                                                  ---*/
424291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
425291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
426291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void* ttaux_malloc ( HChar* tag, SizeT n )
427291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
428291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return VG_(arena_malloc)(VG_AR_TTAUX, tag, n);
429291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
430291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
431291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void ttaux_free ( void* p )
432291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
433291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(arena_free)(VG_AR_TTAUX, p);
434291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
435291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
436291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
437291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
438291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Chaining support                                      ---*/
439291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
440291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
441291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic inline TTEntry* index_tte ( UInt sNo, UInt tteNo )
442291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
443291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(sNo < N_SECTORS);
444291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(tteNo < N_TTES_PER_SECTOR);
445291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Sector* s = &sectors[sNo];
446291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(s->tt);
447291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* tte = &s->tt[tteNo];
448291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(tte->status == InUse);
449291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return tte;
450291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
451291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
452291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdge__init ( InEdge* ie )
453291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
454291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_sNo   = -1; /* invalid */
455291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_tteNo = 0;
456291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_offs  = 0;
457291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->to_fastEP  = False;
458291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
459291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
460291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdge__init ( OutEdge* oe )
461291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
462291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->to_sNo    = -1; /* invalid */
463291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->to_tteNo  = 0;
464291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->from_offs = 0;
465291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
466291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
467291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void TTEntry__init ( TTEntry* tte )
468291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
469291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(memset)(tte, 0, sizeof(*tte));
470291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
471291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
472291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic UWord InEdgeArr__size ( InEdgeArr* iea )
473291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
474291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
475291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
476291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return VG_(sizeXA)(iea->var);
477291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
478291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
479291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return iea->n_fixed;
480291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
481291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
482291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
483291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdgeArr__makeEmpty ( InEdgeArr* iea )
484291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
485291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
486291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
487291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(deleteXA)(iea->var);
488291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->var = NULL;
489291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
490291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
491291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->n_fixed = 0;
492291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
493291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
494291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
495291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
496291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjInEdge* InEdgeArr__index ( InEdgeArr* iea, UWord i )
497291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
498291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
499291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
500291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return (InEdge*)VG_(indexXA)(iea->var, i);
501291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
502291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < iea->n_fixed);
503291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return &iea->fixed[i];
504291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
505291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
506291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
507291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
508291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__deleteIndex ( InEdgeArr* iea, UWord i )
509291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
510291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
511291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
512291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(removeIndexXA)(iea->var, i);
513291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
514291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < iea->n_fixed);
515291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (; i+1 < iea->n_fixed; i++) {
516291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->fixed[i] = iea->fixed[i+1];
517291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
518291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->n_fixed--;
519291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
520291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
521291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
522291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
523291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__add ( InEdgeArr* iea, InEdge* ie )
524291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
525291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
526291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
527291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(addToXA)(iea->var, ie);
528291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
529291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
530291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (iea->n_fixed == N_FIXED_IN_EDGE_ARR) {
531291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* The fixed array is full, so we have to initialise an
532291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            XArray and copy the fixed array into it. */
533291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->var = VG_(newXA)(ttaux_malloc, "transtab.IEA__add",
534291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               ttaux_free,
535291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               sizeof(InEdge));
536291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UWord i;
537291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         for (i = 0; i < iea->n_fixed; i++) {
538291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            VG_(addToXA)(iea->var, &iea->fixed[i]);
539291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         }
540291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         VG_(addToXA)(iea->var, ie);
541291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->n_fixed = 0;
542291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      } else {
543291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Just add to the fixed array. */
544291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->fixed[iea->n_fixed++] = *ie;
545291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
546291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
547291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
548291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
549291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic UWord OutEdgeArr__size ( OutEdgeArr* oea )
550291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
551291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
552291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
553291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return VG_(sizeXA)(oea->var);
554291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
555291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
556291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return oea->n_fixed;
557291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
558291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
559291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
560291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdgeArr__makeEmpty ( OutEdgeArr* oea )
561291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
562291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
563291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
564291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(deleteXA)(oea->var);
565291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->var = NULL;
566291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
567291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
568291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->n_fixed = 0;
569291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
570291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
571291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
572291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
573291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjOutEdge* OutEdgeArr__index ( OutEdgeArr* oea, UWord i )
574291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
575291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
576291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
577291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return (OutEdge*)VG_(indexXA)(oea->var, i);
578291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
579291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < oea->n_fixed);
580291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return &oea->fixed[i];
581291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
582291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
583291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
584291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
585291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__deleteIndex ( OutEdgeArr* oea, UWord i )
586291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
587291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
588291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
589291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(removeIndexXA)(oea->var, i);
590291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
591291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < oea->n_fixed);
592291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (; i+1 < oea->n_fixed; i++) {
593291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->fixed[i] = oea->fixed[i+1];
594291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
595291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->n_fixed--;
596291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
597291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
598291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
599291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
600291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__add ( OutEdgeArr* oea, OutEdge* oe )
601291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
602291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
603291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
604291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(addToXA)(oea->var, oe);
605291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
606291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
607291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (oea->n_fixed == N_FIXED_OUT_EDGE_ARR) {
608291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* The fixed array is full, so we have to initialise an
609291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            XArray and copy the fixed array into it. */
610291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->var = VG_(newXA)(ttaux_malloc, "transtab.OEA__add",
611291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               ttaux_free,
612291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               sizeof(OutEdge));
613291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UWord i;
614291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         for (i = 0; i < oea->n_fixed; i++) {
615291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            VG_(addToXA)(oea->var, &oea->fixed[i]);
616291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         }
617291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         VG_(addToXA)(oea->var, oe);
618291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->n_fixed = 0;
619291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      } else {
620291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Just add to the fixed array. */
621291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->fixed[oea->n_fixed++] = *oe;
622291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
623291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
624291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
625291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
626291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
627291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjInt HostExtent__cmpOrd ( void* v1, void* v2 )
628291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
629291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HostExtent* hx1 = (HostExtent*)v1;
630291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HostExtent* hx2 = (HostExtent*)v2;
631291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (hx1->start + hx1->len <= hx2->start) return -1;
632291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (hx2->start + hx2->len <= hx1->start) return 1;
633291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return 0; /* partial overlap */
634291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
635291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
636291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic __attribute__((noinline))
637291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool find_TTEntry_from_hcode( /*OUT*/UInt* from_sNo,
638291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              /*OUT*/UInt* from_tteNo,
639291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              void* hcode )
640291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
641291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int i;
642291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
643291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Search order logic copied from VG_(search_transtab). */
644291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < N_SECTORS; i++) {
645291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Int sno = sector_search_order[i];
646291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (UNLIKELY(sno == -1))
647291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return False; /* run out of sectors to search */
648291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
649291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Sector* sec = &sectors[sno];
650291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray* /* of HostExtent */ host_extents = sec->host_extents;
651291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(host_extents);
652291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
653291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      HostExtent key;
654291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(memset)(&key, 0, sizeof(key));
655291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      key.start = hcode;
656291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      key.len = 1;
657291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Word firstW = -1, lastW = -1;
658291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Bool found  = VG_(lookupXA_UNSAFE)(
659291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       host_extents, &key, &firstW, &lastW,
660291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       (Int(*)(void*,void*))HostExtent__cmpOrd
661291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    );
662291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(firstW == lastW); // always true, even if not found
663291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (found) {
664291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         HostExtent* hx = VG_(indexXA)(host_extents, firstW);
665291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UInt tteNo = hx->tteNo;
666291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Do some additional sanity checks. */
667291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert(tteNo <= N_TTES_PER_SECTOR);
668291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Entry might have been invalidated. Consider this
669291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            as not found. */
670291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if (sec->tt[tteNo].status == Deleted)
671291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            return False;
672291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert(sec->tt[tteNo].status == InUse);
673291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Can only half check that the found TTEntry contains hcode,
674291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            due to not having a length value for the hcode in the
675291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            TTEntry. */
676291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert((UChar*)sec->tt[tteNo].tcptr <= (UChar*)hcode);
677291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Looks plausible */
678291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         *from_sNo   = sno;
679291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         *from_tteNo = (UInt)tteNo;
680291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return True;
681291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
682291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
683291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return False;
684291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
685291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
686291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
687291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Figure out whether or not hcode is jitted code present in the main
688291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   code cache (but not in the no-redir cache).  Used for sanity
689291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   checking. */
690291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic Bool is_in_the_main_TC ( void* hcode )
691291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
692291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int i, sno;
693291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < N_SECTORS; i++) {
694291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      sno = sector_search_order[i];
695291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (sno == -1)
696291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         break; /* run out of sectors to search */
697291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if ((UChar*)hcode >= (UChar*)sectors[sno].tc
698291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj          && (UChar*)hcode <= (UChar*)sectors[sno].tc_next
699291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              + sizeof(ULong) - 1)
700291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return True;
701291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
702291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return False;
703291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
704291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
705291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
706291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Fulfill a chaining request, and record admin info so we
707291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   can undo it later, if required.
708291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj*/
709291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid VG_(tt_tc_do_chaining) ( void* from__patch_addr,
710291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              UInt  to_sNo,
711291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              UInt  to_tteNo,
712291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              Bool  to_fastEP )
713291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
714291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Get the CPU info established at startup. */
715291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexArch vex_arch = VexArch_INVALID;
716291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(machine_get_VexArchInfo)( &vex_arch, NULL );
717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
718291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // host_code is where we're patching to.  So it needs to
719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // take into account, whether we're jumping to the slow
720291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // or fast entry point.  By definition, the fast entry point
721291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // is exactly one event check's worth of code along from
722291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // the slow (tcptr) entry point.
723291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* to_tte    = index_tte(to_sNo, to_tteNo);
724291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   void*    host_code = ((UChar*)to_tte->tcptr)
725291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                        + (to_fastEP ? LibVEX_evCheckSzB(vex_arch) : 0);
726291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
727291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // stay sane -- the patch point (dst) is in this sector's code cache
728291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( (UChar*)host_code >= (UChar*)sectors[to_sNo].tc );
729291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( (UChar*)host_code <= (UChar*)sectors[to_sNo].tc_next
730291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                   + sizeof(ULong) - 1 );
731291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
732291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Find the TTEntry for the from__ code.  This isn't simple since
733291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      we only know the patch address, which is going to be somewhere
734291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      inside the from_ block. */
735291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UInt from_sNo   = (UInt)-1;
736291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UInt from_tteNo = (UInt)-1;
737291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Bool from_found
738291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = find_TTEntry_from_hcode( &from_sNo, &from_tteNo,
739291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                 from__patch_addr );
740291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (!from_found) {
741291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // The from code might have been discarded due to sector re-use
742291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // or marked Deleted due to translation invalidation.
743291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // In such a case, don't do the chaining.
744291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(debugLog)(1,"transtab",
745291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    "host code %p not found (discarded? sector recycled?)"
746291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    " => no chaining done\n",
747291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    from__patch_addr);
748291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return;
749291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
750291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
751291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* from_tte = index_tte(from_sNo, from_tteNo);
752291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
753291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Get VEX to do the patching itself.  We have to hand it off
754291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      since it is host-dependent. */
755291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexInvalRange vir
756291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = LibVEX_Chain(
757291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           vex_arch,
758291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           from__patch_addr,
759291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           VG_(fnptr_to_fnentry)(
760291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj              to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP)
761291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                        : &VG_(disp_cp_chain_me_to_slowEP)),
762291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           (void*)host_code
763291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        );
764291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( (void*)vir.start, vir.len );
765291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
766291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Now do the tricky bit -- update the ch_succs and ch_preds info
767291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for the two translations involved, so we can undo the chaining
768291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      later, which we will have to do if the to_ block gets removed
769291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for whatever reason. */
770291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
771291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* This is the new from_ -> to_ link to add. */
772291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge ie;
773291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge__init(&ie);
774291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_sNo   = from_sNo;
775291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_tteNo = from_tteNo;
776291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.to_fastEP  = to_fastEP;
777291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HWord from_offs = (HWord)( (UChar*)from__patch_addr
778291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              - (UChar*)from_tte->tcptr );
779291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(from_offs < 100000/* let's say */);
780291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_offs  = (UInt)from_offs;
781291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
782291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* This is the new to_ -> from_ backlink to add. */
783291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge oe;
784291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge__init(&oe);
785291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.to_sNo    = to_sNo;
786291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.to_tteNo  = to_tteNo;
787291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.from_offs = (UInt)from_offs;
788291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
789291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Add .. */
790291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr__add(&to_tte->in_edges, &ie);
791291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr__add(&from_tte->out_edges, &oe);
792291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
793291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
794291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
795291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Unchain one patch, as described by the specified InEdge.  For
796291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   sanity check purposes only (to check that the patched location is
797291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   as expected) it also requires the fast and slow entry point
798291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   addresses of the destination block (that is, the block that owns
799291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   this InEdge). */
800291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj__attribute__((noinline))
801291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void unchain_one ( VexArch vex_arch,
802291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          InEdge* ie,
803291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          void* to_fastEPaddr, void* to_slowEPaddr )
804291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
805291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(ie);
806291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* tte
807291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = index_tte(ie->from_sNo, ie->from_tteNo);
808291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* place_to_patch
809291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = ((HChar*)tte->tcptr) + ie->from_offs;
810291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* disp_cp_chain_me
811291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = VG_(fnptr_to_fnentry)(
812291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           ie->to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP)
813291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                         : &VG_(disp_cp_chain_me_to_slowEP)
814291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        );
815291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* place_to_jump_to_EXPECTED
816291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = ie->to_fastEP ? to_fastEPaddr : to_slowEPaddr;
817291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
818291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // stay sane: both src and dst for this unchaining are
819291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // in the main code cache
820291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( is_in_the_main_TC(place_to_patch) ); // src
821291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( is_in_the_main_TC(place_to_jump_to_EXPECTED) ); // dst
822291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // dst check is ok because LibVEX_UnChain checks that
823291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // place_to_jump_to_EXPECTED really is the current dst, and
824291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // asserts if it isn't.
825291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexInvalRange vir
826291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj       = LibVEX_UnChain( vex_arch, place_to_patch,
827291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                         place_to_jump_to_EXPECTED, disp_cp_chain_me );
828291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( (void*)vir.start, vir.len );
829291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
830291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
831291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
832291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* The specified block is about to be deleted.  Update the preds and
833291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   succs of its associated blocks accordingly.  This includes undoing
834291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   any chained jumps to this block. */
835291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
836291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid unchain_in_preparation_for_deletion ( VexArch vex_arch,
837291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                           UInt here_sNo, UInt here_tteNo )
838291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
839291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (0)
840291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(printf)("QQQ unchain_in_prep %u.%u\n", here_sNo, here_tteNo);
841291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UWord    i, j, n, m;
842291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int      evCheckSzB = LibVEX_evCheckSzB(vex_arch);
843291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* here_tte   = index_tte(here_sNo, here_tteNo);
844291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(here_tte->status == InUse);
845291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
846291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Visit all InEdges owned by here_tte. */
847291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   n = InEdgeArr__size(&here_tte->in_edges);
848291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < n; i++) {
849291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdge* ie = InEdgeArr__index(&here_tte->in_edges, i);
850291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Undo the chaining.
851291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* here_slow_EP = (UChar*)here_tte->tcptr;
852291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* here_fast_EP = here_slow_EP + evCheckSzB;
853291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      unchain_one(vex_arch, ie, here_fast_EP, here_slow_EP);
854291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Find the corresponding entry in the "from" node's out_edges,
855291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // and remove it.
856291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      TTEntry* from_tte = index_tte(ie->from_sNo, ie->from_tteNo);
857291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      m = OutEdgeArr__size(&from_tte->out_edges);
858291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(m > 0); // it must have at least one entry
859291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (j = 0; j < m; j++) {
860291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         OutEdge* oe = OutEdgeArr__index(&from_tte->out_edges, j);
861291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if (oe->to_sNo == here_sNo && oe->to_tteNo == here_tteNo
862291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             && oe->from_offs == ie->from_offs)
863291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           break;
864291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
865291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(j < m); // "oe must be findable"
866291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdgeArr__deleteIndex(&from_tte->out_edges, j);
867291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
868291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
869291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Visit all OutEdges owned by here_tte. */
870291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   n = OutEdgeArr__size(&here_tte->out_edges);
871291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < n; i++) {
872291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdge* oe = OutEdgeArr__index(&here_tte->out_edges, i);
873291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Find the corresponding entry in the "to" node's in_edges,
874291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // and remove it.
875291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      TTEntry* to_tte = index_tte(oe->to_sNo, oe->to_tteNo);
876291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      m = InEdgeArr__size(&to_tte->in_edges);
877291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(m > 0); // it must have at least one entry
878291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (j = 0; j < m; j++) {
879291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         InEdge* ie = InEdgeArr__index(&to_tte->in_edges, j);
880291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if (ie->from_sNo == here_sNo && ie->from_tteNo == here_tteNo
881291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             && ie->from_offs == oe->from_offs)
882291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           break;
883291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
884291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(j < m); // "ie must be findable"
885291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdgeArr__deleteIndex(&to_tte->in_edges, j);
886291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
887291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
888291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr__makeEmpty(&here_tte->in_edges);
889291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr__makeEmpty(&here_tte->out_edges);
890291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
891fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
892fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
8936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
8946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Address-range equivalence class stuff                 ---*/
8956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
8966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
8976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Return equivalence class number for a range. */
8986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
8996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Int range_to_eclass ( Addr64 start, UInt len )
9006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
9016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt mask   = (1 << ECLASS_WIDTH) - 1;
9026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt lo     = (UInt)start;
9036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt hi     = lo + len - 1;
9046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt loBits = (lo >> ECLASS_SHIFT) & mask;
9056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt hiBits = (hi >> ECLASS_SHIFT) & mask;
9066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (loBits == hiBits) {
9076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(loBits < ECLASS_N-1);
9086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return loBits;
9096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   } else {
9106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return ECLASS_MISC;
9116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
9136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Calculates the equivalence class numbers for any VexGuestExtent.
9166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   These are written in *eclasses, which must be big enough to hold 3
9176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Ints.  The number written, between 1 and 3, is returned.  The
9186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclasses are presented in order, and any duplicates are removed.
9196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj*/
9206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
9226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjInt vexGuestExtents_to_eclasses ( /*OUT*/Int* eclasses,
9236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                  VexGuestExtents* vge )
9246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
9256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  define SWAP(_lv1,_lv2) \
9266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      do { Int t = _lv1; _lv1 = _lv2; _lv2 = t; } while (0)
9276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, j, n_ec, r;
9296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
9316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_ec = 0;
9336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < vge->n_used; i++) {
9346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      r = range_to_eclass( vge->base[i], (UInt)vge->len[i] );
9356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (r == ECLASS_MISC)
9366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         goto bad;
9376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* only add if we haven't already seen it */
9386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < n_ec; j++)
9396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (eclasses[j] == r)
9406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            break;
9416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (j == n_ec)
9426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         eclasses[n_ec++] = r;
9436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 1)
9466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 1;
9476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 2) {
9496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* sort */
9506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[1])
9516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[1]);
9526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 2;
9536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 3) {
9566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* sort */
9576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[2])
9586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[2]);
9596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[1])
9606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[1]);
9616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[1] > eclasses[2])
9626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[1], eclasses[2]);
9636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 3;
9646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* NOTREACHED */
9676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(0);
9686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj  bad:
9706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclasses[0] = ECLASS_MISC;
9716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return 1;
9726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  undef SWAP
9746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
9756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Add tteno to the set of entries listed for equivalence class ec in
9786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   this sector.  Returns used location in eclass array. */
9796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
9816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjUInt addEClassNo ( /*MOD*/Sector* sec, Int ec, UShort tteno )
9826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
9836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int    old_sz, new_sz, i, r;
9846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort *old_ar, *new_ar;
9856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(ec >= 0 && ec < ECLASS_N);
9876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno < N_TTES_PER_SECTOR);
9886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (0) VG_(printf)("ec %d  gets %d\n", ec, (Int)tteno);
9906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->ec2tte_used[ec] >= sec->ec2tte_size[ec]) {
9926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->ec2tte_used[ec] == sec->ec2tte_size[ec]);
9946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      old_sz = sec->ec2tte_size[ec];
9966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      old_ar = sec->ec2tte[ec];
9976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      new_sz = old_sz==0 ? 8 : old_sz<64 ? 2*old_sz : (3*old_sz)/2;
998291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      new_ar = ttaux_malloc("transtab.aECN.1",
999291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                            new_sz * sizeof(UShort));
10006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < old_sz; i++)
10016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         new_ar[i] = old_ar[i];
10026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (old_ar)
1003291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         ttaux_free(old_ar);
10046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte_size[ec] = new_sz;
10056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte[ec] = new_ar;
10066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (0) VG_(printf)("expand ec %d to %d\n", ec, new_sz);
10086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Common case */
10116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   r = sec->ec2tte_used[ec]++;
10126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(r >= 0 && r < sec->ec2tte_size[ec]);
10136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->ec2tte[ec][r] = tteno;
10146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return (UInt)r;
10156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
10166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* 'vge' is being added to 'sec' at TT entry 'tteno'.  Add appropriate
10196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclass entries to 'sec'. */
10206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
10226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjvoid upd_eclasses_after_add ( /*MOD*/Sector* sec, Int tteno )
10236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
10246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, r, eclasses[3];
10256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
10266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR);
10276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte = &sec->tt[tteno];
10296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   r = vexGuestExtents_to_eclasses( eclasses, &tte->vge );
10306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(r >= 1 && r <= 3);
10326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->n_tte2ec = r;
10336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < r; i++) {
10356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte->tte2ec_ec[i] = eclasses[i];
10366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte->tte2ec_ix[i] = addEClassNo( sec, eclasses[i], (UShort)tteno );
10376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
10396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Check the eclass info in 'sec' to ensure it is consistent.  Returns
10426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   True if OK, False if something's not right.  Expensive. */
10436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_eclasses_in_sector ( Sector* sec )
10456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
10466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  define BAD(_str) do { whassup = (_str); goto bad; } while (0)
10476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   HChar*   whassup = NULL;
10496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i, j, k, n, ec_num, ec_idx;
10506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
10516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort   tteno;
10526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   ULong*   tce;
10536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Basic checks on this sector */
10556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->tt_n_inuse < 0 || sec->tt_n_inuse > N_TTES_PER_SECTOR_USABLE)
10566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      BAD("invalid sec->tt_n_inuse");
10576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tce = sec->tc_next;
10586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (tce < &sec->tc[0] || tce > &sec->tc[tc_sector_szQ])
10596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      BAD("sec->tc_next points outside tc");
10606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* For each eclass ... */
10626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < ECLASS_N; i++) {
10636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_size[i] == 0 && sec->ec2tte[i] != NULL)
10646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("ec2tte_size/ec2tte mismatch(1)");
10656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_size[i] != 0 && sec->ec2tte[i] == NULL)
10666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("ec2tte_size/ec2tte mismatch(2)");
10676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_used[i] < 0
10686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj          || sec->ec2tte_used[i] > sec->ec2tte_size[i])
10696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("implausible ec2tte_used");
10706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_used[i] == 0)
10716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
10726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* For each tt reference in each eclass .. ensure the reference
10746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         is to a valid tt entry, and that the entry's address ranges
10756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         really include this eclass. */
10766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < sec->ec2tte_used[i]; j++) {
10786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         tteno = sec->ec2tte[i][j];
10796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tteno == EC2TTE_DELETED)
10806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
10816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tteno >= N_TTES_PER_SECTOR)
10826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("implausible tteno");
10836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         tte = &sec->tt[tteno];
10846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->status != InUse)
10856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tteno points to non-inuse tte");
10866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3)
10876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->n_tte2ec out of range");
10886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         /* Exactly least one of tte->eclasses[0 .. tte->n_eclasses-1]
10896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            must equal i.  Inspect tte's eclass info. */
10906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         n = 0;
10916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         for (k = 0; k < tte->n_tte2ec; k++) {
10926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (k < tte->n_tte2ec-1
10936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                && tte->tte2ec_ec[k] >= tte->tte2ec_ec[k+1])
10946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ec[..] out of order");
10956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            ec_num = tte->tte2ec_ec[k];
10966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_num < 0 || ec_num >= ECLASS_N)
10976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ec[..] out of range");
10986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_num != i)
10996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               continue;
11006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            ec_idx = tte->tte2ec_ix[k];
11016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[i])
11026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ix[..] out of range");
11036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_idx == j)
11046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               n++;
11056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
11066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (n != 1)
11076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tteno does not point back at eclass");
11086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* That establishes that for each forward pointer from TTEntrys
11126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      there is a corresponding backward pointer from the eclass[]
11136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      arrays.  However, it doesn't rule out the possibility of other,
11146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      bogus pointers in the eclass[] arrays.  So do those similarly:
11156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      scan through them and check the TTEntryies they point at point
11166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      back. */
11176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < N_TTES_PER_SECTOR_USABLE; i++) {
11196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte = &sec->tt[i];
11216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tte->status == Empty || tte->status == Deleted) {
11226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->n_tte2ec != 0)
11236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->n_eclasses nonzero for unused tte");
11246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
11256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tte->status == InUse);
11286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3)
11306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("tte->n_eclasses out of range(2)");
11316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < tte->n_tte2ec; j++) {
11336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         ec_num = tte->tte2ec_ec[j];
11346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (ec_num < 0 || ec_num >= ECLASS_N)
11356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->eclass[..] out of range");
11366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         ec_idx = tte->tte2ec_ix[j];
11376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[ec_num])
11386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->ec_idx[..] out of range(2)");
11396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->ec2tte[ec_num][ec_idx] != i)
11406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("ec2tte does not point back to tte");
11416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return True;
11456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj  bad:
11476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (whassup)
11486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(0, "transtab", "eclass sanity fail: %s\n", whassup);
11496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  if 0
11516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   VG_(printf)("eclass = %d\n", i);
11526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   VG_(printf)("tteno = %d\n", (Int)tteno);
11536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   switch (tte->status) {
11546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case InUse:   VG_(printf)("InUse\n"); break;
11556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case Deleted: VG_(printf)("Deleted\n"); break;
11566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case Empty:   VG_(printf)("Empty\n"); break;
11576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (tte->status != Empty) {
11596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (k = 0; k < tte->vge.n_used; k++)
11606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         VG_(printf)("0x%llx %d\n", tte->vge.base[k],
11616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                    (Int)tte->vge.len[k]);
11626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  endif
11646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return False;
11666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  undef BAD
11686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
11696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Sanity check absolutely everything.  True == check passed. */
11726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11735f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* forwards */
11740ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void );
11750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
11765d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardjstatic Bool sanity_check_sector_search_order ( void )
11775d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj{
11785d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   Int i, j, nListed;
11795d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* assert the array is the right size */
11805d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   vg_assert(N_SECTORS == (sizeof(sector_search_order)
11815d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj                           / sizeof(sector_search_order[0])));
11825d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check it's of the form  valid_sector_numbers ++ [-1, -1, ..] */
11835d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   for (i = 0; i < N_SECTORS; i++) {
11845d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sector_search_order[i] < 0 || sector_search_order[i] >= N_SECTORS)
11855d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         break;
11865d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
11875d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   nListed = i;
11885d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   for (/* */; i < N_SECTORS; i++) {
11895d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sector_search_order[i] != -1)
11905d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         break;
11915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
11925d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   if (i != N_SECTORS)
11935d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
11945d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check each sector number only appears once */
11955d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   for (i = 0; i < N_SECTORS; i++) {
11965d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sector_search_order[i] == -1)
11975d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         continue;
11985d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      for (j = i+1; j < N_SECTORS; j++) {
11995d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         if (sector_search_order[j] == sector_search_order[i])
12005d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            return False;
12015d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
12025d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12035d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check that the number of listed sectors equals the number
12045d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      in use, by counting nListed back down. */
12055d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   for (i = 0; i < N_SECTORS; i++) {
12065d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sectors[i].tc != NULL)
12075d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         nListed--;
12085d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12095d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   if (nListed != 0)
12105d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
12115d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   return True;
12125d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj}
12135d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
12146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_all_sectors ( void )
12156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
12166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int     sno;
12176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool    sane;
12186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
12196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (sno = 0; sno < N_SECTORS; sno++) {
12206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec = &sectors[sno];
12216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->tc == NULL)
12226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
12236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sane = sanity_check_eclasses_in_sector( sec );
12246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (!sane)
12256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         return False;
12266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
12275f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if ( !sanity_check_redir_tt_tc() )
12285f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      return False;
12295d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   if ( !sanity_check_sector_search_order() )
12305d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
12316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return True;
12326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
12336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1234fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
12355d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1236fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
12376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Add/find translations                                 ---*/
1238fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
1239fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1240fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic UInt vge_osize ( VexGuestExtents* vge )
1241c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{
1242fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt i, n = 0;
1243fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < vge->n_used; i++)
1244fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n += (UInt)vge->len[i];
1245fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n;
1246c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
1247c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
1248fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Bool isValidSector ( Int sector )
12496c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1250fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sector < 0 || sector >= N_SECTORS)
1251fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1252fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
12536c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1254de4a1d01951937632098a6cda45859afa587a06fsewardj
1255fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline UInt HASH_TT ( Addr64 key )
1256de4a1d01951937632098a6cda45859afa587a06fsewardj{
1257fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt kHi = (UInt)(key >> 32);
1258fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt kLo = (UInt)key;
12596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt k32 = kHi ^ kLo;
12606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt ror = 7;
12616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (ror > 0)
12626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      k32 = (k32 >> ror) | (k32 << (32-ror));
12636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return k32 % N_TTES_PER_SECTOR;
1264de4a1d01951937632098a6cda45859afa587a06fsewardj}
1265de4a1d01951937632098a6cda45859afa587a06fsewardj
1266291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void setFastCacheEntry ( Addr64 key, ULong* tcptr )
1267de4a1d01951937632098a6cda45859afa587a06fsewardj{
12683387dda4479102751d544c176a7bfc24f3766669sewardj   UInt cno = (UInt)VG_TT_FAST_HASH(key);
12695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   VG_(tt_fast)[cno].guest = (Addr)key;
12705f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   VG_(tt_fast)[cno].host  = (Addr)tcptr;
1271fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_updates++;
12725f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* This shouldn't fail.  It should be assured by m_translate
12735f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      which should reject any attempt to make translation of code
12745f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      starting at TRANSTAB_BOGUS_GUEST_ADDR. */
12755f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_(tt_fast)[cno].guest != TRANSTAB_BOGUS_GUEST_ADDR);
12766c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1277de4a1d01951937632098a6cda45859afa587a06fsewardj
1278291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Invalidate the fast cache VG_(tt_fast). */
12795f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastCache ( void )
12805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{
12815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   UInt j;
12825f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* This loop is popular enough to make it worth unrolling a
12835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      bit, at least on ppc32. */
12845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0);
12855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   for (j = 0; j < VG_TT_FAST_SIZE; j += 4) {
12865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+0].guest = TRANSTAB_BOGUS_GUEST_ADDR;
12875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+1].guest = TRANSTAB_BOGUS_GUEST_ADDR;
12885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+2].guest = TRANSTAB_BOGUS_GUEST_ADDR;
12895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+3].guest = TRANSTAB_BOGUS_GUEST_ADDR;
12905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
12915f76de086a6d643db51e50a4e623df7dfc9b6161sewardj
12925f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(j == VG_TT_FAST_SIZE);
1293fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_flushes++;
12946c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1295de4a1d01951937632098a6cda45859afa587a06fsewardj
1296fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void initialiseSector ( Int sno )
12976c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1298291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int     i;
1299291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   SysRes  sres;
13006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
1301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(sno));
1302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
13035d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   { Bool sane = sanity_check_sector_search_order();
13045d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj     vg_assert(sane);
13055d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
13066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec = &sectors[sno];
13076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
13086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->tc == NULL) {
13096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Sector has never been used before.  Need to allocate tt and
1311fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         tc. */
13126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt == NULL);
13136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tc_next == NULL);
13146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt_n_inuse == 0);
13156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
13166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte_size[i] == 0);
13176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte_used[i] == 0);
13186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte[i] == NULL);
13196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
1320291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(sec->host_extents == NULL);
132145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
132245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(1,"transtab", "allocate sector %d\n", sno);
132345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
132445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ );
1325cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
132645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TC)",
132745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     8 * tc_sector_szQ );
132845f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
132945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
1330cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      sec->tc = (ULong*)(AddrH)sr_Res(sres);
133145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
133245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)
133345f4e7c91119c7d01a59f5e827c67841632c9314sewardj                ( N_TTES_PER_SECTOR * sizeof(TTEntry) );
1334cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
133545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TT)",
133645f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     N_TTES_PER_SECTOR * sizeof(TTEntry) );
133745f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
133845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
1339cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      sec->tt = (TTEntry*)(AddrH)sr_Res(sres);
13406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
13416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
13426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].status   = Empty;
13436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].n_tte2ec = 0;
13446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
134545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1346291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Set up the host_extents array. */
1347291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      sec->host_extents
1348291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         = VG_(newXA)(ttaux_malloc, "transtab.initialiseSector(host_extents)",
1349291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                      ttaux_free,
1350291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                      sizeof(HostExtent));
1351291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
13525d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      /* Add an entry in the sector_search_order */
13535d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      for (i = 0; i < N_SECTORS; i++) {
13545d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         if (sector_search_order[i] == -1)
13555d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            break;
13565d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
13575d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      vg_assert(i >= 0 && i < N_SECTORS);
13585d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sector_search_order[i] = sno;
13595d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1360fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
1361738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d\n", sno);
13626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1363fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   } else {
13646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
13656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Sector has been used before.  Dump the old contents. */
136645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(1,"transtab", "recycle sector %d\n", sno);
13676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt != NULL);
13686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tc_next != NULL);
13696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      n_dump_count += sec->tt_n_inuse;
13706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1371291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VexArch vex_arch = VexArch_INVALID;
1372291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(machine_get_VexArchInfo)( &vex_arch, NULL );
1373291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
13746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Visit each just-about-to-be-abandoned translation. */
1375291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjVG_(printf)("QQQ unlink-entire-sector: %d START\n", sno);
1376fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
13776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tt[i].status == InUse) {
13786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec >= 1);
13796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec <= 3);
13806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            n_dump_osize += vge_osize(&sec->tt[i].vge);
13813786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            /* Tell the tool too. */
13820b9d74abd0a663b530d290b2b788ddeda46e5400sewardj            if (VG_(needs).superblock_discards) {
13830b9d74abd0a663b530d290b2b788ddeda46e5400sewardj               VG_TDICT_CALL( tool_discard_superblock_info,
13844ba057cce1d81a949f5a899b5abb99e90a731bccsewardj                              sec->tt[i].entry,
13856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                              sec->tt[i].vge );
13863786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            }
1387291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            unchain_in_preparation_for_deletion(vex_arch, sno, i);
13886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         } else {
13896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec == 0);
13906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
13916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].status   = Empty;
13926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].n_tte2ec = 0;
13936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
1394291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjVG_(printf)("QQQ unlink-entire-sector: %d END\n", sno);
13956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
13966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Free up the eclass structures. */
13976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
13986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->ec2tte_size[i] == 0) {
13996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte_used[i] == 0);
14006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte[i] == NULL);
14016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         } else {
14026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte[i] != NULL);
1403291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            ttaux_free(sec->ec2tte[i]);
14046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte[i] = NULL;
14056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte_size[i] = 0;
14066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte_used[i] = 0;
1407fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
1408fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      }
14096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1410291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Empty out the host extents array. */
1411291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(sec->host_extents != NULL);
1412291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(dropTailXA)(sec->host_extents, VG_(sizeXA)(sec->host_extents));
1413291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(VG_(sizeXA)(sec->host_extents) == 0);
1414291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
14155d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      /* Sanity check: ensure it is already in
14165d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         sector_search_order[]. */
14175d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      for (i = 0; i < N_SECTORS; i++) {
14185d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         if (sector_search_order[i] == sno)
14195d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            break;
14205d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
14215d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      vg_assert(i >= 0 && i < N_SECTORS);
14225d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1423fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
1424738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d\n", sno);
14256c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
14264ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
14276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tc_next = sec->tc;
14286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tt_n_inuse = 0;
1429fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1430fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
14315d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
14325d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   { Bool sane = sanity_check_sector_search_order();
14335d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj     vg_assert(sane);
14345d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
14356c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1436de4a1d01951937632098a6cda45859afa587a06fsewardj
1437de4a1d01951937632098a6cda45859afa587a06fsewardj
1438fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC.  The translation is temporarily
1439fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   in code[0 .. code_len-1].
1440de4a1d01951937632098a6cda45859afa587a06fsewardj
1441fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   pre: youngest_sector points to a valid (although possibly full)
1442fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.
1443fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
14448bddf58af8cc7342d4bde6712c5a6a33bf2850d4njnvoid VG_(add_to_transtab)( VexGuestExtents* vge,
14458bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn                           Addr64           entry,
14468bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn                           AddrH            code,
144726412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                           UInt             code_len,
1448291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                           Bool             is_self_checking,
1449291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                           Int              offs_profInc,
1450291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                           VexArch          arch_host )
145122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{
1452fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int    tcAvailQ, reqdQ, y, i;
14535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   ULong  *tcptr, *tcptr2;
1454fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* srcP;
1455fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* dstP;
1456fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1457663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1458fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
1459e808930793aeddc4cfd3e7a94b665913bec2566csewardj
1460e808930793aeddc4cfd3e7a94b665913bec2566csewardj   /* 60000: should agree with N_TMPBUF in m_translate.c. */
1461e808930793aeddc4cfd3e7a94b665913bec2566csewardj   vg_assert(code_len > 0 && code_len < 60000);
1462fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1463fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (0)
14648bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn      VG_(printf)("add_to_transtab(entry = 0x%llx, len = %d)\n",
1465fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                  entry, code_len);
1466fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1467fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_count++;
1468fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_tsize += code_len;
1469fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_osize += vge_osize(vge);
147026412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   if (is_self_checking)
147126412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj      n_in_sc_count++;
1472fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1473fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   y = youngest_sector;
1474fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(y));
1475fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1476fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sectors[y].tc == NULL)
1477fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
1478fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1479fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Try putting the translation in this sector. */
14805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   reqdQ = (code_len + 7) >> 3;
1481fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1482fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Will it fit in tc? */
1483fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
1484fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
1485fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
1486fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
1487fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1488fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (tcAvailQ < reqdQ
1489fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj       || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR_USABLE) {
1490fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* No.  So move on to the next sector.  Either it's never been
1491fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         used before, in which case it will get its tt/tc allocated
1492fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         now, or it has been used before, in which case it is set to be
1493fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         empty, hence throwing out the oldest sector. */
1494a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj      vg_assert(tc_sector_szQ > 0);
1495a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj      VG_(debugLog)(1,"transtab",
1496a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      "declare sector %d full "
1497a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      "(TT loading %2d%%, TC loading %2d%%)\n",
1498a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      y,
1499a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      (100 * sectors[y].tt_n_inuse)
1500a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                         / N_TTES_PER_SECTOR,
1501a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      (100 * (tc_sector_szQ - tcAvailQ))
1502a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                         / tc_sector_szQ);
1503fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      youngest_sector++;
1504fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (youngest_sector >= N_SECTORS)
1505fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         youngest_sector = 0;
1506fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      y = youngest_sector;
1507fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
1508fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
150922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
1510fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Be sure ... */
1511fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
1512fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
1513fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
1514fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
1515fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= reqdQ);
1516fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR_USABLE);
1517fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse >= 0);
1518fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1519fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Copy into tc. */
15205f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tcptr = sectors[y].tc_next;
15215f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr >= &sectors[y].tc[0]);
15225f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr <= &sectors[y].tc[tc_sector_szQ]);
1523fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
15245f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   dstP = (UChar*)tcptr;
1525fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   srcP = (UChar*)code;
1526291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(memcpy)(dstP, srcP, code_len);
1527fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tc_next += reqdQ;
1528fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt_n_inuse++;
1529fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1530fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* more paranoia */
15315f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tcptr2 = sectors[y].tc_next;
15325f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 >= &sectors[y].tc[0]);
15335f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 <= &sectors[y].tc[tc_sector_szQ]);
1534fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1535fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find an empty tt slot, and use it.  There must be such a slot
1536fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      since tt is never allowed to get completely full. */
1537fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   i = HASH_TT(entry);
1538fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(i >= 0 && i < N_TTES_PER_SECTOR);
153922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj   while (True) {
1540fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[y].tt[i].status == Empty
1541fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          || sectors[y].tt[i].status == Deleted)
1542fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         break;
1543fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      i++;
1544fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (i >= N_TTES_PER_SECTOR)
1545fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         i = 0;
154622854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj   }
1547fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1548291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry__init(&sectors[y].tt[i]);
1549fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].status = InUse;
15505f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   sectors[y].tt[i].tcptr  = tcptr;
1551fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].count  = 0;
1552fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].weight = 1;
1553fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].vge    = *vge;
1554fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].entry  = entry;
1555fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1556291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Patch in the profile counter location, if necessary. */
1557291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (offs_profInc != -1) {
1558291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(offs_profInc >= 0 && offs_profInc < code_len);
1559291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VexInvalRange vir
1560291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         = LibVEX_PatchProfInc( arch_host,
1561291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                dstP + offs_profInc,
1562291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                &sectors[y].tt[i].count );
1563291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(invalidate_icache)( (void*)vir.start, vir.len );
1564291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
1565291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
1566291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( dstP, code_len );
1567291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
1568291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Add this entry to the host_extents map, checking that we're
1569291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      adding in order. */
1570291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   { HostExtent hx;
1571291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.start = (UChar*)tcptr;
1572291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.len   = code_len;
1573291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.tteNo = i;
1574291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     vg_assert(hx.len > 0); /* bsearch fails w/ zero length entries */
1575291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     XArray* hx_array = sectors[y].host_extents;
1576291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     vg_assert(hx_array);
1577291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     Word n = VG_(sizeXA)(hx_array);
1578291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     if (n > 0) {
1579291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        HostExtent* hx_prev = (HostExtent*)VG_(indexXA)(hx_array, n-1);
1580291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        vg_assert(hx_prev->start + hx_prev->len <= hx.start);
1581291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     }
1582291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     VG_(addToXA)(hx_array, &hx);
1583291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
1584291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
15856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Update the fast-cache. */
1586291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   setFastCacheEntry( entry, tcptr );
15876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
15886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Note the eclass numbers for this translation. */
15896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   upd_eclasses_after_add( &sectors[y], i );
159022854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj}
159122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
1592fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1593fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address.  If
1594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   requested, a successful search can also cause the fast-caches to be
1595fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   updated.
1596fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
1597291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool VG_(search_transtab) ( /*OUT*/AddrH* res_hcode,
1598291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                            /*OUT*/UInt*  res_sNo,
1599291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                            /*OUT*/UInt*  res_tteNo,
1600fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                            Addr64        guest_addr,
1601fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                            Bool          upd_cache )
16026c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1603fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int i, j, k, kstart, sno;
1604663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
1605663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1606fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find the initial probe point just once.  It will be the same in
1607fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      all sectors and avoids multiple expensive % operations. */
1608fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_full_lookups++;
1609fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   k      = -1;
1610fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   kstart = HASH_TT(guest_addr);
1611fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(kstart >= 0 && kstart < N_TTES_PER_SECTOR);
1612fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
16135d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Search in all the sectors,using sector_search_order[] as a
16145d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      heuristic guide as to what order to visit the sectors. */
1615fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < N_SECTORS; i++) {
1616fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
16175d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sno = sector_search_order[i];
16185d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (UNLIKELY(sno == -1))
16195d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         return False; /* run out of sectors to search */
1620fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1621fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      k = kstart;
1622fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (j = 0; j < N_TTES_PER_SECTOR; j++) {
1623fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         n_lookup_probes++;
1624fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[k].status == InUse
1625fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             && sectors[sno].tt[k].entry == guest_addr) {
1626fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            /* found it */
1627fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (upd_cache)
1628fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               setFastCacheEntry(
1629291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                  guest_addr, sectors[sno].tt[k].tcptr );
1630291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_hcode)
1631291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj               *res_hcode = (AddrH)sectors[sno].tt[k].tcptr;
1632291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_sNo)
1633291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj               *res_sNo = sno;
1634291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_tteNo)
1635291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj               *res_tteNo = k;
16365d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            /* pull this one one step closer to the front.  For large
16375d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               apps this more or less halves the number of required
16385d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               probes. */
16395d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            if (i > 0) {
16405d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               Int tmp = sector_search_order[i-1];
16415d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               sector_search_order[i-1] = sector_search_order[i];
16425d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               sector_search_order[i] = tmp;
16435d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            }
1644fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            return True;
1645fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
1646fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[k].status == Empty)
1647fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            break; /* not found in this sector */
1648fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         k++;
1649fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (k == N_TTES_PER_SECTOR)
1650fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            k = 0;
16516c3769f487145a08c01b58d6e5db3ba274062ad4sewardj      }
1652fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1653fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* If we fall off the end, all entries are InUse and not
1654fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         matching, or Deleted.  In any case we did not find it in this
1655fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         sector. */
16566c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
1657fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1658fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Not found in any sector. */
1659fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
16606c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1661de4a1d01951937632098a6cda45859afa587a06fsewardj
1662de4a1d01951937632098a6cda45859afa587a06fsewardj
16636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
16646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Delete translations.                                  ---*/
16656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
16666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
16670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* forward */
16680ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void unredir_discard_translations( Addr64, ULong );
16690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
16706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Stuff for deleting translations which intersect with a given
16716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   address range.  Unfortunately, to make this run at a reasonable
16726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   speed, it is complex. */
1673fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1674fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
1675a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlap1 ( Addr64 s1, ULong r1, Addr64 s2, ULong r2 )
16766c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1677a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj   Addr64 e1 = s1 + r1 - 1ULL;
1678a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj   Addr64 e2 = s2 + r2 - 1ULL;
1679fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (e1 < s2 || e2 < s1)
1680fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1681fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
16826c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1683de4a1d01951937632098a6cda45859afa587a06fsewardj
1684fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
1685a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlaps ( Addr64 start, ULong range, VexGuestExtents* vge )
16866c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1687fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[0], (UInt)vge->len[0]))
1688fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1689fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 2)
1690fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1691fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[1], (UInt)vge->len[1]))
1692fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1693fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 3)
1694fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1695fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[2], (UInt)vge->len[2]))
1696fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1697fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
16986c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1699de4a1d01951937632098a6cda45859afa587a06fsewardj
1700de4a1d01951937632098a6cda45859afa587a06fsewardj
17016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete a tt entry, and update all the eclass data accordingly. */
17026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1703291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void delete_tte ( /*MOD*/Sector* sec, UInt secNo, Int tteno,
1704291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                         VexArch vex_arch )
17056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
17066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i, ec_num, ec_idx;
17076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
17086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1709291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* sec and secNo are mutually redundant; cross-check. */
1710291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(sec == &sectors[secNo]);
1711291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
17126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR);
17136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte = &sec->tt[tteno];
17146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tte->status == InUse);
17156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tte->n_tte2ec >= 1 && tte->n_tte2ec <= 3);
17166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Unchain .. */
1718291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   unchain_in_preparation_for_deletion(vex_arch, secNo, tteno);
1719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
17206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Deal with the ec-to-tte links first. */
17216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < tte->n_tte2ec; i++) {
17226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec_num = (Int)tte->tte2ec_ec[i];
17236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec_idx = tte->tte2ec_ix[i];
17246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_num >= 0 && ec_num < ECLASS_N);
17256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_idx >= 0);
17266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_idx < sec->ec2tte_used[ec_num]);
17276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Assert that the two links point at each other. */
17286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->ec2tte[ec_num][ec_idx] == (UShort)tteno);
17296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* "delete" the pointer back to here. */
17306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte[ec_num][ec_idx] = EC2TTE_DELETED;
17316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
17326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Now fix up this TTEntry. */
17346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->status   = Deleted;
17356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->n_tte2ec = 0;
17366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Stats .. */
17386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tt_n_inuse--;
17396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_disc_count++;
17406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_disc_osize += vge_osize(&tte->vge);
17416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Tell the tool too. */
17430b9d74abd0a663b530d290b2b788ddeda46e5400sewardj   if (VG_(needs).superblock_discards) {
17440b9d74abd0a663b530d290b2b788ddeda46e5400sewardj      VG_TDICT_CALL( tool_discard_superblock_info,
17454ba057cce1d81a949f5a899b5abb99e90a731bccsewardj                     tte->entry,
17466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                     tte->vge );
17476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
17486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
17496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, but
17526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   only consider translations in the specified eclass. */
17536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
1755291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool delete_translations_in_sector_eclass ( /*MOD*/Sector* sec, UInt secNo,
17566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                            Addr64 guest_start, ULong range,
1757291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                            Int ec,
1758291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                            VexArch vex_arch )
17596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
17606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i;
17616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort   tteno;
17626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool     anyDeld = False;
17636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
17646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(ec >= 0 && ec < ECLASS_N);
17666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < sec->ec2tte_used[ec]; i++) {
17686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tteno = sec->ec2tte[ec][i];
17706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tteno == EC2TTE_DELETED) {
17716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         /* already deleted */
17726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
17736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
17746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tteno < N_TTES_PER_SECTOR);
17766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte = &sec->tt[tteno];
17786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tte->status == InUse);
17796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (overlaps( guest_start, range, &tte->vge )) {
17816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeld = True;
1782291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         delete_tte( sec, secNo, (Int)tteno, vex_arch );
17836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
17846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
17866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return anyDeld;
17886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
17896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, the
17926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   slow way, by inspecting all translations in sec. */
17936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
1795291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool delete_translations_in_sector ( /*MOD*/Sector* sec, UInt secNo,
1796291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                     Addr64 guest_start, ULong range,
1797291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                     VexArch vex_arch )
17986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
17996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int  i;
18006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool anyDeld = False;
18016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < N_TTES_PER_SECTOR; i++) {
18036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->tt[i].status == InUse
18046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj          && overlaps( guest_start, range, &sec->tt[i].vge )) {
18056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeld = True;
1806291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         delete_tte( sec, secNo, i, vex_arch );
18076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
18086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
18096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return anyDeld;
18116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
18126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
181445f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid VG_(discard_translations) ( Addr64 guest_start, ULong range,
181545f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                 HChar* who )
18166c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
18176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
18186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int     sno, ec;
18196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool    anyDeleted = False;
18206c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1821663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1822663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
1823a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj   VG_(debugLog)(2, "transtab",
182445f4e7c91119c7d01a59f5e827c67841632c9314sewardj                    "discard_translations(0x%llx, %lld) req by %s\n",
182545f4e7c91119c7d01a59f5e827c67841632c9314sewardj                    guest_start, range, who );
182645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
18276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Pre-deletion sanity check */
18286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (VG_(clo_sanity_level >= 4)) {
18296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Bool sane = sanity_check_all_sectors();
18306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sane);
18316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
18326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (range == 0)
18346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return;
18356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1836291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexArch vex_arch = VexArch_INVALID;
1837291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(machine_get_VexArchInfo)( &vex_arch, NULL );
1838291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
18396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* There are two different ways to do this.
18406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      If the range fits within a single address-range equivalence
18426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class, as will be the case for a cache line sized invalidation,
18436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      then we only have to inspect the set of translations listed in
18446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      that equivalence class, and also in the "sin-bin" equivalence
18456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class ECLASS_MISC.
18466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Otherwise, the invalidation is of a larger range and probably
18486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      results from munmap.  In this case it's (probably!) faster just
18496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      to inspect all translations, dump those we don't want, and
18506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      regenerate the equivalence class information (since modifying it
18516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      in-situ is even more expensive).
18526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   */
18536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* First off, figure out if the range falls within a single class,
18556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      and if so which one. */
18566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   ec = ECLASS_MISC;
18586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (range < (1ULL << ECLASS_SHIFT))
18596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec = range_to_eclass( guest_start, (UInt)range );
18606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* if ec is ECLASS_MISC then we aren't looking at just a single
18626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class, so use the slow scheme.  Else use the fast scheme,
18636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      examining 'ec' and ECLASS_MISC. */
18646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (ec != ECLASS_MISC) {
18666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(2, "transtab",
18686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                       "                    FAST, ec = %d\n", ec);
18696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Fast scheme */
18716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec >= 0 && ec < ECLASS_MISC);
18726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (sno = 0; sno < N_SECTORS; sno++) {
18746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
18756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
18766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
18776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector_eclass(
1878291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          sec, sno, guest_start, range, ec,
1879291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          vex_arch
1880291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       );
18816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector_eclass(
1882291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          sec, sno, guest_start, range, ECLASS_MISC,
1883291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          vex_arch
1884291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       );
18856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
18866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   } else {
18886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* slow scheme */
18906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(2, "transtab",
18926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                       "                    SLOW, ec = %d\n", ec);
18936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (sno = 0; sno < N_SECTORS; sno++) {
18956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
18966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
18976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
18986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector(
1899291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          sec, sno, guest_start, range, vex_arch );
19006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
19016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1902de4a1d01951937632098a6cda45859afa587a06fsewardj   }
1903de4a1d01951937632098a6cda45859afa587a06fsewardj
1904fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (anyDeleted)
1905fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      invalidateFastCache();
19066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* don't forget the no-redir cache */
19080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_discard_translations( guest_start, range );
19090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Post-deletion sanity check */
19116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (VG_(clo_sanity_level >= 4)) {
19126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int      i;
19136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      TTEntry* tte;
19146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Bool     sane = sanity_check_all_sectors();
19156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sane);
19166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* But now, also check the requested address range isn't
19176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         present anywhere. */
19186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (sno = 0; sno < N_SECTORS; sno++) {
19196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
19206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
19216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
19226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         for (i = 0; i < N_TTES_PER_SECTOR; i++) {
19236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            tte = &sec->tt[i];
19246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (tte->status != InUse)
19256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               continue;
19266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(!overlaps( guest_start, range, &tte->vge ));
19276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
19286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
19296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
1930fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
19316c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
19326c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1933fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
19340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*--- AUXILIARY: the unredirected TT/TC                    ---*/
19350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/
19360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* A very simple translation cache which holds a small number of
19380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredirected translations.  This is completely independent of the
19390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   main tt/tc structures.  When unredir_tc or unredir_tt becomes full,
19400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   both structures are simply dumped and we start over.
19410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Since these translations are unredirected, the search key is (by
19430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   definition) the first address entry in the .vge field. */
19440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Sized to hold 500 translations of average size 1000 bytes. */
19460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define UNREDIR_SZB   1000
19480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TT  500
19500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TCQ (N_UNREDIR_TT * UNREDIR_SZB / sizeof(ULong))
19510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19520ec07f32bbbb209d749b9974408e6f025ad40b31sewardjtypedef
19530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   struct {
19540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      VexGuestExtents vge;
19550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      Addr            hcode;
19560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      Bool            inUse;
19570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
19580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   UTCEntry;
19590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* We just allocate forwards in _tc, never deleting. */
196178c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic ULong    *unredir_tc;
196278c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic Int      unredir_tc_used = N_UNREDIR_TCQ;
19630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Slots in _tt can come into use and out again (.inUse).
19650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Nevertheless _tt_highwater is maintained so that invalidations
19660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   don't have to scan all the slots when only a few are in use.
19670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   _tt_highwater holds the index of the highest ever allocated
19680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   slot. */
19690ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic UTCEntry unredir_tt[N_UNREDIR_TT];
19700ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Int      unredir_tt_highwater;
19710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19730ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void init_unredir_tt_tc ( void )
19740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
19750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
197678c0c09d429c95115e826ef769ecaa6cff2ac338tom   if (unredir_tc == NULL) {
1977cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      SysRes sres = VG_(am_mmap_anon_float_valgrind)
1978cda2f0fbda4c4b2644babc830244be8aed95de1dnjn                       ( N_UNREDIR_TT * UNREDIR_SZB );
1979cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
1980cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         VG_(out_of_memory_NORETURN)("init_unredir_tt_tc",
1981cda2f0fbda4c4b2644babc830244be8aed95de1dnjn                                     N_UNREDIR_TT * UNREDIR_SZB);
198278c0c09d429c95115e826ef769ecaa6cff2ac338tom         /*NOTREACHED*/
198378c0c09d429c95115e826ef769ecaa6cff2ac338tom      }
1984cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      unredir_tc = (ULong *)(AddrH)sr_Res(sres);
198578c0c09d429c95115e826ef769ecaa6cff2ac338tom   }
19860ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tc_used = 0;
19870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++)
19880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      unredir_tt[i].inUse = False;
19890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt_highwater = -1;
19900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
19910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Do a sanity check; return False on failure. */
19930ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void )
19940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
19950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
19960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tt_highwater < -1) return False;
19970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tt_highwater >= N_UNREDIR_TT) return False;
19980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = unredir_tt_highwater+1; i < N_UNREDIR_TT; i++)
20000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].inUse)
20010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         return False;
20020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tc_used < 0) return False;
20040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tc_used > N_UNREDIR_TCQ) return False;
20050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   return True;
20070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
20080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Add an UNREDIRECTED translation of vge to TT/TC.  The translation
20110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   is temporarily in code[0 .. code_len-1].
20120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj*/
20130ec07f32bbbb209d749b9974408e6f025ad40b31sewardjvoid VG_(add_to_unredir_transtab)( VexGuestExtents* vge,
20140ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                   Addr64           entry,
20150ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                   AddrH            code,
20161dcee097db02f9ef3ba355162c4373d90d0e895cnjn                                   UInt             code_len )
20170ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
20180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int   i, j, code_szQ;
20190ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   HChar *srcP, *dstP;
20200ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(sanity_check_redir_tt_tc());
20220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* This is the whole point: it's not redirected! */
20240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(entry == vge->base[0]);
20250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* How many unredir_tt slots are needed */
20270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   code_szQ = (code_len + 7) / 8;
20280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* Look for an empty unredir_tc slot */
20300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++)
20310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (!unredir_tt[i].inUse)
20320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         break;
20330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (i >= N_UNREDIR_TT || code_szQ > (N_UNREDIR_TCQ - unredir_tc_used)) {
20350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      /* It's full; dump everything we currently have */
20360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      init_unredir_tt_tc();
20370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      i = 0;
20380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
20390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used >= 0);
20410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used <= N_UNREDIR_TCQ);
20420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(code_szQ > 0);
20430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(code_szQ + unredir_tc_used <= N_UNREDIR_TCQ);
20440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(i >= 0 && i < N_UNREDIR_TT);
20450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tt[i].inUse == False);
20460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (i > unredir_tt_highwater)
20480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      unredir_tt_highwater = i;
20490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   dstP = (HChar*)&unredir_tc[unredir_tc_used];
20510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   srcP = (HChar*)code;
20520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (j = 0; j < code_len; j++)
20530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      dstP[j] = srcP[j];
20540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
2055291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( dstP, code_len );
2056c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj
20570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].inUse = True;
20580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].vge   = *vge;
20590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].hcode = (Addr)dstP;
20600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tc_used += code_szQ;
20620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used >= 0);
20630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used <= N_UNREDIR_TCQ);
20640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(&dstP[code_len] <= (HChar*)&unredir_tc[unredir_tc_used]);
20660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
20670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20680ec07f32bbbb209d749b9974408e6f025ad40b31sewardjBool VG_(search_unredir_transtab) ( /*OUT*/AddrH* result,
20690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                    Addr64        guest_addr )
20700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
20710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
20720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++) {
20730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (!unredir_tt[i].inUse)
20740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         continue;
20750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].vge.base[0] == guest_addr) {
20760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         *result = (AddrH)unredir_tt[i].hcode;
20770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         return True;
20780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      }
20790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
20800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   return False;
20810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
20820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20830ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void unredir_discard_translations( Addr64 guest_start, ULong range )
20840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
20850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
20860ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(sanity_check_redir_tt_tc());
20880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i <= unredir_tt_highwater; i++) {
20900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].inUse
20910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj          && overlaps( guest_start, range, &unredir_tt[i].vge))
20920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         unredir_tt[i].inUse = False;
20930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
20940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
20950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/
2098fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation.                                      ---*/
2099fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2100fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2101fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void )
21026c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
21036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, j, avg_codeszQ;
2104de4a1d01951937632098a6cda45859afa587a06fsewardj
2105663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(!init_done);
2106663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   init_done = True;
2107663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
2108fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Otherwise lots of things go wrong... */
2109fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sizeof(ULong) == 8);
2110fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sizeof(Addr64) == 8);
21115f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache entries really are 2 words long */
21125f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof(Addr) == sizeof(void*));
21135f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof(FastCacheEntry) == 2 * sizeof(Addr));
21145f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache entries are packed back-to-back with no spaces */
21155f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof( VG_(tt_fast) ) == VG_TT_FAST_SIZE * sizeof(FastCacheEntry));
21165f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache is aligned as we requested.  Not fatal if it
21175f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      isn't, but we might as well make sure. */
21185f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_IS_16_ALIGNED( ((Addr) & VG_(tt_fast)[0]) ));
2119de4a1d01951937632098a6cda45859afa587a06fsewardj
2120fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (VG_(clo_verbosity) > 2)
2121fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2122fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                   "TT/TC: VG_(init_tt_tc) "
2123738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                   "(startup of code management)\n");
2124fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2125fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Figure out how big each tc area should be.  */
212643b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   avg_codeszQ   = (VG_(details).avg_translation_sizeB + 7) / 8;
212743b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   tc_sector_szQ = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ);
2128fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2129fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Ensure the calculated value is not way crazy. */
2130fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR_USABLE);
21311e0fff690e9c571275e8025eb2dcff7bf29b53afsewardj   vg_assert(tc_sector_szQ <= 100 * N_TTES_PER_SECTOR_USABLE);
2132fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2133fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Initialise the sectors */
2134fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest_sector = 0;
2135fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < N_SECTORS; i++) {
2136fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tc = NULL;
2137fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tt = NULL;
2138fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tc_next = NULL;
2139fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tt_n_inuse = 0;
21406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < ECLASS_N; j++) {
21416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sectors[i].ec2tte_size[j] = 0;
21426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sectors[i].ec2tte_used[j] = 0;
21436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sectors[i].ec2tte[j] = NULL;
21446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
2145291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      sectors[i].host_extents = NULL;
21466c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
21474ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
21485d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Initialise the sector_search_order hint table. */
21495d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   for (i = 0; i < N_SECTORS; i++)
21505d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sector_search_order[i] = -1;
21515d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
2152291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Initialise the fast cache. */
2153fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
2154fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
21550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* and the unredir tt/tc */
21560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   init_unredir_tt_tc();
21570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
2158fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (VG_(clo_verbosity) > 2) {
2159fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2160738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         "TT/TC: cache: %d sectors of %d bytes each = %d total\n",
2161fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          N_SECTORS, 8 * tc_sector_szQ,
2162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          N_SECTORS * 8 * tc_sector_szQ );
2163fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2164738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         "TT/TC: table: %d total entries, max occupancy %d (%d%%)\n",
2165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         N_SECTORS * N_TTES_PER_SECTOR,
2166fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         N_SECTORS * N_TTES_PER_SECTOR_USABLE,
2167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         SECTOR_TT_LIMIT_PERCENT );
2168fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
216945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
217045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "transtab",
217145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      "cache: %d sectors of %d bytes each = %d total\n",
217245f4e7c91119c7d01a59f5e827c67841632c9314sewardj       N_SECTORS, 8 * tc_sector_szQ,
217345f4e7c91119c7d01a59f5e827c67841632c9314sewardj       N_SECTORS * 8 * tc_sector_szQ );
217445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "transtab",
217545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      "table: %d total entries, max occupancy %d (%d%%)\n",
217645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      N_SECTORS * N_TTES_PER_SECTOR,
217745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      N_SECTORS * N_TTES_PER_SECTOR_USABLE,
217845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      SECTOR_TT_LIMIT_PERCENT );
2179de4a1d01951937632098a6cda45859afa587a06fsewardj}
2180de4a1d01951937632098a6cda45859afa587a06fsewardj
21814ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
2182fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2183fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics.                             ---*/
2184fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2185fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2186fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong safe_idiv( ULong a, ULong b )
218792e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
218892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   return (b == 0 ? 0 : a / b);
218992e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
219092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote
2191fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void )
2192fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
2193fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n_in_count;
2194fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
2195fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2196fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void )
219792e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
219892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2199738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      "    tt/tc: %'llu tt lookups requiring %'llu probes\n",
2200fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_full_lookups, n_lookup_probes );
220192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2202738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      "    tt/tc: %'llu fast-cache updates, %'llu flushes\n",
2203fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_fast_updates, n_fast_flushes );
2204fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
220592e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2206a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                " transtab: new        %'lld "
2207738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                "(%'llu -> %'llu; ratio %'llu:10) [%'llu scs]\n",
2208fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_in_count, n_in_osize, n_in_tsize,
220926412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                safe_idiv(10*n_in_tsize, n_in_osize),
221026412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                n_in_sc_count);
221192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2212738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                " transtab: dumped     %'llu (%'llu -> ?" "?)\n",
2213fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_dump_count, n_dump_osize );
2214fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   VG_(message)(Vg_DebugMsg,
2215738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                " transtab: discarded  %'llu (%'llu -> ?" "?)\n",
2216fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_disc_count, n_disc_osize );
22176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
22186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (0) {
22196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int i;
22206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(printf)("\n");
22216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
22226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         VG_(printf)(" %4d", sectors[0].ec2tte_used[i]);
22236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (i % 16 == 15)
22246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            VG_(printf)("\n");
22256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
22266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(printf)("\n\n");
22276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
222892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
2229de4a1d01951937632098a6cda45859afa587a06fsewardj
2230fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2231fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results.                   ---*/
2232fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
22334ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
2234fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong score ( TTEntry* tte )
2235fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
2236fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return ((ULong)tte->weight) * ((ULong)tte->count);
2237de4a1d01951937632098a6cda45859afa587a06fsewardj}
2238de4a1d01951937632098a6cda45859afa587a06fsewardj
22392025cf98a3210c175a90fc77cb599cca1643bd68njnULong VG_(get_BB_profile) ( BBProfEntry tops[], UInt n_tops )
2240de4a1d01951937632098a6cda45859afa587a06fsewardj{
2241fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int   sno, i, r, s;
22422025cf98a3210c175a90fc77cb599cca1643bd68njn   ULong score_total;
2243fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2244fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* First, compute the total weighted count, and find the top N
22452025cf98a3210c175a90fc77cb599cca1643bd68njn      ttes.  tops contains pointers to the most-used n_tops blocks, in
2246fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      descending order (viz, tops[0] is the highest scorer). */
22472025cf98a3210c175a90fc77cb599cca1643bd68njn   for (i = 0; i < n_tops; i++) {
22482025cf98a3210c175a90fc77cb599cca1643bd68njn      tops[i].addr  = 0;
22492025cf98a3210c175a90fc77cb599cca1643bd68njn      tops[i].score = 0;
22502025cf98a3210c175a90fc77cb599cca1643bd68njn   }
2251fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2252fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   score_total = 0;
2253fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2254fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (sno = 0; sno < N_SECTORS; sno++) {
2255fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[sno].tc == NULL)
225618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         continue;
2257fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
2258fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[i].status != InUse)
2259fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            continue;
2260fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         score_total += score(&sectors[sno].tt[i]);
2261fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* Find the rank for sectors[sno].tt[i]. */
22622025cf98a3210c175a90fc77cb599cca1643bd68njn         r = n_tops-1;
2263fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         while (True) {
2264fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (r == -1)
2265fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               break;
22662025cf98a3210c175a90fc77cb599cca1643bd68njn             if (tops[r].addr == 0) {
2267fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               r--;
2268fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               continue;
2269fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
22702025cf98a3210c175a90fc77cb599cca1643bd68njn             if ( score(&sectors[sno].tt[i]) > tops[r].score ) {
2271fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                r--;
2272fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                continue;
2273fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
2274fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             break;
2275fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
2276fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         r++;
22772025cf98a3210c175a90fc77cb599cca1643bd68njn         vg_assert(r >= 0 && r <= n_tops);
2278fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* This bb should be placed at r, and bbs above it shifted
2279fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            upwards one slot. */
22802025cf98a3210c175a90fc77cb599cca1643bd68njn         if (r < n_tops) {
22812025cf98a3210c175a90fc77cb599cca1643bd68njn            for (s = n_tops-1; s > r; s--)
2282fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               tops[s] = tops[s-1];
22832025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].addr  = sectors[sno].tt[i].entry;
22842025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].score = score( &sectors[sno].tt[i] );
2285fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
2286de4a1d01951937632098a6cda45859afa587a06fsewardj      }
2287de4a1d01951937632098a6cda45859afa587a06fsewardj   }
2288de4a1d01951937632098a6cda45859afa587a06fsewardj
22892025cf98a3210c175a90fc77cb599cca1643bd68njn   return score_total;
2290c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
2291c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
2292de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
22938bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end                                                          ---*/
2294de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
2295