m_transtab.c revision 523b5b8ca67d2063afd02342d0138b0dc0ed6706
1de4a1d01951937632098a6cda45859afa587a06fsewardj
2de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
3de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- Management of the translation table and cache.               ---*/
48bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*---                                                 m_transtab.c ---*/
5de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
6de4a1d01951937632098a6cda45859afa587a06fsewardj
7de4a1d01951937632098a6cda45859afa587a06fsewardj/*
8b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn   This file is part of Valgrind, a dynamic binary instrumentation
9b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn   framework.
10de4a1d01951937632098a6cda45859afa587a06fsewardj
110f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj   Copyright (C) 2000-2013 Julian Seward
12de4a1d01951937632098a6cda45859afa587a06fsewardj      jseward@acm.org
13de4a1d01951937632098a6cda45859afa587a06fsewardj
14de4a1d01951937632098a6cda45859afa587a06fsewardj   This program is free software; you can redistribute it and/or
15de4a1d01951937632098a6cda45859afa587a06fsewardj   modify it under the terms of the GNU General Public License as
16de4a1d01951937632098a6cda45859afa587a06fsewardj   published by the Free Software Foundation; either version 2 of the
17de4a1d01951937632098a6cda45859afa587a06fsewardj   License, or (at your option) any later version.
18de4a1d01951937632098a6cda45859afa587a06fsewardj
19de4a1d01951937632098a6cda45859afa587a06fsewardj   This program is distributed in the hope that it will be useful, but
20de4a1d01951937632098a6cda45859afa587a06fsewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21de4a1d01951937632098a6cda45859afa587a06fsewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22de4a1d01951937632098a6cda45859afa587a06fsewardj   General Public License for more details.
23de4a1d01951937632098a6cda45859afa587a06fsewardj
24de4a1d01951937632098a6cda45859afa587a06fsewardj   You should have received a copy of the GNU General Public License
25de4a1d01951937632098a6cda45859afa587a06fsewardj   along with this program; if not, write to the Free Software
26de4a1d01951937632098a6cda45859afa587a06fsewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27de4a1d01951937632098a6cda45859afa587a06fsewardj   02111-1307, USA.
28de4a1d01951937632098a6cda45859afa587a06fsewardj
29e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   The GNU General Public License is contained in the file COPYING.
30de4a1d01951937632098a6cda45859afa587a06fsewardj*/
31de4a1d01951937632098a6cda45859afa587a06fsewardj
32c7561b931e249acf3768ead77638545b0ccaa8f1njn#include "pub_core_basics.h"
3345f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_debuglog.h"
34291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_machine.h"    // For VG_(machine_get_VexArchInfo)
3597405b2d134b52880d6dbec3eb2929e2002c2542njn#include "pub_core_libcbase.h"
36291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_vki.h"        // to keep pub_core_libproc.h happy, sigh
37291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_libcproc.h"   // VG_(invalidate_icache)
38132bfccd21960e462352175f8553a5bdce8a210cnjn#include "pub_core_libcassert.h"
3936a20fa5f779a0a6fb7b4a90dcaa6376481f1faanjn#include "pub_core_libcprint.h"
402024234c590f408994b373abfb00bc2cd2a90c48njn#include "pub_core_options.h"
4110f08cf5b84882eebbb6712a7be890577650e8adsewardj#include "pub_core_tooliface.h"  // For VG_(details).avg_translation_sizeB
428bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn#include "pub_core_transtab.h"
4345f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_aspacemgr.h"
4445f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_mallocfree.h" // VG_(out_of_memory_NORETURN)
45291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_xarray.h"
46291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_dispatch.h"   // For VG_(disp_cp*) addresses
4759570ffbe31930ab4d678754daaeec0715117a3dsewardj
4859570ffbe31930ab4d678754daaeec0715117a3dsewardj
493a5322057616d0da214b9e0f897866e203c03e40philippe#define DEBUG_TRANSTAB 0
5018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj
51de4a1d01951937632098a6cda45859afa587a06fsewardj
526c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/
536c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*--- Management of the FIFO-based translation table+cache. ---*/
546c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/
55de4a1d01951937632098a6cda45859afa587a06fsewardj
568e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe/* Nr of sectors provided via command line parameter. */
578e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippeUInt VG_(clo_num_transtab_sectors) = N_SECTORS_DEFAULT;
588e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe/* Nr of sectors.
598e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   Will be set by VG_(init_tt_tc) to VG_(clo_num_transtab_sectors). */
60523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic SECno n_sectors = 0;
61de4a1d01951937632098a6cda45859afa587a06fsewardj
62924c852b5883a7b42298dc8c7542116bd9a8a485philippe/* Average size of a transtab code entry. 0 means to use the tool
63924c852b5883a7b42298dc8c7542116bd9a8a485philippe   provided default. */
64924c852b5883a7b42298dc8c7542116bd9a8a485philippeUInt VG_(clo_avg_transtab_entry_size) = 0;
65924c852b5883a7b42298dc8c7542116bd9a8a485philippe
668e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe/*------------------ CONSTANTS ------------------*/
67bece82eba7ba26398a673def2fa326341c4f8ef7philippe/* Number of entries in hash table of each sector.  This needs to be a prime
68bece82eba7ba26398a673def2fa326341c4f8ef7philippe   number to work properly, it must be <= 65535 (so that a TTE index
69bece82eba7ba26398a673def2fa326341c4f8ef7philippe   fits in a UShort, leaving room for 0xFFFF(EC2TTE_DELETED, HTT_DELETED)
70bece82eba7ba26398a673def2fa326341c4f8ef7philippe   to denote 'deleted') and  0xFFFE (HTT_EMPTY) to denote 'Empty' in the
71bece82eba7ba26398a673def2fa326341c4f8ef7philippe   hash table.
72bece82eba7ba26398a673def2fa326341c4f8ef7philippe   It is strongly recommended not to change this.
736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   65521 is the largest prime <= 65535. */
74bece82eba7ba26398a673def2fa326341c4f8ef7philippe#define N_HTTES_PER_SECTOR /*10007*/ /*30011*/ /*40009*/ 65521
75bece82eba7ba26398a673def2fa326341c4f8ef7philippe
76bece82eba7ba26398a673def2fa326341c4f8ef7philippe#define EC2TTE_DELETED  0xFFFF /* 16-bit special value */
77bece82eba7ba26398a673def2fa326341c4f8ef7philippe#define HTT_DELETED     EC2TTE_DELETED
78bece82eba7ba26398a673def2fa326341c4f8ef7philippe#define HTT_EMPTY       0XFFFE
79de4a1d01951937632098a6cda45859afa587a06fsewardj
80523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe// HTTno is the Sector->htt hash table index. Must be the same type as TTEno.
81523b5b8ca67d2063afd02342d0138b0dc0ed6706philippetypedef UShort HTTno;
82523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe
83fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to
84fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   specify the maximum allowable loading, after which the sector is
85fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   deemed full. */
865d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj#define SECTOR_TT_LIMIT_PERCENT 65
87de4a1d01951937632098a6cda45859afa587a06fsewardj
88fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */
89bece82eba7ba26398a673def2fa326341c4f8ef7philippe#define N_TTES_PER_SECTOR \
90bece82eba7ba26398a673def2fa326341c4f8ef7philippe           ((N_HTTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100)
916c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Equivalence classes for fast address range deletion.  There are 1 +
936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   2^ECLASS_WIDTH bins.  The highest one, ECLASS_MISC, describes an
946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   address range which does not fall cleanly within any specific bin.
956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Note that ECLASS_SHIFT + ECLASS_WIDTH must be < 32. */
966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_SHIFT 11
976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_WIDTH 8
986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_MISC  (1 << ECLASS_WIDTH)
996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_N     (1 + ECLASS_MISC)
1006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
102de4a1d01951937632098a6cda45859afa587a06fsewardj
1036c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/
104de4a1d01951937632098a6cda45859afa587a06fsewardj
105291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* In edges ("to-me") in the graph created by chaining. */
106291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
107291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
108523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      SECno from_sNo;   /* sector number */
109523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      TTEno from_tteNo; /* TTE number in given sector */
110523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      UInt  from_offs;  /* code offset from TCEntry::tcptr where the patch is */
111523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      Bool  to_fastEP;  /* Is the patch to a fast or slow entry point? */
112291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
113291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge;
114291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
115291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
116291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Out edges ("from-me") in the graph created by chaining. */
117291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
118291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
119523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      SECno to_sNo;    /* sector number */
120523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      TTEno to_tteNo;  /* TTE number in given sector */
121523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      UInt  from_offs; /* code offset in owning translation where patch is */
122291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
123291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge;
124291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
125291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
126291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_IN_EDGE_ARR 3
127291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
128291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
129291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt     n_fixed; /* 0 .. N_FIXED_IN_EDGE_ARR */
130291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdge   fixed[N_FIXED_IN_EDGE_ARR];
131291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray*  var; /* XArray* of InEdgeArr */
132291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
133291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr;
134291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
135291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_OUT_EDGE_ARR 2
136291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
137291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
138291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt    n_fixed; /* 0 .. N_FIXED_OUT_EDGE_ARR */
139291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdge fixed[N_FIXED_OUT_EDGE_ARR];
140291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray* var; /* XArray* of OutEdgeArr */
141291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
142291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr;
143291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
144291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
145fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry.  This indicates precisely which areas of
146fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   guest code are included in the translation, and contains all other
147fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   auxiliary info too.  */
1486c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef
1496c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   struct {
150bece82eba7ba26398a673def2fa326341c4f8ef7philippe      union {
151bece82eba7ba26398a673def2fa326341c4f8ef7philippe         struct {
152bece82eba7ba26398a673def2fa326341c4f8ef7philippe            /* Profiling only: the count and weight (arbitrary meaning) for
153bece82eba7ba26398a673def2fa326341c4f8ef7philippe               this translation.  Weight is a property of the translation
154bece82eba7ba26398a673def2fa326341c4f8ef7philippe               itself and computed once when the translation is created.
155bece82eba7ba26398a673def2fa326341c4f8ef7philippe               Count is an entry count for the translation and is
156bece82eba7ba26398a673def2fa326341c4f8ef7philippe               incremented by 1 every time the translation is used, if we
157bece82eba7ba26398a673def2fa326341c4f8ef7philippe               are profiling. */
158bece82eba7ba26398a673def2fa326341c4f8ef7philippe            ULong    count;
159bece82eba7ba26398a673def2fa326341c4f8ef7philippe            UShort   weight;
160bece82eba7ba26398a673def2fa326341c4f8ef7philippe         } prof; // if status == InUse
161523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         TTEno next_empty_tte; // if status != InUse
162bece82eba7ba26398a673def2fa326341c4f8ef7philippe      } usage;
163fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
164fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Status of the slot.  Note, we need to be able to do lazy
165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         deletion, hence the Deleted state. */
166fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      enum { InUse, Deleted, Empty } status;
167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1685f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      /* 64-bit aligned pointer to one or more 64-bit words containing
1695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         the corresponding host code (must be in the same sector!)
1705f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         This is a pointer into the sector's tc (code) area. */
1715f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      ULong* tcptr;
172fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
173fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This is the original guest address that purportedly is the
174fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         entry point of the translation.  You might think that .entry
175fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         should be the same as .vge->base[0], and most of the time it
176fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         is.  However, when doing redirections, that is not the case.
177fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         .vge must always correctly describe the guest code sections
178fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         from which this translation was made.  However, .entry may or
179fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         may not be a lie, depending on whether or not we're doing
180fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         redirection. */
181ddd61ff058f02059064e083a8accaefed23d5548florian      Addr entry;
182fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
183fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This structure describes precisely what ranges of guest code
184fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         the translation covers, so we can decide whether or not to
185fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         delete it when translations of a given address range are
186fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         invalidated. */
187fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VexGuestExtents vge;
1886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Address range summary info: these are pointers back to
1906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         eclass[] entries in the containing Sector.  Those entries in
1916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         turn point back here -- the two structures are mutually
1926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         redundant but both necessary to make fast deletions work.
1936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         The eclass info is similar to, and derived from, this entry's
1946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         'vge' field, but it is not the same */
1956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort n_tte2ec;      // # tte2ec pointers (1 to 3)
1966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort tte2ec_ec[3];  // for each, the eclass #
1976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UInt   tte2ec_ix[3];  // and the index within the eclass.
1986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // for i in 0 .. n_tte2ec-1
1996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      //    sec->ec2tte[ tte2ec_ec[i] ][ tte2ec_ix[i] ]
2006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // should be the index
2016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // of this TTEntry in the containing Sector's tt array.
202291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
203291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Admin information for chaining.  'in_edges' is a set of the
204291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         patch points which jump to this translation -- hence are
205291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         predecessors in the control flow graph.  'out_edges' points
206291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         to successors in the control flow graph -- translations to
207291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         which this one has a patched jump.  In short these are just
208291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         backwards and forwards edges in the graph of patched-together
209291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         blocks.  The 'in_edges' contain slightly more info, enough
210291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         that we can undo the chaining of each mentioned patch point.
211291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The 'out_edges' list exists only so that we can visit the
212291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         'in_edges' entries of all blocks we're patched through to, in
213291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         order to remove ourselves from then when we're deleted. */
214291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
215291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* A translation can disappear for two reasons:
216291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj          1. erased (as part of the oldest sector cleanup) when the
217291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             youngest sector is full.
218291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj          2. discarded due to calls to VG_(discard_translations).
219291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             VG_(discard_translations) sets the status of the
220291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             translation to 'Deleted'.
221291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             A.o., the gdbserver discards one or more translations
222291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             when a breakpoint is inserted or removed at an Addr,
223291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             or when single stepping mode is enabled/disabled
224291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             or when a translation is instrumented for gdbserver
225291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             (all the target jumps of this translation are
226291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj              invalidated).
227291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
228291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         So, it is possible that the translation A to be patched
229291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (to obtain a patched jump from A to B) is invalidated
230291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         after B is translated and before A is patched.
231291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         In case a translation is erased or discarded, the patching
232291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         cannot be done.  VG_(tt_tc_do_chaining) and find_TTEntry_from_hcode
233291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         are checking the 'from' translation still exists before
234291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         doing the patching.
235291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
236291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Is it safe to erase or discard the current translation E being
237291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         executed ? Amazing, but yes, it is safe.
238291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Here is the explanation:
239291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
240291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The translation E being executed can only be erased if a new
241291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation N is being done. A new translation is done only
242291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if the host addr is a not yet patched jump to another
243291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation. In such a case, the guest address of N is
244291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         assigned to the PC in the VEX state. Control is returned
245291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         to the scheduler. N will be translated. This can erase the
246291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation E (in case of sector full). VG_(tt_tc_do_chaining)
247291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         will not do the chaining to a non found translation E.
248291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The execution will continue at the current guest PC
249291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (i.e. the translation N).
250291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         => it is safe to erase the current translation being executed.
251291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
252291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The current translation E being executed can also be discarded
253291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (e.g. by gdbserver). VG_(discard_translations) will mark
254291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         this translation E as Deleted, but the translation itself
255291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         is not erased. In particular, its host code can only
256291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         be overwritten or erased in case a new translation is done.
257291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         A new translation will only be done if a not yet translated
258291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         jump is to be executed. The execution of the Deleted translation
259291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         E will continue till a non patched jump is encountered.
260291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         This situation is then similar to the 'erasing' case above :
261291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         the current translation E can be erased or overwritten, as the
262291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         execution will continue at the new translation N.
263291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
264291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      */
265291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
266291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* It is possible, although very unlikely, that a block A has
267291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         more than one patched jump to block B.  This could happen if
268291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (eg) A finishes "jcond B; jmp B".
269291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
270291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         This means in turn that B's in_edges set can list A more than
271291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         once (twice in this example).  However, each such entry must
272291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         have a different from_offs, since a patched jump can only
273291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         jump to one place at once (it's meaningless for it to have
274291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         multiple destinations.)  IOW, the successor and predecessor
275291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         edges in the graph are not uniquely determined by a
276291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         TTEntry --> TTEntry pair, but rather by a
277291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (TTEntry,offset) --> TTEntry triple.
278291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
279291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         If A has multiple edges to B then B will mention A multiple
280291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         times in its in_edges.  To make things simpler, we then
281291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         require that A mentions B exactly the same number of times in
282291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         its out_edges.  Furthermore, a matching out-in pair must have
283291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         the same offset (from_offs).  This facilitates sanity
284291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         checking, and it facilitates establishing the invariant that
285291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         a out_edges set may not have duplicates when using the
286291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         equality defined by (TTEntry,offset).  Hence the out_edges
287291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         and in_edges sets really do have both have set semantics.
288291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
289291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         eg if  A has been patched to B at offsets 42 and 87 (in A)
290291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         then   A.out_edges = { (B,42), (B,87) }   (in any order)
291291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         and    B.in_edges  = { (A,42), (A,87) }   (in any order)
292291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
293291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Hence for each node pair P->Q in the graph, there's a 1:1
294291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         mapping between P.out_edges and Q.in_edges.
295291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      */
296291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdgeArr  in_edges;
297291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdgeArr out_edges;
2986c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
2996c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   TTEntry;
3006c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3014ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
302291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* A structure used for mapping host code addresses back to the
303291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   relevant TTEntry.  Used when doing chaining, for finding the
304291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry to which some arbitrary patch address belongs. */
305291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
306291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
307291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* start;
308291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt   len;
309523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      TTEno  tteNo;
310291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
311291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HostExtent;
312291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
313fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself.  Each sector contains an array of
314fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   TCEntries, which hold code, and an array of TTEntries, containing
315fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   all required administrative info.  Profiling is supported using the
316bece82eba7ba26398a673def2fa326341c4f8ef7philippe   TTEntry usage.prof.count and usage.prof.weight fields, if required.
3174ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
318fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   If the sector is not in use, all three pointers are NULL and
319fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tt_n_inuse is zero.
320fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
321fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef
322fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   struct {
323fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TCEntry area.  Size of this depends on the average
324fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         translation size.  We try and size it so it becomes full
325fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         precisely when this sector's translation table (tt) reaches
326fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         its load limit (SECTOR_TT_LIMIT_PERCENT). */
327fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc;
3284ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
329523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      /* An hash table, mapping guest address to an index in the tt array.
330bece82eba7ba26398a673def2fa326341c4f8ef7philippe         htt is a fixed size, always containing
331bece82eba7ba26398a673def2fa326341c4f8ef7philippe         exactly N_HTTES_PER_SECTOR entries. */
332523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      TTEno* htt;
333bece82eba7ba26398a673def2fa326341c4f8ef7philippe
334fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TTEntry array.  This is a fixed size, always containing
335fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         exactly N_TTES_PER_SECTOR entries. */
336fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      TTEntry* tt;
3376c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
338fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This points to the current allocation point in tc. */
339fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc_next;
340de4a1d01951937632098a6cda45859afa587a06fsewardj
341fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The count of tt entries with state InUse. */
342fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Int tt_n_inuse;
3436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
344bece82eba7ba26398a673def2fa326341c4f8ef7philippe      /* A list of Empty/Deleted entries, chained by tte->next_empty_tte */
345523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      TTEno empty_tt_list;
346bece82eba7ba26398a673def2fa326341c4f8ef7philippe
3476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Expandable arrays of tt indices for each of the ECLASS_N
3486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         address range equivalence classes.  These hold indices into
3496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         the containing sector's tt array, which in turn should point
3506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         back here. */
3516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int     ec2tte_size[ECLASS_N];
3526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int     ec2tte_used[ECLASS_N];
353523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      TTEno*  ec2tte[ECLASS_N];
354291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
355291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* The host extents.  The [start, +len) ranges are constructed
356291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         in strictly non-overlapping order, so we can binary search
357291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         them at any time. */
358291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray* host_extents; /* XArray* of HostExtent */
359fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
360fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Sector;
361de4a1d01951937632098a6cda45859afa587a06fsewardj
362de4a1d01951937632098a6cda45859afa587a06fsewardj
3636c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/
3646c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
365fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors.  The index of the
366fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest sector is recorded, and new translations are put into that
367fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.  When it fills up, we move along to the next sector and
368fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   start to fill that up, wrapping around at the end of the array.
369fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   That way, once all N_TC_SECTORS have been bought into use for the
370fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   first time, and are full, we then re-use the oldest sector,
371fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   endlessly.
372fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
373fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   When running, youngest sector should be between >= 0 and <
374523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   N_TC_SECTORS.  The initial  value indicates the TT/TC system is
375fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   not yet initialised.
376fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
3778e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippestatic Sector sectors[MAX_N_SECTORS];
378523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic Int    youngest_sector = INV_SNO;
3796c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
380fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area.  This is computed once
381fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   at startup and does not change. */
382a11ec17946cdbafb336e9121b64961c0633af2e7sewardjstatic Int    tc_sector_szQ = 0;
3836c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3846c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3855d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj/* A list of sector numbers, in the order which they should be
3865d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   searched to find translations.  This is an optimisation to be used
3875d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   when searching for translations and should not affect
388523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   correctness.  INV_SNO denotes "no entry". */
389523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic SECno sector_search_order[MAX_N_SECTORS];
3905d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
3915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
3925f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Fast helper for the TC.  A direct-mapped cache which holds a set of
3935f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   recently used (guest address, host address) pairs.  This array is
3945f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   referred to directly from m_dispatch/dispatch-<platform>.S.
3956c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3965f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   Entries in tt_fast may refer to any valid TC entry, regardless of
397fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   which sector it's in.  Consequently we must be very careful to
398fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidate this cache when TC entries are changed or disappear.
399c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
4005f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   A special .guest address - TRANSTAB_BOGUS_GUEST_ADDR -- must be
4015f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   pointed at to cause that cache entry to miss.  This relies on the
4025f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   assumption that no guest code actually has that address, hence a
4035f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   value 0x1 seems good.  m_translate gives the client a synthetic
4045f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   segfault if it tries to execute at this address.
4055f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/
4065f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*
4075f76de086a6d643db51e50a4e623df7dfc9b6161sewardjtypedef
4085f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   struct {
4095f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      Addr guest;
4105f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      Addr host;
4115f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
4125f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   FastCacheEntry;
4135f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/
4145f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*global*/ __attribute__((aligned(16)))
4155f76de086a6d643db51e50a4e623df7dfc9b6161sewardj           FastCacheEntry VG_(tt_fast)[VG_TT_FAST_SIZE];
416de4a1d01951937632098a6cda45859afa587a06fsewardj
417663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */
418663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False;
419663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
420663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
421fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/
422de4a1d01951937632098a6cda45859afa587a06fsewardj
423fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */
424291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_flushes = 0;
425291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_updates = 0;
42622854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
427fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */
428291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_full_lookups = 0;
429291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_lookup_probes = 0;
43022854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
43126412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj/* Number/osize/tsize of translations entered; also the number of
43226412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   those for which self-checking was requested. */
433291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_count    = 0;
434291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_osize    = 0;
435291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_tsize    = 0;
436291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_sc_count = 0;
437de4a1d01951937632098a6cda45859afa587a06fsewardj
438fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */
439291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_count = 0;
440291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_osize = 0;
4415e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippestatic ULong n_sectors_recycled = 0;
442fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
443fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */
444291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_count = 0;
445291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_osize = 0;
446291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
447291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
448291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
449291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Misc                                                  ---*/
450291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
451291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
45254fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorianstatic void* ttaux_malloc ( const HChar* tag, SizeT n )
453291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
454291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return VG_(arena_malloc)(VG_AR_TTAUX, tag, n);
455291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
456291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
457291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void ttaux_free ( void* p )
458291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
459291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(arena_free)(VG_AR_TTAUX, p);
460291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
461291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
462291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
463291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
464291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Chaining support                                      ---*/
465291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
466291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
467523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic inline TTEntry* index_tte ( SECno sNo, TTEno tteNo )
468291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
4698e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   vg_assert(sNo < n_sectors);
470291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(tteNo < N_TTES_PER_SECTOR);
471291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Sector* s = &sectors[sNo];
472291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(s->tt);
473291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* tte = &s->tt[tteNo];
474291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(tte->status == InUse);
475291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return tte;
476291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
477291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
478291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdge__init ( InEdge* ie )
479291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
480523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   ie->from_sNo   = INV_SNO; /* invalid */
481291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_tteNo = 0;
482291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_offs  = 0;
483291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->to_fastEP  = False;
484291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
485291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
486291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdge__init ( OutEdge* oe )
487291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
488523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   oe->to_sNo    = INV_SNO; /* invalid */
489291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->to_tteNo  = 0;
490291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->from_offs = 0;
491291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
492291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
493291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void TTEntry__init ( TTEntry* tte )
494291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
495291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(memset)(tte, 0, sizeof(*tte));
496291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
497291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
498518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UWord InEdgeArr__size ( const InEdgeArr* iea )
499291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
500291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
501291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
502291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return VG_(sizeXA)(iea->var);
503291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
504291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
505291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return iea->n_fixed;
506291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
507291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
508291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
509291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdgeArr__makeEmpty ( InEdgeArr* iea )
510291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
511291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
512291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
513291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(deleteXA)(iea->var);
514291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->var = NULL;
515291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
516291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
517291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->n_fixed = 0;
518291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
519291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
520291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
521291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
522291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjInEdge* InEdgeArr__index ( InEdgeArr* iea, UWord i )
523291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
524291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
525291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
526291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return (InEdge*)VG_(indexXA)(iea->var, i);
527291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
528291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < iea->n_fixed);
529291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return &iea->fixed[i];
530291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
531291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
532291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
533291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
534291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__deleteIndex ( InEdgeArr* iea, UWord i )
535291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
536291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
537291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
538291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(removeIndexXA)(iea->var, i);
539291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
540291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < iea->n_fixed);
541291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (; i+1 < iea->n_fixed; i++) {
542291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->fixed[i] = iea->fixed[i+1];
543291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
544291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->n_fixed--;
545291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
546291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
547291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
548291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
549291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__add ( InEdgeArr* iea, InEdge* ie )
550291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
551291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
552291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
553291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(addToXA)(iea->var, ie);
554291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
555291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
556291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (iea->n_fixed == N_FIXED_IN_EDGE_ARR) {
557291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* The fixed array is full, so we have to initialise an
558291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            XArray and copy the fixed array into it. */
559291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->var = VG_(newXA)(ttaux_malloc, "transtab.IEA__add",
560291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               ttaux_free,
561291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               sizeof(InEdge));
562291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UWord i;
563291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         for (i = 0; i < iea->n_fixed; i++) {
564291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            VG_(addToXA)(iea->var, &iea->fixed[i]);
565291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         }
566291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         VG_(addToXA)(iea->var, ie);
567291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->n_fixed = 0;
568291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      } else {
569291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Just add to the fixed array. */
570291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->fixed[iea->n_fixed++] = *ie;
571291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
572291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
573291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
574291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
575518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UWord OutEdgeArr__size ( const OutEdgeArr* oea )
576291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
577291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
578291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
579291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return VG_(sizeXA)(oea->var);
580291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
581291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
582291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return oea->n_fixed;
583291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
584291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
585291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
586291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdgeArr__makeEmpty ( OutEdgeArr* oea )
587291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
588291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
589291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
590291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(deleteXA)(oea->var);
591291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->var = NULL;
592291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
593291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
594291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->n_fixed = 0;
595291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
596291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
597291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
598291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
599291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjOutEdge* OutEdgeArr__index ( OutEdgeArr* oea, UWord i )
600291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
601291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
602291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
603291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return (OutEdge*)VG_(indexXA)(oea->var, i);
604291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
605291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < oea->n_fixed);
606291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return &oea->fixed[i];
607291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
608291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
609291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
610291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
611291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__deleteIndex ( OutEdgeArr* oea, UWord i )
612291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
613291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
614291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
615291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(removeIndexXA)(oea->var, i);
616291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
617291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < oea->n_fixed);
618291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (; i+1 < oea->n_fixed; i++) {
619291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->fixed[i] = oea->fixed[i+1];
620291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
621291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->n_fixed--;
622291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
623291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
624291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
625291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
626291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__add ( OutEdgeArr* oea, OutEdge* oe )
627291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
628291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
629291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
630291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(addToXA)(oea->var, oe);
631291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
632291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
633291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (oea->n_fixed == N_FIXED_OUT_EDGE_ARR) {
634291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* The fixed array is full, so we have to initialise an
635291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            XArray and copy the fixed array into it. */
636291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->var = VG_(newXA)(ttaux_malloc, "transtab.OEA__add",
637291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               ttaux_free,
638291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               sizeof(OutEdge));
639291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UWord i;
640291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         for (i = 0; i < oea->n_fixed; i++) {
641291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            VG_(addToXA)(oea->var, &oea->fixed[i]);
642291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         }
643291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         VG_(addToXA)(oea->var, oe);
644291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->n_fixed = 0;
645291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      } else {
646291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Just add to the fixed array. */
647291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->fixed[oea->n_fixed++] = *oe;
648291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
649291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
650291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
651291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
652291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
6536bd9dc18c043927c1196caba20a327238a179c42florianInt HostExtent__cmpOrd ( const void* v1, const void* v2 )
654291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
6556bd9dc18c043927c1196caba20a327238a179c42florian   const HostExtent* hx1 = v1;
6566bd9dc18c043927c1196caba20a327238a179c42florian   const HostExtent* hx2 = v2;
657291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (hx1->start + hx1->len <= hx2->start) return -1;
658291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (hx2->start + hx2->len <= hx1->start) return 1;
659291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return 0; /* partial overlap */
660291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
661291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
6623a5322057616d0da214b9e0f897866e203c03e40philippe/* True if hx is a dead host extent, i.e. corresponds to host code
6633a5322057616d0da214b9e0f897866e203c03e40philippe   of an entry that was invalidated. */
6643a5322057616d0da214b9e0f897866e203c03e40philippestatic
6653a5322057616d0da214b9e0f897866e203c03e40philippeBool HostExtent__is_dead (const HostExtent* hx, const Sector* sec)
6663a5322057616d0da214b9e0f897866e203c03e40philippe{
667523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   const TTEno tteNo = hx->tteNo;
6683a5322057616d0da214b9e0f897866e203c03e40philippe#define LDEBUG(m) if (DEBUG_TRANSTAB)                           \
6693a5322057616d0da214b9e0f897866e203c03e40philippe      VG_(printf) (m                                            \
6703a5322057616d0da214b9e0f897866e203c03e40philippe                   " start 0x%p len %u sector %d ttslot %u"     \
671ddd61ff058f02059064e083a8accaefed23d5548florian                   " tt.entry 0x%lu tt.tcptr 0x%p\n",           \
6723a5322057616d0da214b9e0f897866e203c03e40philippe                   hx->start, hx->len, (int)(sec - sectors),    \
6733a5322057616d0da214b9e0f897866e203c03e40philippe                   hx->tteNo,                                   \
6743a5322057616d0da214b9e0f897866e203c03e40philippe                   sec->tt[tteNo].entry, sec->tt[tteNo].tcptr)
6753a5322057616d0da214b9e0f897866e203c03e40philippe
6763a5322057616d0da214b9e0f897866e203c03e40philippe   /* Entry might have been invalidated and not re-used yet.*/
6773a5322057616d0da214b9e0f897866e203c03e40philippe   if (sec->tt[tteNo].status == Deleted) {
6783a5322057616d0da214b9e0f897866e203c03e40philippe      LDEBUG("found deleted entry");
6793a5322057616d0da214b9e0f897866e203c03e40philippe      return True;
6803a5322057616d0da214b9e0f897866e203c03e40philippe   }
6813a5322057616d0da214b9e0f897866e203c03e40philippe   /* Maybe we found this entry via a host_extents which was
6823a5322057616d0da214b9e0f897866e203c03e40philippe      inserted for an entry which was changed to Deleted then
6833a5322057616d0da214b9e0f897866e203c03e40philippe      re-used after. If this entry was re-used, then its tcptr
6843a5322057616d0da214b9e0f897866e203c03e40philippe      is >= to host_extents start (i.e. the previous tcptr) + len.
6853a5322057616d0da214b9e0f897866e203c03e40philippe      This is the case as there is no re-use of host code: a new
6863a5322057616d0da214b9e0f897866e203c03e40philippe      entry or re-used entry always gets "higher value" host code. */
6873a5322057616d0da214b9e0f897866e203c03e40philippe   if ((UChar*) sec->tt[tteNo].tcptr >= hx->start + hx->len) {
6883a5322057616d0da214b9e0f897866e203c03e40philippe      LDEBUG("found re-used entry");
6893a5322057616d0da214b9e0f897866e203c03e40philippe      return True;
6903a5322057616d0da214b9e0f897866e203c03e40philippe   }
6913a5322057616d0da214b9e0f897866e203c03e40philippe
6923a5322057616d0da214b9e0f897866e203c03e40philippe   return False;
6933a5322057616d0da214b9e0f897866e203c03e40philippe#undef LDEBUG
6943a5322057616d0da214b9e0f897866e203c03e40philippe}
6953a5322057616d0da214b9e0f897866e203c03e40philippe
696291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic __attribute__((noinline))
697523b5b8ca67d2063afd02342d0138b0dc0ed6706philippeBool find_TTEntry_from_hcode( /*OUT*/SECno* from_sNo,
698523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                              /*OUT*/TTEno* from_tteNo,
699291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              void* hcode )
700291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
701523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   SECno i;
702291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
703291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Search order logic copied from VG_(search_transtab). */
7048e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
705523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      SECno sno = sector_search_order[i];
706523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      if (UNLIKELY(sno == INV_SNO))
707291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return False; /* run out of sectors to search */
708291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
709518850bf0da07ed3e2244e307268ae0fd80e93a8florian      const Sector* sec = &sectors[sno];
710518850bf0da07ed3e2244e307268ae0fd80e93a8florian      const XArray* /* of HostExtent */ host_extents = sec->host_extents;
711291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(host_extents);
712291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
713291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      HostExtent key;
714291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(memset)(&key, 0, sizeof(key));
715291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      key.start = hcode;
716291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      key.len = 1;
717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Word firstW = -1, lastW = -1;
718291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Bool found  = VG_(lookupXA_UNSAFE)(
719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       host_extents, &key, &firstW, &lastW,
7206bd9dc18c043927c1196caba20a327238a179c42florian                       HostExtent__cmpOrd );
721291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(firstW == lastW); // always true, even if not found
722291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (found) {
723291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         HostExtent* hx = VG_(indexXA)(host_extents, firstW);
724523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         TTEno tteNo = hx->tteNo;
725291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Do some additional sanity checks. */
726bece82eba7ba26398a673def2fa326341c4f8ef7philippe         vg_assert(tteNo < N_TTES_PER_SECTOR);
7273a5322057616d0da214b9e0f897866e203c03e40philippe
7283a5322057616d0da214b9e0f897866e203c03e40philippe         /* if this hx entry corresponds to dead host code, we must
7293a5322057616d0da214b9e0f897866e203c03e40philippe            tell this code has not been found, as it cannot be patched. */
7303a5322057616d0da214b9e0f897866e203c03e40philippe         if (HostExtent__is_dead (hx, sec))
731291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            return False;
7323a5322057616d0da214b9e0f897866e203c03e40philippe
733291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert(sec->tt[tteNo].status == InUse);
734291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Can only half check that the found TTEntry contains hcode,
735291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            due to not having a length value for the hcode in the
736291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            TTEntry. */
737291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert((UChar*)sec->tt[tteNo].tcptr <= (UChar*)hcode);
738291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Looks plausible */
739291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         *from_sNo   = sno;
740523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         *from_tteNo = tteNo;
741291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return True;
742291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
743291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
744291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return False;
745291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
746291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
747291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
748291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Figure out whether or not hcode is jitted code present in the main
749291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   code cache (but not in the no-redir cache).  Used for sanity
750291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   checking. */
751518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool is_in_the_main_TC ( const void* hcode )
752291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
753523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   SECno i, sno;
7548e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
755291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      sno = sector_search_order[i];
756523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      if (sno == INV_SNO)
757291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         break; /* run out of sectors to search */
758518850bf0da07ed3e2244e307268ae0fd80e93a8florian      if ((const UChar*)hcode >= (const UChar*)sectors[sno].tc
759518850bf0da07ed3e2244e307268ae0fd80e93a8florian          && (const UChar*)hcode <= (const UChar*)sectors[sno].tc_next
760291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              + sizeof(ULong) - 1)
761291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return True;
762291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
763291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return False;
764291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
765291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
766291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
767291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Fulfill a chaining request, and record admin info so we
768291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   can undo it later, if required.
769291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj*/
770291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid VG_(tt_tc_do_chaining) ( void* from__patch_addr,
771523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                              SECno to_sNo,
772523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                              TTEno to_tteNo,
773291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              Bool  to_fastEP )
774291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
775291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Get the CPU info established at startup. */
776597314210494248b4fbefd45525a748439629218sewardj   VexArch     arch_host = VexArch_INVALID;
777597314210494248b4fbefd45525a748439629218sewardj   VexArchInfo archinfo_host;
778597314210494248b4fbefd45525a748439629218sewardj   VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host));
779597314210494248b4fbefd45525a748439629218sewardj   VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host );
780597314210494248b4fbefd45525a748439629218sewardj   VexEndness endness_host = archinfo_host.endness;
781291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
782291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // host_code is where we're patching to.  So it needs to
783291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // take into account, whether we're jumping to the slow
784291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // or fast entry point.  By definition, the fast entry point
785291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // is exactly one event check's worth of code along from
786291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // the slow (tcptr) entry point.
787291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* to_tte    = index_tte(to_sNo, to_tteNo);
788291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   void*    host_code = ((UChar*)to_tte->tcptr)
7895f8ced84fdd6ebd260cece49b51477c68437e8caflorian                        + (to_fastEP ? LibVEX_evCheckSzB(arch_host) : 0);
790291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
791291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // stay sane -- the patch point (dst) is in this sector's code cache
792291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( (UChar*)host_code >= (UChar*)sectors[to_sNo].tc );
793291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( (UChar*)host_code <= (UChar*)sectors[to_sNo].tc_next
794291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                   + sizeof(ULong) - 1 );
795291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
796291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Find the TTEntry for the from__ code.  This isn't simple since
797291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      we only know the patch address, which is going to be somewhere
798291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      inside the from_ block. */
799523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   SECno from_sNo   = INV_SNO;
800523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   TTEno from_tteNo = INV_TTE;
801291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Bool from_found
802291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = find_TTEntry_from_hcode( &from_sNo, &from_tteNo,
803291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                 from__patch_addr );
804291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (!from_found) {
805291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // The from code might have been discarded due to sector re-use
806291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // or marked Deleted due to translation invalidation.
807291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // In such a case, don't do the chaining.
808291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(debugLog)(1,"transtab",
809291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    "host code %p not found (discarded? sector recycled?)"
810291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    " => no chaining done\n",
811291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    from__patch_addr);
812291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return;
813291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
814291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
815291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* from_tte = index_tte(from_sNo, from_tteNo);
816291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
817291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Get VEX to do the patching itself.  We have to hand it off
818291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      since it is host-dependent. */
819291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexInvalRange vir
820291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = LibVEX_Chain(
821597314210494248b4fbefd45525a748439629218sewardj           arch_host, endness_host,
822291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           from__patch_addr,
823291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           VG_(fnptr_to_fnentry)(
824291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj              to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP)
825291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                        : &VG_(disp_cp_chain_me_to_slowEP)),
826291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           (void*)host_code
827291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        );
828291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( (void*)vir.start, vir.len );
829291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
830291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Now do the tricky bit -- update the ch_succs and ch_preds info
831291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for the two translations involved, so we can undo the chaining
832291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      later, which we will have to do if the to_ block gets removed
833291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for whatever reason. */
834291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
835291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* This is the new from_ -> to_ link to add. */
836291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge ie;
837291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge__init(&ie);
838291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_sNo   = from_sNo;
839291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_tteNo = from_tteNo;
840291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.to_fastEP  = to_fastEP;
841291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HWord from_offs = (HWord)( (UChar*)from__patch_addr
842291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              - (UChar*)from_tte->tcptr );
843291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(from_offs < 100000/* let's say */);
844291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_offs  = (UInt)from_offs;
845291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
846291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* This is the new to_ -> from_ backlink to add. */
847291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge oe;
848291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge__init(&oe);
849291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.to_sNo    = to_sNo;
850291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.to_tteNo  = to_tteNo;
851291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.from_offs = (UInt)from_offs;
852291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
853291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Add .. */
854291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr__add(&to_tte->in_edges, &ie);
855291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr__add(&from_tte->out_edges, &oe);
856291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
857291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
858291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
859291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Unchain one patch, as described by the specified InEdge.  For
860291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   sanity check purposes only (to check that the patched location is
861291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   as expected) it also requires the fast and slow entry point
862291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   addresses of the destination block (that is, the block that owns
863291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   this InEdge). */
864291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj__attribute__((noinline))
865597314210494248b4fbefd45525a748439629218sewardjstatic void unchain_one ( VexArch arch_host, VexEndness endness_host,
866291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          InEdge* ie,
867291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          void* to_fastEPaddr, void* to_slowEPaddr )
868291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
869291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(ie);
870291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* tte
871291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = index_tte(ie->from_sNo, ie->from_tteNo);
872291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* place_to_patch
87319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      = ((UChar*)tte->tcptr) + ie->from_offs;
874291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* disp_cp_chain_me
875291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = VG_(fnptr_to_fnentry)(
876291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           ie->to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP)
877291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                         : &VG_(disp_cp_chain_me_to_slowEP)
878291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        );
879291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* place_to_jump_to_EXPECTED
880291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = ie->to_fastEP ? to_fastEPaddr : to_slowEPaddr;
881291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
882291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // stay sane: both src and dst for this unchaining are
883291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // in the main code cache
884291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( is_in_the_main_TC(place_to_patch) ); // src
885291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( is_in_the_main_TC(place_to_jump_to_EXPECTED) ); // dst
886291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // dst check is ok because LibVEX_UnChain checks that
887291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // place_to_jump_to_EXPECTED really is the current dst, and
888291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // asserts if it isn't.
889291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexInvalRange vir
890597314210494248b4fbefd45525a748439629218sewardj       = LibVEX_UnChain( arch_host, endness_host, place_to_patch,
891291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                         place_to_jump_to_EXPECTED, disp_cp_chain_me );
892291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( (void*)vir.start, vir.len );
893291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
894291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
895291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
896291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* The specified block is about to be deleted.  Update the preds and
897291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   succs of its associated blocks accordingly.  This includes undoing
898291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   any chained jumps to this block. */
899291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
900597314210494248b4fbefd45525a748439629218sewardjvoid unchain_in_preparation_for_deletion ( VexArch arch_host,
901597314210494248b4fbefd45525a748439629218sewardj                                           VexEndness endness_host,
902523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                                           SECno here_sNo, TTEno here_tteNo )
903291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
9043a5322057616d0da214b9e0f897866e203c03e40philippe   if (DEBUG_TRANSTAB)
9053a5322057616d0da214b9e0f897866e203c03e40philippe      VG_(printf)("QQQ unchain_in_prep %u.%u...\n", here_sNo, here_tteNo);
906291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UWord    i, j, n, m;
9075f8ced84fdd6ebd260cece49b51477c68437e8caflorian   Int      evCheckSzB = LibVEX_evCheckSzB(arch_host);
908291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* here_tte   = index_tte(here_sNo, here_tteNo);
9093a5322057616d0da214b9e0f897866e203c03e40philippe   if (DEBUG_TRANSTAB)
910ddd61ff058f02059064e083a8accaefed23d5548florian      VG_(printf)("... QQQ tt.entry 0x%lu tt.tcptr 0x%p\n",
9113a5322057616d0da214b9e0f897866e203c03e40philippe                  here_tte->entry, here_tte->tcptr);
912291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(here_tte->status == InUse);
913291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
914291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Visit all InEdges owned by here_tte. */
915291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   n = InEdgeArr__size(&here_tte->in_edges);
916291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < n; i++) {
917291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdge* ie = InEdgeArr__index(&here_tte->in_edges, i);
918291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Undo the chaining.
919291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* here_slow_EP = (UChar*)here_tte->tcptr;
920291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* here_fast_EP = here_slow_EP + evCheckSzB;
921597314210494248b4fbefd45525a748439629218sewardj      unchain_one(arch_host, endness_host, ie, here_fast_EP, here_slow_EP);
922291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Find the corresponding entry in the "from" node's out_edges,
923291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // and remove it.
924291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      TTEntry* from_tte = index_tte(ie->from_sNo, ie->from_tteNo);
925291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      m = OutEdgeArr__size(&from_tte->out_edges);
926291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(m > 0); // it must have at least one entry
927291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (j = 0; j < m; j++) {
928291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         OutEdge* oe = OutEdgeArr__index(&from_tte->out_edges, j);
929291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if (oe->to_sNo == here_sNo && oe->to_tteNo == here_tteNo
930291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             && oe->from_offs == ie->from_offs)
931291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           break;
932291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
933291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(j < m); // "oe must be findable"
934291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdgeArr__deleteIndex(&from_tte->out_edges, j);
935291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
936291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
937291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Visit all OutEdges owned by here_tte. */
938291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   n = OutEdgeArr__size(&here_tte->out_edges);
939291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < n; i++) {
940291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdge* oe = OutEdgeArr__index(&here_tte->out_edges, i);
941291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Find the corresponding entry in the "to" node's in_edges,
942291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // and remove it.
943291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      TTEntry* to_tte = index_tte(oe->to_sNo, oe->to_tteNo);
944291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      m = InEdgeArr__size(&to_tte->in_edges);
945291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(m > 0); // it must have at least one entry
946291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (j = 0; j < m; j++) {
947291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         InEdge* ie = InEdgeArr__index(&to_tte->in_edges, j);
948291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if (ie->from_sNo == here_sNo && ie->from_tteNo == here_tteNo
949291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             && ie->from_offs == oe->from_offs)
950291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           break;
951291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
952291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(j < m); // "ie must be findable"
953291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdgeArr__deleteIndex(&to_tte->in_edges, j);
954291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
955291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
956291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr__makeEmpty(&here_tte->in_edges);
957291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr__makeEmpty(&here_tte->out_edges);
958291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
959fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
960fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
9616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
9626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Address-range equivalence class stuff                 ---*/
9636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
9646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Return equivalence class number for a range. */
9666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
967ddd61ff058f02059064e083a8accaefed23d5548florianstatic Int range_to_eclass ( Addr start, UInt len )
9686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
9696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt mask   = (1 << ECLASS_WIDTH) - 1;
9706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt lo     = (UInt)start;
9716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt hi     = lo + len - 1;
9726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt loBits = (lo >> ECLASS_SHIFT) & mask;
9736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt hiBits = (hi >> ECLASS_SHIFT) & mask;
9746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (loBits == hiBits) {
9756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(loBits < ECLASS_N-1);
9766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return loBits;
9776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   } else {
9786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return ECLASS_MISC;
9796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
9816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Calculates the equivalence class numbers for any VexGuestExtent.
9846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   These are written in *eclasses, which must be big enough to hold 3
9856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Ints.  The number written, between 1 and 3, is returned.  The
9866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclasses are presented in order, and any duplicates are removed.
9876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj*/
9886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
9906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjInt vexGuestExtents_to_eclasses ( /*OUT*/Int* eclasses,
991518850bf0da07ed3e2244e307268ae0fd80e93a8florian                                  const VexGuestExtents* vge )
9926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
993518850bf0da07ed3e2244e307268ae0fd80e93a8florian
9946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  define SWAP(_lv1,_lv2) \
9956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      do { Int t = _lv1; _lv1 = _lv2; _lv2 = t; } while (0)
9966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, j, n_ec, r;
9986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
10006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_ec = 0;
10026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < vge->n_used; i++) {
1003ddd61ff058f02059064e083a8accaefed23d5548florian      r = range_to_eclass( vge->base[i], vge->len[i] );
10046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (r == ECLASS_MISC)
10056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         goto bad;
10066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* only add if we haven't already seen it */
10076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < n_ec; j++)
10086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (eclasses[j] == r)
10096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            break;
10106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (j == n_ec)
10116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         eclasses[n_ec++] = r;
10126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 1)
10156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 1;
10166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 2) {
10186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* sort */
10196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[1])
10206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[1]);
10216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 2;
10226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 3) {
10256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* sort */
10266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[2])
10276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[2]);
10286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[1])
10296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[1]);
10306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[1] > eclasses[2])
10316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[1], eclasses[2]);
10326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 3;
10336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* NOTREACHED */
10366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(0);
10376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj  bad:
10396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclasses[0] = ECLASS_MISC;
10406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return 1;
10416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  undef SWAP
10436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
10446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Add tteno to the set of entries listed for equivalence class ec in
10476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   this sector.  Returns used location in eclass array. */
10486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
1050523b5b8ca67d2063afd02342d0138b0dc0ed6706philippeUInt addEClassNo ( /*MOD*/Sector* sec, Int ec, TTEno tteno )
10516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
10526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int    old_sz, new_sz, i, r;
1053523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   TTEno  *old_ar, *new_ar;
10546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(ec >= 0 && ec < ECLASS_N);
10566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno < N_TTES_PER_SECTOR);
10576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10583a5322057616d0da214b9e0f897866e203c03e40philippe   if (DEBUG_TRANSTAB) VG_(printf)("ec %d  gets %d\n", ec, (Int)tteno);
10596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->ec2tte_used[ec] >= sec->ec2tte_size[ec]) {
10616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->ec2tte_used[ec] == sec->ec2tte_size[ec]);
10636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      old_sz = sec->ec2tte_size[ec];
10656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      old_ar = sec->ec2tte[ec];
10666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      new_sz = old_sz==0 ? 8 : old_sz<64 ? 2*old_sz : (3*old_sz)/2;
1067291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      new_ar = ttaux_malloc("transtab.aECN.1",
1068523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                            new_sz * sizeof(TTEno));
10696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < old_sz; i++)
10706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         new_ar[i] = old_ar[i];
10716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (old_ar)
1072291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         ttaux_free(old_ar);
10736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte_size[ec] = new_sz;
10746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte[ec] = new_ar;
10756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10763a5322057616d0da214b9e0f897866e203c03e40philippe      if (DEBUG_TRANSTAB) VG_(printf)("expand ec %d to %d\n", ec, new_sz);
10776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Common case */
10806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   r = sec->ec2tte_used[ec]++;
10816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(r >= 0 && r < sec->ec2tte_size[ec]);
10826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->ec2tte[ec][r] = tteno;
10836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return (UInt)r;
10846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
10856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* 'vge' is being added to 'sec' at TT entry 'tteno'.  Add appropriate
10886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclass entries to 'sec'. */
10896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
1091523b5b8ca67d2063afd02342d0138b0dc0ed6706philippevoid upd_eclasses_after_add ( /*MOD*/Sector* sec, TTEno tteno )
10926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
10936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, r, eclasses[3];
10946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
10956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR);
10966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte = &sec->tt[tteno];
10986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   r = vexGuestExtents_to_eclasses( eclasses, &tte->vge );
10996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(r >= 1 && r <= 3);
11016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->n_tte2ec = r;
11026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < r; i++) {
11046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte->tte2ec_ec[i] = eclasses[i];
1105523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      tte->tte2ec_ix[i] = addEClassNo( sec, eclasses[i], tteno );
11066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
11086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Check the eclass info in 'sec' to ensure it is consistent.  Returns
11116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   True if OK, False if something's not right.  Expensive. */
11126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1113518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool sanity_check_eclasses_in_sector ( const Sector* sec )
11146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
11156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  define BAD(_str) do { whassup = (_str); goto bad; } while (0)
11166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11176bd9dc18c043927c1196caba20a327238a179c42florian   const HChar* whassup = NULL;
11186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i, j, k, n, ec_num, ec_idx;
11196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
1120523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   TTEno    tteno;
11216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   ULong*   tce;
11226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Basic checks on this sector */
1124bece82eba7ba26398a673def2fa326341c4f8ef7philippe   if (sec->tt_n_inuse < 0 || sec->tt_n_inuse > N_TTES_PER_SECTOR)
11256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      BAD("invalid sec->tt_n_inuse");
11266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tce = sec->tc_next;
11276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (tce < &sec->tc[0] || tce > &sec->tc[tc_sector_szQ])
11286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      BAD("sec->tc_next points outside tc");
11296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* For each eclass ... */
11316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < ECLASS_N; i++) {
11326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_size[i] == 0 && sec->ec2tte[i] != NULL)
11336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("ec2tte_size/ec2tte mismatch(1)");
11346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_size[i] != 0 && sec->ec2tte[i] == NULL)
11356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("ec2tte_size/ec2tte mismatch(2)");
11366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_used[i] < 0
11376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj          || sec->ec2tte_used[i] > sec->ec2tte_size[i])
11386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("implausible ec2tte_used");
11396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_used[i] == 0)
11406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
11416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* For each tt reference in each eclass .. ensure the reference
11436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         is to a valid tt entry, and that the entry's address ranges
11446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         really include this eclass. */
11456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < sec->ec2tte_used[i]; j++) {
11476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         tteno = sec->ec2tte[i][j];
11486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tteno == EC2TTE_DELETED)
11496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
11506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tteno >= N_TTES_PER_SECTOR)
11516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("implausible tteno");
11526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         tte = &sec->tt[tteno];
11536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->status != InUse)
11546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tteno points to non-inuse tte");
11556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3)
11566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->n_tte2ec out of range");
11576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         /* Exactly least one of tte->eclasses[0 .. tte->n_eclasses-1]
11586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            must equal i.  Inspect tte's eclass info. */
11596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         n = 0;
11606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         for (k = 0; k < tte->n_tte2ec; k++) {
11616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (k < tte->n_tte2ec-1
11626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                && tte->tte2ec_ec[k] >= tte->tte2ec_ec[k+1])
11636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ec[..] out of order");
11646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            ec_num = tte->tte2ec_ec[k];
11656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_num < 0 || ec_num >= ECLASS_N)
11666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ec[..] out of range");
11676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_num != i)
11686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               continue;
11696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            ec_idx = tte->tte2ec_ix[k];
11706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[i])
11716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ix[..] out of range");
11726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_idx == j)
11736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               n++;
11746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
11756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (n != 1)
11766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tteno does not point back at eclass");
11776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* That establishes that for each forward pointer from TTEntrys
11816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      there is a corresponding backward pointer from the eclass[]
11826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      arrays.  However, it doesn't rule out the possibility of other,
11836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      bogus pointers in the eclass[] arrays.  So do those similarly:
11846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      scan through them and check the TTEntryies they point at point
11856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      back. */
11866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1187523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   for (tteno = 0; tteno < N_TTES_PER_SECTOR; tteno++) {
11886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1189523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      tte = &sec->tt[tteno];
11906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tte->status == Empty || tte->status == Deleted) {
11916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->n_tte2ec != 0)
11926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->n_eclasses nonzero for unused tte");
11936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
11946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tte->status == InUse);
11976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3)
11996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("tte->n_eclasses out of range(2)");
12006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < tte->n_tte2ec; j++) {
12026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         ec_num = tte->tte2ec_ec[j];
12036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (ec_num < 0 || ec_num >= ECLASS_N)
12046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->eclass[..] out of range");
12056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         ec_idx = tte->tte2ec_ix[j];
12066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[ec_num])
12076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->ec_idx[..] out of range(2)");
1208523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         if (sec->ec2tte[ec_num][ec_idx] != tteno)
12096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("ec2tte does not point back to tte");
12106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
12116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
12126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return True;
12146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj  bad:
12166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (whassup)
12176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(0, "transtab", "eclass sanity fail: %s\n", whassup);
12186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  if 0
12206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   VG_(printf)("eclass = %d\n", i);
12216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   VG_(printf)("tteno = %d\n", (Int)tteno);
12226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   switch (tte->status) {
12236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case InUse:   VG_(printf)("InUse\n"); break;
12246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case Deleted: VG_(printf)("Deleted\n"); break;
12256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case Empty:   VG_(printf)("Empty\n"); break;
12266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
12276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (tte->status != Empty) {
12286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (k = 0; k < tte->vge.n_used; k++)
1229ddd61ff058f02059064e083a8accaefed23d5548florian         VG_(printf)("0x%lx %u\n", tte->vge.base[k], (UInt)tte->vge.len[k]);
12306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
12316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  endif
12326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return False;
12346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  undef BAD
12366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
12376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Sanity check absolutely everything.  True == check passed. */
12406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12415f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* forwards */
12420ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void );
12430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
12445d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardjstatic Bool sanity_check_sector_search_order ( void )
12455d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj{
1246523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   SECno i, j, nListed;
12475d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* assert the array is the right size */
12488e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   vg_assert(MAX_N_SECTORS == (sizeof(sector_search_order)
12498e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe                               / sizeof(sector_search_order[0])));
1250523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   /* Check it's of the form  valid_sector_numbers ++ [INV_SNO, INV_SNO, ..] */
12518e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
1252523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      if (sector_search_order[i] == INV_SNO
1253523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe          || sector_search_order[i] >= n_sectors)
12545d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         break;
12555d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12565d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   nListed = i;
12578e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (/* */; i < n_sectors; i++) {
1258523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      if (sector_search_order[i] != INV_SNO)
12595d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         break;
12605d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12618e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   if (i != n_sectors)
12625d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
12635d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check each sector number only appears once */
12648e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
1265523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      if (sector_search_order[i] == INV_SNO)
12665d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         continue;
12678e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (j = i+1; j < n_sectors; j++) {
12685d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         if (sector_search_order[j] == sector_search_order[i])
12695d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            return False;
12705d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
12715d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12725d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check that the number of listed sectors equals the number
12735d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      in use, by counting nListed back down. */
12748e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
12755d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sectors[i].tc != NULL)
12765d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         nListed--;
12775d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12785d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   if (nListed != 0)
12795d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
12805d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   return True;
12815d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj}
12825d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
12836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_all_sectors ( void )
12846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
1285523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   SECno   sno;
12866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool    sane;
12876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
12888e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (sno = 0; sno < n_sectors; sno++) {
12893a5322057616d0da214b9e0f897866e203c03e40philippe      Int i;
12903a5322057616d0da214b9e0f897866e203c03e40philippe      Int nr_not_dead_hx = 0;
12913a5322057616d0da214b9e0f897866e203c03e40philippe      Int szhxa;
12926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec = &sectors[sno];
12936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->tc == NULL)
12946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
12956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sane = sanity_check_eclasses_in_sector( sec );
12966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (!sane)
12976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         return False;
12983a5322057616d0da214b9e0f897866e203c03e40philippe      szhxa = VG_(sizeXA)(sec->host_extents);
12993a5322057616d0da214b9e0f897866e203c03e40philippe      for (i = 0; i < szhxa; i++) {
13003a5322057616d0da214b9e0f897866e203c03e40philippe         const HostExtent* hx = VG_(indexXA)(sec->host_extents, i);
13013a5322057616d0da214b9e0f897866e203c03e40philippe         if (!HostExtent__is_dead (hx, sec))
13023a5322057616d0da214b9e0f897866e203c03e40philippe            nr_not_dead_hx++;
13033a5322057616d0da214b9e0f897866e203c03e40philippe      }
13043a5322057616d0da214b9e0f897866e203c03e40philippe      if (nr_not_dead_hx != sec->tt_n_inuse) {
13053a5322057616d0da214b9e0f897866e203c03e40philippe         VG_(debugLog)(0, "transtab",
1306523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                       "nr_not_dead_hx %d sanity fail "
1307523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                       "(expected == in use %d)\n",
13083a5322057616d0da214b9e0f897866e203c03e40philippe                       nr_not_dead_hx, sec->tt_n_inuse);
13093a5322057616d0da214b9e0f897866e203c03e40philippe         return False;
13103a5322057616d0da214b9e0f897866e203c03e40philippe      }
13116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
13123a5322057616d0da214b9e0f897866e203c03e40philippe
13135f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if ( !sanity_check_redir_tt_tc() )
13145f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      return False;
13155d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   if ( !sanity_check_sector_search_order() )
13165d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
13176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return True;
13186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
13196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1320fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
13215d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1322fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
13236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Add/find translations                                 ---*/
1324fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
1325fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1326518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UInt vge_osize ( const VexGuestExtents* vge )
1327c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{
1328fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt i, n = 0;
1329fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < vge->n_used; i++)
1330fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n += (UInt)vge->len[i];
1331fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n;
1332c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
1333c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
1334523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic Bool isValidSector ( SECno sector )
13356c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1336523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   if (sector == INV_SNO || sector >= n_sectors)
1337fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1338fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
13396c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1340de4a1d01951937632098a6cda45859afa587a06fsewardj
1341523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic inline HTTno HASH_TT ( Addr key )
1342de4a1d01951937632098a6cda45859afa587a06fsewardj{
1343ddd61ff058f02059064e083a8accaefed23d5548florian   UInt kHi = sizeof(Addr) == 4 ? 0 : (key >> 32);
1344fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt kLo = (UInt)key;
13456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt k32 = kHi ^ kLo;
13466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt ror = 7;
13476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (ror > 0)
13486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      k32 = (k32 >> ror) | (k32 << (32-ror));
1349523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   return (HTTno)(k32 % N_HTTES_PER_SECTOR);
1350de4a1d01951937632098a6cda45859afa587a06fsewardj}
1351de4a1d01951937632098a6cda45859afa587a06fsewardj
1352ddd61ff058f02059064e083a8accaefed23d5548florianstatic void setFastCacheEntry ( Addr key, ULong* tcptr )
1353de4a1d01951937632098a6cda45859afa587a06fsewardj{
13543387dda4479102751d544c176a7bfc24f3766669sewardj   UInt cno = (UInt)VG_TT_FAST_HASH(key);
1355ddd61ff058f02059064e083a8accaefed23d5548florian   VG_(tt_fast)[cno].guest = key;
13565f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   VG_(tt_fast)[cno].host  = (Addr)tcptr;
1357fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_updates++;
13585f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* This shouldn't fail.  It should be assured by m_translate
13595f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      which should reject any attempt to make translation of code
13605f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      starting at TRANSTAB_BOGUS_GUEST_ADDR. */
13615f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_(tt_fast)[cno].guest != TRANSTAB_BOGUS_GUEST_ADDR);
13626c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1363de4a1d01951937632098a6cda45859afa587a06fsewardj
1364291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Invalidate the fast cache VG_(tt_fast). */
13655f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastCache ( void )
13665f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{
13675f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   UInt j;
13685f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* This loop is popular enough to make it worth unrolling a
13695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      bit, at least on ppc32. */
13705f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0);
13715f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   for (j = 0; j < VG_TT_FAST_SIZE; j += 4) {
13725f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+0].guest = TRANSTAB_BOGUS_GUEST_ADDR;
13735f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+1].guest = TRANSTAB_BOGUS_GUEST_ADDR;
13745f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+2].guest = TRANSTAB_BOGUS_GUEST_ADDR;
13755f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+3].guest = TRANSTAB_BOGUS_GUEST_ADDR;
13765f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
13775f76de086a6d643db51e50a4e623df7dfc9b6161sewardj
13785f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(j == VG_TT_FAST_SIZE);
1379fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_flushes++;
13806c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1381de4a1d01951937632098a6cda45859afa587a06fsewardj
1382bece82eba7ba26398a673def2fa326341c4f8ef7philippe
1383523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic TTEno get_empty_tt_slot(SECno sNo)
1384bece82eba7ba26398a673def2fa326341c4f8ef7philippe{
1385523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   TTEno i;
1386bece82eba7ba26398a673def2fa326341c4f8ef7philippe
1387bece82eba7ba26398a673def2fa326341c4f8ef7philippe   i = sectors[sNo].empty_tt_list;
1388bece82eba7ba26398a673def2fa326341c4f8ef7philippe   sectors[sNo].empty_tt_list = sectors[sNo].tt[i].usage.next_empty_tte;
1389bece82eba7ba26398a673def2fa326341c4f8ef7philippe
1390bece82eba7ba26398a673def2fa326341c4f8ef7philippe   vg_assert (i >= 0 && i < N_TTES_PER_SECTOR);
1391bece82eba7ba26398a673def2fa326341c4f8ef7philippe
1392bece82eba7ba26398a673def2fa326341c4f8ef7philippe   return i;
1393bece82eba7ba26398a673def2fa326341c4f8ef7philippe}
1394bece82eba7ba26398a673def2fa326341c4f8ef7philippe
1395523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic void add_in_empty_tt_list (SECno sNo, TTEno tteno)
1396bece82eba7ba26398a673def2fa326341c4f8ef7philippe{
1397bece82eba7ba26398a673def2fa326341c4f8ef7philippe   sectors[sNo].tt[tteno].usage.next_empty_tte = sectors[sNo].empty_tt_list;
1398bece82eba7ba26398a673def2fa326341c4f8ef7philippe   sectors[sNo].empty_tt_list = tteno;
1399bece82eba7ba26398a673def2fa326341c4f8ef7philippe}
1400bece82eba7ba26398a673def2fa326341c4f8ef7philippe
1401523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic void initialiseSector ( SECno sno )
14026c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1403523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   UInt i;
1404291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   SysRes  sres;
14056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
1406fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(sno));
1407fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
14085d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   { Bool sane = sanity_check_sector_search_order();
14095d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj     vg_assert(sane);
14105d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
14116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec = &sectors[sno];
14126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
14136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->tc == NULL) {
14146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1415fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Sector has never been used before.  Need to allocate tt and
1416fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         tc. */
14176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt == NULL);
14186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tc_next == NULL);
14196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt_n_inuse == 0);
14206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
14216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte_size[i] == 0);
14226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte_used[i] == 0);
14236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte[i] == NULL);
14246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
1425291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(sec->host_extents == NULL);
142645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
14275e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe      if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1)
1428059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj         VG_(dmsg)("transtab: " "allocate sector %d\n", sno);
142945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
143045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ );
1431cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
143245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TC)",
143345f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     8 * tc_sector_szQ );
143445f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
143545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
143644bd4465581ff28cef83bb39e684a489297d7b71florian      sec->tc = (ULong*)(Addr)sr_Res(sres);
143745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
143845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)
143945f4e7c91119c7d01a59f5e827c67841632c9314sewardj                ( N_TTES_PER_SECTOR * sizeof(TTEntry) );
1440cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
144145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TT)",
144245f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     N_TTES_PER_SECTOR * sizeof(TTEntry) );
144345f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
144445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
144544bd4465581ff28cef83bb39e684a489297d7b71florian      sec->tt = (TTEntry*)(Addr)sr_Res(sres);
1446bece82eba7ba26398a673def2fa326341c4f8ef7philippe      sec->empty_tt_list = HTT_EMPTY;
1447523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      for (TTEno ei = 0; ei < N_TTES_PER_SECTOR; ei++) {
1448523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         sec->tt[ei].status   = Empty;
1449523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         sec->tt[ei].n_tte2ec = 0;
1450523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         add_in_empty_tt_list(sno, ei);
14516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
1452523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe
1453523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      sres = VG_(am_mmap_anon_float_valgrind)
1454523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                ( N_HTTES_PER_SECTOR * sizeof(TTEno) );
1455523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      if (sr_isError(sres)) {
1456523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         VG_(out_of_memory_NORETURN)("initialiseSector(HTT)",
1457523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                                     N_HTTES_PER_SECTOR * sizeof(TTEno) );
1458523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe	 /*NOTREACHED*/
1459523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      }
1460523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      sec->htt = (TTEno*)(Addr)sr_Res(sres);
1461523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      for (HTTno hi = 0; hi < N_HTTES_PER_SECTOR; hi++)
1462523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         sec->htt[hi] = HTT_EMPTY;
146345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1464291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Set up the host_extents array. */
1465291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      sec->host_extents
1466291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         = VG_(newXA)(ttaux_malloc, "transtab.initialiseSector(host_extents)",
1467291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                      ttaux_free,
1468291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                      sizeof(HostExtent));
1469291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
14705d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      /* Add an entry in the sector_search_order */
14718e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (i = 0; i < n_sectors; i++) {
1472523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         if (sector_search_order[i] == INV_SNO)
14735d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            break;
14745d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
14758e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      vg_assert(i >= 0 && i < n_sectors);
14765d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sector_search_order[i] = sno;
14775d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1478fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
1479738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d\n", sno);
14806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1481fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   } else {
14826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
14836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Sector has been used before.  Dump the old contents. */
14845e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe      if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1)
14851bb648db3172e70b73a8ca3a3f3c12ffc1dcd263sewardj         VG_(dmsg)("transtab: " "recycle  sector %d\n", sno);
14865e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe      n_sectors_recycled++;
1487059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj
14886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt != NULL);
14896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tc_next != NULL);
14906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      n_dump_count += sec->tt_n_inuse;
14916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1492597314210494248b4fbefd45525a748439629218sewardj      VexArch     arch_host = VexArch_INVALID;
1493597314210494248b4fbefd45525a748439629218sewardj      VexArchInfo archinfo_host;
1494597314210494248b4fbefd45525a748439629218sewardj      VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host));
1495597314210494248b4fbefd45525a748439629218sewardj      VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host );
1496597314210494248b4fbefd45525a748439629218sewardj      VexEndness endness_host = archinfo_host.endness;
1497291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
14986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Visit each just-about-to-be-abandoned translation. */
14993a5322057616d0da214b9e0f897866e203c03e40philippe      if (DEBUG_TRANSTAB) VG_(printf)("QQQ unlink-entire-sector: %d START\n",
15003a5322057616d0da214b9e0f897866e203c03e40philippe                                      sno);
1501bece82eba7ba26398a673def2fa326341c4f8ef7philippe      sec->empty_tt_list = HTT_EMPTY;
1502523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      for (TTEno ei = 0; ei < N_TTES_PER_SECTOR; ei++) {
1503523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         if (sec->tt[ei].status == InUse) {
1504523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe            vg_assert(sec->tt[ei].n_tte2ec >= 1);
1505523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe            vg_assert(sec->tt[ei].n_tte2ec <= 3);
1506523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe            n_dump_osize += vge_osize(&sec->tt[ei].vge);
15073786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            /* Tell the tool too. */
15080b9d74abd0a663b530d290b2b788ddeda46e5400sewardj            if (VG_(needs).superblock_discards) {
15090b9d74abd0a663b530d290b2b788ddeda46e5400sewardj               VG_TDICT_CALL( tool_discard_superblock_info,
1510523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                              sec->tt[ei].entry,
1511523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                              sec->tt[ei].vge );
15123786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            }
1513597314210494248b4fbefd45525a748439629218sewardj            unchain_in_preparation_for_deletion(arch_host,
1514523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                                                endness_host, sno, ei);
15156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         } else {
1516523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe            vg_assert(sec->tt[ei].n_tte2ec == 0);
15176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
1518523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         sec->tt[ei].status   = Empty;
1519523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         sec->tt[ei].n_tte2ec = 0;
1520523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         add_in_empty_tt_list(sno, ei);
15216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
1522523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      for (HTTno hi = 0; hi < N_HTTES_PER_SECTOR; hi++)
1523523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         sec->htt[hi] = HTT_EMPTY;
1524bece82eba7ba26398a673def2fa326341c4f8ef7philippe
15253a5322057616d0da214b9e0f897866e203c03e40philippe      if (DEBUG_TRANSTAB) VG_(printf)("QQQ unlink-entire-sector: %d END\n",
15263a5322057616d0da214b9e0f897866e203c03e40philippe                                      sno);
15276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
15286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Free up the eclass structures. */
15296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
15306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->ec2tte_size[i] == 0) {
15316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte_used[i] == 0);
15326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte[i] == NULL);
15336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         } else {
15346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte[i] != NULL);
1535291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            ttaux_free(sec->ec2tte[i]);
15366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte[i] = NULL;
15376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte_size[i] = 0;
15386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte_used[i] = 0;
1539fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
1540fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      }
15416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1542291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Empty out the host extents array. */
1543291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(sec->host_extents != NULL);
1544291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(dropTailXA)(sec->host_extents, VG_(sizeXA)(sec->host_extents));
1545291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(VG_(sizeXA)(sec->host_extents) == 0);
1546291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
15475d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      /* Sanity check: ensure it is already in
15485d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         sector_search_order[]. */
1549523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      SECno ix;
1550523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      for (ix = 0; ix < n_sectors; ix++) {
1551523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         if (sector_search_order[ix] == sno)
15525d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            break;
15535d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
1554523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      vg_assert(ix >= 0 && ix < n_sectors);
15555d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1556fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
1557738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d\n", sno);
15586c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
15594ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
15606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tc_next = sec->tc;
15616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tt_n_inuse = 0;
1562fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1563fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
15645d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
15655d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   { Bool sane = sanity_check_sector_search_order();
15665d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj     vg_assert(sane);
15675d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
15686c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1569de4a1d01951937632098a6cda45859afa587a06fsewardj
1570fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC.  The translation is temporarily
1571fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   in code[0 .. code_len-1].
1572de4a1d01951937632098a6cda45859afa587a06fsewardj
1573fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   pre: youngest_sector points to a valid (although possibly full)
1574fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.
1575fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
1576518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid VG_(add_to_transtab)( const VexGuestExtents* vge,
1577ddd61ff058f02059064e083a8accaefed23d5548florian                           Addr             entry,
157844bd4465581ff28cef83bb39e684a489297d7b71florian                           Addr             code,
157926412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                           UInt             code_len,
1580291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                           Bool             is_self_checking,
1581291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                           Int              offs_profInc,
1582597314210494248b4fbefd45525a748439629218sewardj                           UInt             n_guest_instrs )
158322854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{
1584523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   Int    tcAvailQ, reqdQ, y;
15855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   ULong  *tcptr, *tcptr2;
1586fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* srcP;
1587fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* dstP;
1588fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1589663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1590fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
1591e808930793aeddc4cfd3e7a94b665913bec2566csewardj
1592e808930793aeddc4cfd3e7a94b665913bec2566csewardj   /* 60000: should agree with N_TMPBUF in m_translate.c. */
1593e808930793aeddc4cfd3e7a94b665913bec2566csewardj   vg_assert(code_len > 0 && code_len < 60000);
1594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1595b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj   /* Generally stay sane */
1596b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj   vg_assert(n_guest_instrs < 200); /* it can be zero, tho */
1597b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj
15983a5322057616d0da214b9e0f897866e203c03e40philippe   if (DEBUG_TRANSTAB)
1599ddd61ff058f02059064e083a8accaefed23d5548florian      VG_(printf)("add_to_transtab(entry = 0x%lx, len = %u) ...\n",
1600fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                  entry, code_len);
1601fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1602fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_count++;
1603fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_tsize += code_len;
1604fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_osize += vge_osize(vge);
160526412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   if (is_self_checking)
160626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj      n_in_sc_count++;
1607fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1608fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   y = youngest_sector;
1609fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(y));
1610fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1611fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sectors[y].tc == NULL)
1612fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
1613fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1614fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Try putting the translation in this sector. */
16155f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   reqdQ = (code_len + 7) >> 3;
1616fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1617fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Will it fit in tc? */
1618fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
1619fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
1620fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
1621fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
1622fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1623fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (tcAvailQ < reqdQ
1624bece82eba7ba26398a673def2fa326341c4f8ef7philippe       || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR) {
1625fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* No.  So move on to the next sector.  Either it's never been
1626fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         used before, in which case it will get its tt/tc allocated
1627fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         now, or it has been used before, in which case it is set to be
1628fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         empty, hence throwing out the oldest sector. */
1629a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj      vg_assert(tc_sector_szQ > 0);
1630059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj      Int tt_loading_pct = (100 * sectors[y].tt_n_inuse)
1631bece82eba7ba26398a673def2fa326341c4f8ef7philippe                           / N_HTTES_PER_SECTOR;
1632059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj      Int tc_loading_pct = (100 * (tc_sector_szQ - tcAvailQ))
1633059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj                           / tc_sector_szQ;
16345e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe      if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1) {
1635059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj         VG_(dmsg)("transtab: "
16361bb648db3172e70b73a8ca3a3f3c12ffc1dcd263sewardj                   "declare  sector %d full "
16375e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                   "(TT loading %2d%%, TC loading %2d%%, avg tce size %d)\n",
16385e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                   y, tt_loading_pct, tc_loading_pct,
16395e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                   8 * (tc_sector_szQ - tcAvailQ)/sectors[y].tt_n_inuse);
1640059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj      }
1641fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      youngest_sector++;
16428e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      if (youngest_sector >= n_sectors)
1643fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         youngest_sector = 0;
1644fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      y = youngest_sector;
1645fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
1646fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
164722854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
1648fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Be sure ... */
1649fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
1650fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
1651fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
1652fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
1653fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= reqdQ);
1654bece82eba7ba26398a673def2fa326341c4f8ef7philippe   vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR);
1655fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse >= 0);
1656fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1657fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Copy into tc. */
16585f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tcptr = sectors[y].tc_next;
16595f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr >= &sectors[y].tc[0]);
16605f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr <= &sectors[y].tc[tc_sector_szQ]);
1661fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
16625f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   dstP = (UChar*)tcptr;
1663fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   srcP = (UChar*)code;
1664291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(memcpy)(dstP, srcP, code_len);
1665fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tc_next += reqdQ;
1666fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt_n_inuse++;
1667fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1668fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* more paranoia */
16695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tcptr2 = sectors[y].tc_next;
16705f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 >= &sectors[y].tc[0]);
16715f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 <= &sectors[y].tc[tc_sector_szQ]);
1672fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1673fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find an empty tt slot, and use it.  There must be such a slot
1674fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      since tt is never allowed to get completely full. */
1675523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   TTEno tteix = get_empty_tt_slot(y);
1676523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   TTEntry__init(&sectors[y].tt[tteix]);
1677523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   sectors[y].tt[tteix].status = InUse;
1678523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   sectors[y].tt[tteix].tcptr  = tcptr;
1679523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   sectors[y].tt[tteix].usage.prof.count  = 0;
1680523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   sectors[y].tt[tteix].usage.prof.weight =
1681bece82eba7ba26398a673def2fa326341c4f8ef7philippe      n_guest_instrs == 0 ? 1 : n_guest_instrs;
1682523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   sectors[y].tt[tteix].vge    = *vge;
1683523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   sectors[y].tt[tteix].entry  = entry;
1684fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1685bece82eba7ba26398a673def2fa326341c4f8ef7philippe   // Point an htt entry to the tt slot
1686523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   HTTno htti = HASH_TT(entry);
1687bece82eba7ba26398a673def2fa326341c4f8ef7philippe   vg_assert(htti >= 0 && htti < N_HTTES_PER_SECTOR);
1688bece82eba7ba26398a673def2fa326341c4f8ef7philippe   while (True) {
1689bece82eba7ba26398a673def2fa326341c4f8ef7philippe      if (sectors[y].htt[htti] == HTT_EMPTY
1690bece82eba7ba26398a673def2fa326341c4f8ef7philippe          || sectors[y].htt[htti] == HTT_DELETED)
1691bece82eba7ba26398a673def2fa326341c4f8ef7philippe         break;
1692bece82eba7ba26398a673def2fa326341c4f8ef7philippe      htti++;
1693bece82eba7ba26398a673def2fa326341c4f8ef7philippe      if (htti >= N_HTTES_PER_SECTOR)
1694bece82eba7ba26398a673def2fa326341c4f8ef7philippe         htti = 0;
1695bece82eba7ba26398a673def2fa326341c4f8ef7philippe   }
1696523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   sectors[y].htt[htti] = tteix;
1697bece82eba7ba26398a673def2fa326341c4f8ef7philippe
1698291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Patch in the profile counter location, if necessary. */
1699291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (offs_profInc != -1) {
1700291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(offs_profInc >= 0 && offs_profInc < code_len);
1701597314210494248b4fbefd45525a748439629218sewardj      VexArch     arch_host = VexArch_INVALID;
1702597314210494248b4fbefd45525a748439629218sewardj      VexArchInfo archinfo_host;
1703597314210494248b4fbefd45525a748439629218sewardj      VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host));
1704597314210494248b4fbefd45525a748439629218sewardj      VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host );
1705597314210494248b4fbefd45525a748439629218sewardj      VexEndness endness_host = archinfo_host.endness;
1706291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VexInvalRange vir
1707597314210494248b4fbefd45525a748439629218sewardj         = LibVEX_PatchProfInc( arch_host, endness_host,
1708291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                dstP + offs_profInc,
1709523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                                &sectors[y].tt[tteix].usage.prof.count );
1710291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(invalidate_icache)( (void*)vir.start, vir.len );
1711291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
1712291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
1713291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( dstP, code_len );
1714291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
1715291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Add this entry to the host_extents map, checking that we're
1716291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      adding in order. */
1717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   { HostExtent hx;
1718291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.start = (UChar*)tcptr;
1719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.len   = code_len;
1720523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe     hx.tteNo = tteix;
1721291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     vg_assert(hx.len > 0); /* bsearch fails w/ zero length entries */
1722291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     XArray* hx_array = sectors[y].host_extents;
1723291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     vg_assert(hx_array);
1724291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     Word n = VG_(sizeXA)(hx_array);
1725291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     if (n > 0) {
1726291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        HostExtent* hx_prev = (HostExtent*)VG_(indexXA)(hx_array, n-1);
1727291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        vg_assert(hx_prev->start + hx_prev->len <= hx.start);
1728291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     }
1729291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     VG_(addToXA)(hx_array, &hx);
17303a5322057616d0da214b9e0f897866e203c03e40philippe     if (DEBUG_TRANSTAB)
17313a5322057616d0da214b9e0f897866e203c03e40philippe        VG_(printf)("... hx.start 0x%p hx.len %u sector %d ttslot %d\n",
1732523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                    hx.start, hx.len, y, tteix);
1733291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
1734291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
17356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Update the fast-cache. */
1736291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   setFastCacheEntry( entry, tcptr );
17376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Note the eclass numbers for this translation. */
1739523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   upd_eclasses_after_add( &sectors[y], tteix );
174022854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj}
174122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
1742fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1743fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address.  If
1744fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   requested, a successful search can also cause the fast-caches to be
1745523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   updated.
1746fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
174744bd4465581ff28cef83bb39e684a489297d7b71florianBool VG_(search_transtab) ( /*OUT*/Addr*  res_hcode,
1748523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                            /*OUT*/SECno* res_sNo,
1749523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe                            /*OUT*/TTEno* res_tteNo,
1750ddd61ff058f02059064e083a8accaefed23d5548florian                            Addr          guest_addr,
1751fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                            Bool          upd_cache )
17526c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1753523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   SECno i, sno;
1754523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   HTTno j, k, kstart;
1755523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   TTEno tti;
1756663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
1757663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1758fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find the initial probe point just once.  It will be the same in
1759fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      all sectors and avoids multiple expensive % operations. */
1760fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_full_lookups++;
1761fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   kstart = HASH_TT(guest_addr);
1762bece82eba7ba26398a673def2fa326341c4f8ef7philippe   vg_assert(kstart >= 0 && kstart < N_HTTES_PER_SECTOR);
1763fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
17645d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Search in all the sectors,using sector_search_order[] as a
17655d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      heuristic guide as to what order to visit the sectors. */
17668e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
1767fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
17685d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sno = sector_search_order[i];
1769523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      if (UNLIKELY(sno == INV_SNO))
17705d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         return False; /* run out of sectors to search */
1771fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1772fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      k = kstart;
1773bece82eba7ba26398a673def2fa326341c4f8ef7philippe      for (j = 0; j < N_HTTES_PER_SECTOR; j++) {
1774fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         n_lookup_probes++;
1775bece82eba7ba26398a673def2fa326341c4f8ef7philippe         tti = sectors[sno].htt[k];
1776bece82eba7ba26398a673def2fa326341c4f8ef7philippe         if (tti < N_TTES_PER_SECTOR
1777bece82eba7ba26398a673def2fa326341c4f8ef7philippe             && sectors[sno].tt[tti].entry == guest_addr) {
1778fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            /* found it */
1779fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (upd_cache)
1780fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               setFastCacheEntry(
1781bece82eba7ba26398a673def2fa326341c4f8ef7philippe                  guest_addr, sectors[sno].tt[tti].tcptr );
1782291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_hcode)
1783bece82eba7ba26398a673def2fa326341c4f8ef7philippe               *res_hcode = (Addr)sectors[sno].tt[tti].tcptr;
1784291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_sNo)
1785291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj               *res_sNo = sno;
1786291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_tteNo)
1787bece82eba7ba26398a673def2fa326341c4f8ef7philippe               *res_tteNo = tti;
17885d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            /* pull this one one step closer to the front.  For large
17895d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               apps this more or less halves the number of required
17905d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               probes. */
17915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            if (i > 0) {
17925d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               Int tmp = sector_search_order[i-1];
17935d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               sector_search_order[i-1] = sector_search_order[i];
17945d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               sector_search_order[i] = tmp;
17955d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            }
1796fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            return True;
1797fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
1798bece82eba7ba26398a673def2fa326341c4f8ef7philippe         // tti is HTT_EMPTY or HTT_DELETED or not the entry of guest_addr
1799bece82eba7ba26398a673def2fa326341c4f8ef7philippe         if (sectors[sno].htt[k] == HTT_EMPTY)
1800fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            break; /* not found in this sector */
1801fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         k++;
1802bece82eba7ba26398a673def2fa326341c4f8ef7philippe         if (k == N_HTTES_PER_SECTOR)
1803fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            k = 0;
18046c3769f487145a08c01b58d6e5db3ba274062ad4sewardj      }
1805fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1806fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* If we fall off the end, all entries are InUse and not
1807fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         matching, or Deleted.  In any case we did not find it in this
1808fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         sector. */
18096c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
1810fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1811fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Not found in any sector. */
1812fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
18136c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1814de4a1d01951937632098a6cda45859afa587a06fsewardj
1815de4a1d01951937632098a6cda45859afa587a06fsewardj
18166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
18176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Delete translations.                                  ---*/
18186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
18196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18200ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* forward */
1821ddd61ff058f02059064e083a8accaefed23d5548florianstatic void unredir_discard_translations( Addr, ULong );
18220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
18236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Stuff for deleting translations which intersect with a given
18246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   address range.  Unfortunately, to make this run at a reasonable
18256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   speed, it is complex. */
1826fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1827fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
1828ddd61ff058f02059064e083a8accaefed23d5548florianBool overlap1 ( Addr s1, ULong r1, Addr s2, ULong r2 )
18296c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1830ddd61ff058f02059064e083a8accaefed23d5548florian   Addr e1 = s1 + r1 - 1;
1831ddd61ff058f02059064e083a8accaefed23d5548florian   Addr e2 = s2 + r2 - 1;
1832fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (e1 < s2 || e2 < s1)
1833fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1834fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
18356c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1836de4a1d01951937632098a6cda45859afa587a06fsewardj
1837fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
1838ddd61ff058f02059064e083a8accaefed23d5548florianBool overlaps ( Addr start, ULong range, const VexGuestExtents* vge )
18396c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1840ddd61ff058f02059064e083a8accaefed23d5548florian   if (overlap1(start, range, vge->base[0], vge->len[0]))
1841fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1842fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 2)
1843fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1844ddd61ff058f02059064e083a8accaefed23d5548florian   if (overlap1(start, range, vge->base[1], vge->len[1]))
1845fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1846fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 3)
1847fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1848ddd61ff058f02059064e083a8accaefed23d5548florian   if (overlap1(start, range, vge->base[2], vge->len[2]))
1849fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1850fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
18516c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1852de4a1d01951937632098a6cda45859afa587a06fsewardj
1853de4a1d01951937632098a6cda45859afa587a06fsewardj
18546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete a tt entry, and update all the eclass data accordingly. */
18556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1856523b5b8ca67d2063afd02342d0138b0dc0ed6706philippestatic void delete_tte ( /*MOD*/Sector* sec, SECno secNo, TTEno tteno,
1857597314210494248b4fbefd45525a748439629218sewardj                         VexArch arch_host, VexEndness endness_host )
18586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
18596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i, ec_num, ec_idx;
18606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
18616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1862291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* sec and secNo are mutually redundant; cross-check. */
1863291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(sec == &sectors[secNo]);
1864291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
18656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR);
18666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte = &sec->tt[tteno];
18676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tte->status == InUse);
18686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tte->n_tte2ec >= 1 && tte->n_tte2ec <= 3);
18696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1870291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Unchain .. */
1871597314210494248b4fbefd45525a748439629218sewardj   unchain_in_preparation_for_deletion(arch_host, endness_host, secNo, tteno);
1872291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
18736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Deal with the ec-to-tte links first. */
18746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < tte->n_tte2ec; i++) {
18756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec_num = (Int)tte->tte2ec_ec[i];
18766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec_idx = tte->tte2ec_ix[i];
18776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_num >= 0 && ec_num < ECLASS_N);
18786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_idx >= 0);
18796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_idx < sec->ec2tte_used[ec_num]);
18806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Assert that the two links point at each other. */
1881523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      vg_assert(sec->ec2tte[ec_num][ec_idx] == tteno);
18826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* "delete" the pointer back to here. */
18836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte[ec_num][ec_idx] = EC2TTE_DELETED;
18846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
18856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Now fix up this TTEntry. */
1887bece82eba7ba26398a673def2fa326341c4f8ef7philippe   /* Mark the entry as deleted in htt.
1888bece82eba7ba26398a673def2fa326341c4f8ef7philippe      Note: we could avoid the below hash table search by
1889bece82eba7ba26398a673def2fa326341c4f8ef7philippe      adding a reference from tte to its hash position in tt. */
1890523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   HTTno j;
1891523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   HTTno k = HASH_TT(tte->entry);
1892523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   vg_assert(k >= 0 && k < N_HTTES_PER_SECTOR);
1893bece82eba7ba26398a673def2fa326341c4f8ef7philippe   for (j = 0; j < N_HTTES_PER_SECTOR; j++) {
1894bece82eba7ba26398a673def2fa326341c4f8ef7philippe      if (sec->htt[k] == tteno)
1895bece82eba7ba26398a673def2fa326341c4f8ef7philippe         break;
1896bece82eba7ba26398a673def2fa326341c4f8ef7philippe      k++;
1897bece82eba7ba26398a673def2fa326341c4f8ef7philippe      if (k == N_HTTES_PER_SECTOR)
1898bece82eba7ba26398a673def2fa326341c4f8ef7philippe         k = 0;
1899bece82eba7ba26398a673def2fa326341c4f8ef7philippe   }
1900bece82eba7ba26398a673def2fa326341c4f8ef7philippe   vg_assert(j < N_HTTES_PER_SECTOR);
1901bece82eba7ba26398a673def2fa326341c4f8ef7philippe   sec->htt[k]   = HTT_DELETED;
19026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->status   = Deleted;
19036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->n_tte2ec = 0;
1904bece82eba7ba26398a673def2fa326341c4f8ef7philippe   add_in_empty_tt_list(secNo, tteno);
19056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Stats .. */
19076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tt_n_inuse--;
19086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_disc_count++;
19096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_disc_osize += vge_osize(&tte->vge);
19106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Tell the tool too. */
19120b9d74abd0a663b530d290b2b788ddeda46e5400sewardj   if (VG_(needs).superblock_discards) {
19130b9d74abd0a663b530d290b2b788ddeda46e5400sewardj      VG_TDICT_CALL( tool_discard_superblock_info,
19144ba057cce1d81a949f5a899b5abb99e90a731bccsewardj                     tte->entry,
19156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                     tte->vge );
19166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
19176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
19186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, but
19216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   only consider translations in the specified eclass. */
19226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
1924523b5b8ca67d2063afd02342d0138b0dc0ed6706philippeBool delete_translations_in_sector_eclass ( /*MOD*/Sector* sec, SECno secNo,
1925ddd61ff058f02059064e083a8accaefed23d5548florian                                            Addr guest_start, ULong range,
1926291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                            Int ec,
1927597314210494248b4fbefd45525a748439629218sewardj                                            VexArch arch_host,
1928597314210494248b4fbefd45525a748439629218sewardj                                            VexEndness endness_host )
19296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
19306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i;
1931523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   TTEno    tteno;
19326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool     anyDeld = False;
19336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
19346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(ec >= 0 && ec < ECLASS_N);
19366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < sec->ec2tte_used[ec]; i++) {
19386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tteno = sec->ec2tte[ec][i];
19406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tteno == EC2TTE_DELETED) {
19416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         /* already deleted */
19426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
19436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
19446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tteno < N_TTES_PER_SECTOR);
19466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte = &sec->tt[tteno];
19486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tte->status == InUse);
19496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (overlaps( guest_start, range, &tte->vge )) {
19516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeld = True;
1952523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         delete_tte( sec, secNo, tteno, arch_host, endness_host );
19536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
19546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
19566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return anyDeld;
19586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
19596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, the
19626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   slow way, by inspecting all translations in sec. */
19636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
1965523b5b8ca67d2063afd02342d0138b0dc0ed6706philippeBool delete_translations_in_sector ( /*MOD*/Sector* sec, SECno secNo,
1966ddd61ff058f02059064e083a8accaefed23d5548florian                                     Addr guest_start, ULong range,
1967597314210494248b4fbefd45525a748439629218sewardj                                     VexArch arch_host,
1968597314210494248b4fbefd45525a748439629218sewardj                                     VexEndness endness_host )
19696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
1970523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   TTEno i;
1971523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   Bool  anyDeld = False;
19726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < N_TTES_PER_SECTOR; i++) {
19746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->tt[i].status == InUse
19756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj          && overlaps( guest_start, range, &sec->tt[i].vge )) {
19766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeld = True;
1977597314210494248b4fbefd45525a748439629218sewardj         delete_tte( sec, secNo, i, arch_host, endness_host );
19786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
19796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
19806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return anyDeld;
19826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
19836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1985ddd61ff058f02059064e083a8accaefed23d5548florianvoid VG_(discard_translations) ( Addr guest_start, ULong range,
19861636d33c13958b9c0e7d3059cdd5005746418eb2florian                                 const HChar* who )
19876c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
19886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
1989523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   SECno   sno;
1990523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   Int     ec;
19916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool    anyDeleted = False;
19926c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1993663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1994663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
1995a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj   VG_(debugLog)(2, "transtab",
1996ddd61ff058f02059064e083a8accaefed23d5548florian                    "discard_translations(0x%lx, %llu) req by %s\n",
199745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                    guest_start, range, who );
199845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
19996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Pre-deletion sanity check */
20006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (VG_(clo_sanity_level >= 4)) {
20016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Bool sane = sanity_check_all_sectors();
20026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sane);
20036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
20046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (range == 0)
20066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return;
20076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
2008597314210494248b4fbefd45525a748439629218sewardj   VexArch     arch_host = VexArch_INVALID;
2009597314210494248b4fbefd45525a748439629218sewardj   VexArchInfo archinfo_host;
2010597314210494248b4fbefd45525a748439629218sewardj   VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host));
2011597314210494248b4fbefd45525a748439629218sewardj   VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host );
2012597314210494248b4fbefd45525a748439629218sewardj   VexEndness endness_host = archinfo_host.endness;
2013291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
20146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* There are two different ways to do this.
20156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      If the range fits within a single address-range equivalence
20176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class, as will be the case for a cache line sized invalidation,
20186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      then we only have to inspect the set of translations listed in
20196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      that equivalence class, and also in the "sin-bin" equivalence
20206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class ECLASS_MISC.
20216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Otherwise, the invalidation is of a larger range and probably
20236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      results from munmap.  In this case it's (probably!) faster just
20246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      to inspect all translations, dump those we don't want, and
20256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      regenerate the equivalence class information (since modifying it
20266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      in-situ is even more expensive).
20276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   */
20286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* First off, figure out if the range falls within a single class,
20306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      and if so which one. */
20316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   ec = ECLASS_MISC;
20336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (range < (1ULL << ECLASS_SHIFT))
20346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec = range_to_eclass( guest_start, (UInt)range );
20356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* if ec is ECLASS_MISC then we aren't looking at just a single
20376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class, so use the slow scheme.  Else use the fast scheme,
20386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      examining 'ec' and ECLASS_MISC. */
20396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (ec != ECLASS_MISC) {
20416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(2, "transtab",
20436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                       "                    FAST, ec = %d\n", ec);
20446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Fast scheme */
20466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec >= 0 && ec < ECLASS_MISC);
20476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20488e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (sno = 0; sno < n_sectors; sno++) {
20496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
20506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
20516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
20526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector_eclass(
2053291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          sec, sno, guest_start, range, ec,
2054597314210494248b4fbefd45525a748439629218sewardj                          arch_host, endness_host
2055291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       );
20566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector_eclass(
2057291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          sec, sno, guest_start, range, ECLASS_MISC,
2058597314210494248b4fbefd45525a748439629218sewardj                          arch_host, endness_host
2059291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       );
20606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
20616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   } else {
20636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* slow scheme */
20656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(2, "transtab",
20676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                       "                    SLOW, ec = %d\n", ec);
20686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20698e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (sno = 0; sno < n_sectors; sno++) {
20706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
20716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
20726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
20736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector(
2074597314210494248b4fbefd45525a748439629218sewardj                          sec, sno, guest_start, range,
2075597314210494248b4fbefd45525a748439629218sewardj                          arch_host, endness_host
2076597314210494248b4fbefd45525a748439629218sewardj                       );
20776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
20786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
2079de4a1d01951937632098a6cda45859afa587a06fsewardj   }
2080de4a1d01951937632098a6cda45859afa587a06fsewardj
2081fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (anyDeleted)
2082fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      invalidateFastCache();
20836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* don't forget the no-redir cache */
20850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_discard_translations( guest_start, range );
20860ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Post-deletion sanity check */
20886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (VG_(clo_sanity_level >= 4)) {
2089523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      TTEno    i;
20906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      TTEntry* tte;
20916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Bool     sane = sanity_check_all_sectors();
20926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sane);
20936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* But now, also check the requested address range isn't
20946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         present anywhere. */
20958e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (sno = 0; sno < n_sectors; sno++) {
20966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
20976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
20986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
20996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         for (i = 0; i < N_TTES_PER_SECTOR; i++) {
21006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            tte = &sec->tt[i];
21016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (tte->status != InUse)
21026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               continue;
21036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(!overlaps( guest_start, range, &tte->vge ));
21046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
21056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
21066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
2107fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
21086c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
21095f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian/* Whether or not tools may discard translations. */
21105f1aeb620eb5a3aab662f8b949b031a77a0d14feflorianBool  VG_(ok_to_discard_translations) = False;
21115f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian
21125f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian/* This function is exported to tools which can use it to discard
21135f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian   translations, provided it is safe to do so. */
21145f1aeb620eb5a3aab662f8b949b031a77a0d14feflorianvoid VG_(discard_translations_safely) ( Addr  start, SizeT len,
21155f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian                                        const HChar* who )
21165f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian{
21175f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian   vg_assert(VG_(ok_to_discard_translations));
21185f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian   VG_(discard_translations)(start, len, who);
21195f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian}
21206c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
2121fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
21220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*--- AUXILIARY: the unredirected TT/TC                    ---*/
21230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/
21240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* A very simple translation cache which holds a small number of
21260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredirected translations.  This is completely independent of the
21270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   main tt/tc structures.  When unredir_tc or unredir_tt becomes full,
21280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   both structures are simply dumped and we start over.
21290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Since these translations are unredirected, the search key is (by
21310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   definition) the first address entry in the .vge field. */
21320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Sized to hold 500 translations of average size 1000 bytes. */
21340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define UNREDIR_SZB   1000
21360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TT  500
21380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TCQ (N_UNREDIR_TT * UNREDIR_SZB / sizeof(ULong))
21390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21400ec07f32bbbb209d749b9974408e6f025ad40b31sewardjtypedef
21410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   struct {
21420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      VexGuestExtents vge;
21430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      Addr            hcode;
21440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      Bool            inUse;
21450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
21460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   UTCEntry;
21470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* We just allocate forwards in _tc, never deleting. */
214978c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic ULong    *unredir_tc;
215078c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic Int      unredir_tc_used = N_UNREDIR_TCQ;
21510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Slots in _tt can come into use and out again (.inUse).
21530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Nevertheless _tt_highwater is maintained so that invalidations
21540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   don't have to scan all the slots when only a few are in use.
21550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   _tt_highwater holds the index of the highest ever allocated
21560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   slot. */
21570ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic UTCEntry unredir_tt[N_UNREDIR_TT];
21580ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Int      unredir_tt_highwater;
21590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21610ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void init_unredir_tt_tc ( void )
21620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
21630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
216478c0c09d429c95115e826ef769ecaa6cff2ac338tom   if (unredir_tc == NULL) {
2165cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      SysRes sres = VG_(am_mmap_anon_float_valgrind)
2166cda2f0fbda4c4b2644babc830244be8aed95de1dnjn                       ( N_UNREDIR_TT * UNREDIR_SZB );
2167cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
2168cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         VG_(out_of_memory_NORETURN)("init_unredir_tt_tc",
2169cda2f0fbda4c4b2644babc830244be8aed95de1dnjn                                     N_UNREDIR_TT * UNREDIR_SZB);
217078c0c09d429c95115e826ef769ecaa6cff2ac338tom         /*NOTREACHED*/
217178c0c09d429c95115e826ef769ecaa6cff2ac338tom      }
217244bd4465581ff28cef83bb39e684a489297d7b71florian      unredir_tc = (ULong *)(Addr)sr_Res(sres);
217378c0c09d429c95115e826ef769ecaa6cff2ac338tom   }
21740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tc_used = 0;
21750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++)
21760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      unredir_tt[i].inUse = False;
21770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt_highwater = -1;
21780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
21790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Do a sanity check; return False on failure. */
21810ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void )
21820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
21830ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
21840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tt_highwater < -1) return False;
21850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tt_highwater >= N_UNREDIR_TT) return False;
21860ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = unredir_tt_highwater+1; i < N_UNREDIR_TT; i++)
21880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].inUse)
21890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         return False;
21900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tc_used < 0) return False;
21920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tc_used > N_UNREDIR_TCQ) return False;
21930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   return True;
21950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
21960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Add an UNREDIRECTED translation of vge to TT/TC.  The translation
21990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   is temporarily in code[0 .. code_len-1].
22000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj*/
2201518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid VG_(add_to_unredir_transtab)( const VexGuestExtents* vge,
2202ddd61ff058f02059064e083a8accaefed23d5548florian                                   Addr             entry,
220344bd4465581ff28cef83bb39e684a489297d7b71florian                                   Addr             code,
22041dcee097db02f9ef3ba355162c4373d90d0e895cnjn                                   UInt             code_len )
22050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
22060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int   i, j, code_szQ;
22070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   HChar *srcP, *dstP;
22080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(sanity_check_redir_tt_tc());
22100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* This is the whole point: it's not redirected! */
22120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(entry == vge->base[0]);
22130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22140ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* How many unredir_tt slots are needed */
22150ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   code_szQ = (code_len + 7) / 8;
22160ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22170ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* Look for an empty unredir_tc slot */
22180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++)
22190ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (!unredir_tt[i].inUse)
22200ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         break;
22210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (i >= N_UNREDIR_TT || code_szQ > (N_UNREDIR_TCQ - unredir_tc_used)) {
22230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      /* It's full; dump everything we currently have */
22240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      init_unredir_tt_tc();
22250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      i = 0;
22260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
22270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used >= 0);
22290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used <= N_UNREDIR_TCQ);
22300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(code_szQ > 0);
22310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(code_szQ + unredir_tc_used <= N_UNREDIR_TCQ);
22320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(i >= 0 && i < N_UNREDIR_TT);
22330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tt[i].inUse == False);
22340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (i > unredir_tt_highwater)
22360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      unredir_tt_highwater = i;
22370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   dstP = (HChar*)&unredir_tc[unredir_tc_used];
22390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   srcP = (HChar*)code;
22400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (j = 0; j < code_len; j++)
22410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      dstP[j] = srcP[j];
22420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
2243291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( dstP, code_len );
2244c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj
22450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].inUse = True;
22460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].vge   = *vge;
22470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].hcode = (Addr)dstP;
22480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tc_used += code_szQ;
22500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used >= 0);
22510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used <= N_UNREDIR_TCQ);
22520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(&dstP[code_len] <= (HChar*)&unredir_tc[unredir_tc_used]);
22540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
22550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
225644bd4465581ff28cef83bb39e684a489297d7b71florianBool VG_(search_unredir_transtab) ( /*OUT*/Addr*  result,
2257ddd61ff058f02059064e083a8accaefed23d5548florian                                    Addr          guest_addr )
22580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
22590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
22600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++) {
22610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (!unredir_tt[i].inUse)
22620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         continue;
22630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].vge.base[0] == guest_addr) {
2264ddd61ff058f02059064e083a8accaefed23d5548florian         *result = unredir_tt[i].hcode;
22650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         return True;
22660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      }
22670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
22680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   return False;
22690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
22700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
2271ddd61ff058f02059064e083a8accaefed23d5548florianstatic void unredir_discard_translations( Addr guest_start, ULong range )
22720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
22730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
22740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(sanity_check_redir_tt_tc());
22760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i <= unredir_tt_highwater; i++) {
22780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].inUse
22790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj          && overlaps( guest_start, range, &unredir_tt[i].vge))
22800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         unredir_tt[i].inUse = False;
22810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
22820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
22830ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/
2286fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation.                                      ---*/
2287fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2288fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2289fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void )
22906c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
2291a11ec17946cdbafb336e9121b64961c0633af2e7sewardj   Int i, avg_codeszQ;
2292de4a1d01951937632098a6cda45859afa587a06fsewardj
2293663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(!init_done);
2294663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   init_done = True;
2295663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
2296fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Otherwise lots of things go wrong... */
2297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sizeof(ULong) == 8);
2298523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   vg_assert(sizeof(TTEno) == sizeof(HTTno));
2299523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   vg_assert(sizeof(TTEno) == 2);
2300523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   vg_assert(N_TTES_PER_SECTOR <= N_HTTES_PER_SECTOR);
2301523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   vg_assert(N_HTTES_PER_SECTOR < INV_TTE);
2302523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   vg_assert(N_HTTES_PER_SECTOR < EC2TTE_DELETED);
2303523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   vg_assert(N_HTTES_PER_SECTOR < HTT_EMPTY);
23045f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache entries really are 2 words long */
23055f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof(Addr) == sizeof(void*));
23065f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof(FastCacheEntry) == 2 * sizeof(Addr));
23075f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache entries are packed back-to-back with no spaces */
2308523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   vg_assert(sizeof( VG_(tt_fast) )
2309523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe             == VG_TT_FAST_SIZE * sizeof(FastCacheEntry));
23105f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache is aligned as we requested.  Not fatal if it
23115f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      isn't, but we might as well make sure. */
23125f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_IS_16_ALIGNED( ((Addr) & VG_(tt_fast)[0]) ));
2313de4a1d01951937632098a6cda45859afa587a06fsewardj
2314fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (VG_(clo_verbosity) > 2)
2315fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2316fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                   "TT/TC: VG_(init_tt_tc) "
2317738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                   "(startup of code management)\n");
2318fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2319fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Figure out how big each tc area should be.  */
2320924c852b5883a7b42298dc8c7542116bd9a8a485philippe   if (VG_(clo_avg_transtab_entry_size) == 0)
2321924c852b5883a7b42298dc8c7542116bd9a8a485philippe      avg_codeszQ   = (VG_(details).avg_translation_sizeB + 7) / 8;
2322924c852b5883a7b42298dc8c7542116bd9a8a485philippe   else
2323924c852b5883a7b42298dc8c7542116bd9a8a485philippe      avg_codeszQ   = (VG_(clo_avg_transtab_entry_size) + 7) / 8;
2324bece82eba7ba26398a673def2fa326341c4f8ef7philippe   tc_sector_szQ = N_TTES_PER_SECTOR * (1 + avg_codeszQ);
2325fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2326fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Ensure the calculated value is not way crazy. */
2327bece82eba7ba26398a673def2fa326341c4f8ef7philippe   vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR);
2328bece82eba7ba26398a673def2fa326341c4f8ef7philippe   vg_assert(tc_sector_szQ <= 100 * N_TTES_PER_SECTOR);
2329fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
23308e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   n_sectors = VG_(clo_num_transtab_sectors);
23318e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   vg_assert(n_sectors >= MIN_N_SECTORS);
23328e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   vg_assert(n_sectors <= MAX_N_SECTORS);
23338e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe
2334a11ec17946cdbafb336e9121b64961c0633af2e7sewardj   /* Initialise the sectors, even the ones we aren't going to use.
2335a11ec17946cdbafb336e9121b64961c0633af2e7sewardj      Set all fields to zero. */
2336fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest_sector = 0;
2337a11ec17946cdbafb336e9121b64961c0633af2e7sewardj   for (i = 0; i < MAX_N_SECTORS; i++)
2338a11ec17946cdbafb336e9121b64961c0633af2e7sewardj      VG_(memset)(&sectors[i], 0, sizeof(sectors[i]));
23394ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
2340a11ec17946cdbafb336e9121b64961c0633af2e7sewardj   /* Initialise the sector_search_order hint table, including the
2341a11ec17946cdbafb336e9121b64961c0633af2e7sewardj      entries we aren't going to use. */
2342a11ec17946cdbafb336e9121b64961c0633af2e7sewardj   for (i = 0; i < MAX_N_SECTORS; i++)
2343523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      sector_search_order[i] = INV_SNO;
23445d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
2345291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Initialise the fast cache. */
2346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
2347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
23480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* and the unredir tt/tc */
23490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   init_unredir_tt_tc();
23500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
23518e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   if (VG_(clo_verbosity) > 2 || VG_(clo_stats)
23528e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe       || VG_(debugLog_getLevel) () >= 2) {
2353fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2354924c852b5883a7b42298dc8c7542116bd9a8a485philippe         "TT/TC: cache: %s--avg-transtab-entry-size=%d, "
2355924c852b5883a7b42298dc8c7542116bd9a8a485philippe         "%stool provided default %d\n",
2356924c852b5883a7b42298dc8c7542116bd9a8a485philippe         VG_(clo_avg_transtab_entry_size) == 0 ? "ignoring " : "using ",
2357924c852b5883a7b42298dc8c7542116bd9a8a485philippe         VG_(clo_avg_transtab_entry_size),
2358924c852b5883a7b42298dc8c7542116bd9a8a485philippe         VG_(clo_avg_transtab_entry_size) == 0 ? "using " : "ignoring ",
2359924c852b5883a7b42298dc8c7542116bd9a8a485philippe         VG_(details).avg_translation_sizeB);
2360924c852b5883a7b42298dc8c7542116bd9a8a485philippe      VG_(message)(Vg_DebugMsg,
2361bece82eba7ba26398a673def2fa326341c4f8ef7philippe         "TT/TC: cache: %d sectors of %d bytes each = %d total TC\n",
23628e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe          n_sectors, 8 * tc_sector_szQ,
23638e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe          n_sectors * 8 * tc_sector_szQ );
2364fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2365bece82eba7ba26398a673def2fa326341c4f8ef7philippe         "TT/TC: table: %d tables[%d]  of %d bytes each = %d total TT\n",
2366bece82eba7ba26398a673def2fa326341c4f8ef7philippe          n_sectors, N_TTES_PER_SECTOR,
2367bece82eba7ba26398a673def2fa326341c4f8ef7philippe          (int)(N_TTES_PER_SECTOR * sizeof(TTEntry)),
23688e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe          (int)(n_sectors * N_TTES_PER_SECTOR * sizeof(TTEntry)));
23698e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      VG_(message)(Vg_DebugMsg,
2370bece82eba7ba26398a673def2fa326341c4f8ef7philippe         "TT/TC: table: %d tt entries each = %d total tt entries\n",
2371bece82eba7ba26398a673def2fa326341c4f8ef7philippe         N_TTES_PER_SECTOR, n_sectors * N_TTES_PER_SECTOR);
2372bece82eba7ba26398a673def2fa326341c4f8ef7philippe      VG_(message)(Vg_DebugMsg,
2373bece82eba7ba26398a673def2fa326341c4f8ef7philippe         "TT/TC: table: %d htt[%d] of %d bytes each = %d total HTT"
2374bece82eba7ba26398a673def2fa326341c4f8ef7philippe                       " (htt[%d] %d%% max occup)\n",
2375bece82eba7ba26398a673def2fa326341c4f8ef7philippe         n_sectors, N_HTTES_PER_SECTOR,
2376523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         (int)(N_HTTES_PER_SECTOR * sizeof(TTEno)),
2377523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe         (int)(n_sectors * N_HTTES_PER_SECTOR * sizeof(TTEno)),
2378bece82eba7ba26398a673def2fa326341c4f8ef7philippe         N_HTTES_PER_SECTOR, SECTOR_TT_LIMIT_PERCENT);
2379fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
2380de4a1d01951937632098a6cda45859afa587a06fsewardj}
2381de4a1d01951937632098a6cda45859afa587a06fsewardj
23824ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
2383fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2384fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics.                             ---*/
2385fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2386fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2387fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong safe_idiv( ULong a, ULong b )
238892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
238992e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   return (b == 0 ? 0 : a / b);
239092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
239192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote
2392fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void )
2393fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
2394fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n_in_count;
2395fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
2396fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2397fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void )
239892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
239992e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2400738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      "    tt/tc: %'llu tt lookups requiring %'llu probes\n",
2401fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_full_lookups, n_lookup_probes );
240292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2403738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      "    tt/tc: %'llu fast-cache updates, %'llu flushes\n",
2404fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_fast_updates, n_fast_flushes );
2405fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
240692e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2407a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                " transtab: new        %'lld "
24085e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                "(%'llu -> %'llu; ratio %'llu:10) [%'llu scs] "
24095e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                "avg tce size %d\n",
2410fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_in_count, n_in_osize, n_in_tsize,
241126412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                safe_idiv(10*n_in_tsize, n_in_osize),
24125e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                n_in_sc_count,
241387d15de937a7fda829d1916bda59b9bcf62a2fd3philippe                (int) (n_in_tsize / n_in_count));
241492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
24155e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                " transtab: dumped     %'llu (%'llu -> ?" "?) "
24165e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                "(sectors recycled %'llu)\n",
24175e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                n_dump_count, n_dump_osize, n_sectors_recycled );
2418fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   VG_(message)(Vg_DebugMsg,
2419738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                " transtab: discarded  %'llu (%'llu -> ?" "?)\n",
2420fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_disc_count, n_disc_osize );
24216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
24223a5322057616d0da214b9e0f897866e203c03e40philippe   if (DEBUG_TRANSTAB) {
24236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int i;
24246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(printf)("\n");
24256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
24266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         VG_(printf)(" %4d", sectors[0].ec2tte_used[i]);
24276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (i % 16 == 15)
24286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            VG_(printf)("\n");
24296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
24306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(printf)("\n\n");
24316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
243292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
2433de4a1d01951937632098a6cda45859afa587a06fsewardj
2434fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2435fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results.                   ---*/
2436fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
24374ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
2438518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic ULong score ( const TTEntry* tte )
2439fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
2440bece82eba7ba26398a673def2fa326341c4f8ef7philippe   return ((ULong)tte->usage.prof.weight) * ((ULong)tte->usage.prof.count);
2441de4a1d01951937632098a6cda45859afa587a06fsewardj}
2442de4a1d01951937632098a6cda45859afa587a06fsewardj
244317c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardjULong VG_(get_SB_profile) ( SBProfEntry tops[], UInt n_tops )
2444de4a1d01951937632098a6cda45859afa587a06fsewardj{
2445523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   SECno sno;
2446523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   Int   r, s;
24472025cf98a3210c175a90fc77cb599cca1643bd68njn   ULong score_total;
2448523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   TTEno i;
2449fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2450fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* First, compute the total weighted count, and find the top N
24512025cf98a3210c175a90fc77cb599cca1643bd68njn      ttes.  tops contains pointers to the most-used n_tops blocks, in
2452fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      descending order (viz, tops[0] is the highest scorer). */
2453523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe   for (s = 0; s < n_tops; s++) {
2454523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      tops[s].addr  = 0;
2455523b5b8ca67d2063afd02342d0138b0dc0ed6706philippe      tops[s].score = 0;
24562025cf98a3210c175a90fc77cb599cca1643bd68njn   }
2457fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2458fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   score_total = 0;
2459fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
24608e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (sno = 0; sno < n_sectors; sno++) {
2461fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[sno].tc == NULL)
246218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         continue;
2463fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
2464fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[i].status != InUse)
2465fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            continue;
2466fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         score_total += score(&sectors[sno].tt[i]);
2467fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* Find the rank for sectors[sno].tt[i]. */
24682025cf98a3210c175a90fc77cb599cca1643bd68njn         r = n_tops-1;
2469fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         while (True) {
2470fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (r == -1)
2471fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               break;
24722025cf98a3210c175a90fc77cb599cca1643bd68njn             if (tops[r].addr == 0) {
2473fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               r--;
2474fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               continue;
2475fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
24762025cf98a3210c175a90fc77cb599cca1643bd68njn             if ( score(&sectors[sno].tt[i]) > tops[r].score ) {
2477fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                r--;
2478fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                continue;
2479fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
2480fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             break;
2481fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
2482fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         r++;
24832025cf98a3210c175a90fc77cb599cca1643bd68njn         vg_assert(r >= 0 && r <= n_tops);
2484fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* This bb should be placed at r, and bbs above it shifted
2485fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            upwards one slot. */
24862025cf98a3210c175a90fc77cb599cca1643bd68njn         if (r < n_tops) {
24872025cf98a3210c175a90fc77cb599cca1643bd68njn            for (s = n_tops-1; s > r; s--)
2488fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               tops[s] = tops[s-1];
24892025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].addr  = sectors[sno].tt[i].entry;
24902025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].score = score( &sectors[sno].tt[i] );
2491fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
2492de4a1d01951937632098a6cda45859afa587a06fsewardj      }
2493de4a1d01951937632098a6cda45859afa587a06fsewardj   }
2494de4a1d01951937632098a6cda45859afa587a06fsewardj
249517c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj   /* Now zero out all the counter fields, so that we can make
249617c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj      multiple calls here and just get the values since the last call,
249717c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj      each time, rather than values accumulated for the whole run. */
24988e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (sno = 0; sno < n_sectors; sno++) {
249917c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj      if (sectors[sno].tc == NULL)
250017c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj         continue;
250117c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
250217c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj         if (sectors[sno].tt[i].status != InUse)
250317c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj            continue;
2504bece82eba7ba26398a673def2fa326341c4f8ef7philippe         sectors[sno].tt[i].usage.prof.count = 0;
250517c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj      }
250617c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj   }
250717c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj
25082025cf98a3210c175a90fc77cb599cca1643bd68njn   return score_total;
2509c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
2510c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
2511de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
25128bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end                                                          ---*/
2513de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
2514