m_transtab.c revision a0b6b2cf9abc7b0d87be1215a245eaccc0452af9
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
114d474d086188fd1f29fa97dbd84d8ea2e589a9b8sewardj   Copyright (C) 2000-2008 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"
341f0d814045aba94e01e62e04e968ca8b970b3d44cerion#include "pub_core_machine.h"    // For VG(machine_get_VexArchInfo)
3597405b2d134b52880d6dbec3eb2929e2002c2542njn#include "pub_core_libcbase.h"
36132bfccd21960e462352175f8553a5bdce8a210cnjn#include "pub_core_libcassert.h"
3736a20fa5f779a0a6fb7b4a90dcaa6376481f1faanjn#include "pub_core_libcprint.h"
382024234c590f408994b373abfb00bc2cd2a90c48njn#include "pub_core_options.h"
3910f08cf5b84882eebbb6712a7be890577650e8adsewardj#include "pub_core_tooliface.h"  // For VG_(details).avg_translation_sizeB
408bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn#include "pub_core_transtab.h"
4145f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_aspacemgr.h"
4245f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_mallocfree.h" // VG_(out_of_memory_NORETURN)
43de4a1d01951937632098a6cda45859afa587a06fsewardj
4418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* #define DEBUG_TRANSTAB */
4518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj
46de4a1d01951937632098a6cda45859afa587a06fsewardj
476c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/
486c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*--- Management of the FIFO-based translation table+cache. ---*/
496c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/
50de4a1d01951937632098a6cda45859afa587a06fsewardj
516c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ CONSTANTS ------------------*/
52de4a1d01951937632098a6cda45859afa587a06fsewardj
53fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of sectors the TC is divided into.  If you need a larger
54fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   overall translation cache, increase this value. */
55fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_SECTORS 8
56de4a1d01951937632098a6cda45859afa587a06fsewardj
57fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of TC entries in each sector.  This needs to be a prime
586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   number to work properly, it must be <= 65535 (so that a TT index
596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   fits in a UShort, leaving room for 0xFFFF(EC2TTE_DELETED) to denote
606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   'deleted') and it is strongly recommended not to change this.
616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   65521 is the largest prime <= 65535. */
626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define N_TTES_PER_SECTOR /*30011*/ /*40009*/ 65521
63de4a1d01951937632098a6cda45859afa587a06fsewardj
64fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to
65fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   specify the maximum allowable loading, after which the sector is
66fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   deemed full. */
676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define SECTOR_TT_LIMIT_PERCENT 80
68de4a1d01951937632098a6cda45859afa587a06fsewardj
69fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */
70fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_TTES_PER_SECTOR_USABLE \
71fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj           ((N_TTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100)
726c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Equivalence classes for fast address range deletion.  There are 1 +
746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   2^ECLASS_WIDTH bins.  The highest one, ECLASS_MISC, describes an
756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   address range which does not fall cleanly within any specific bin.
766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Note that ECLASS_SHIFT + ECLASS_WIDTH must be < 32. */
776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_SHIFT 11
786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_WIDTH 8
796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_MISC  (1 << ECLASS_WIDTH)
806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_N     (1 + ECLASS_MISC)
816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define EC2TTE_DELETED  0xFFFF /* 16-bit special value */
836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
84de4a1d01951937632098a6cda45859afa587a06fsewardj
856c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/
86de4a1d01951937632098a6cda45859afa587a06fsewardj
87fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry.  This indicates precisely which areas of
88fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   guest code are included in the translation, and contains all other
89fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   auxiliary info too.  */
906c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef
916c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   struct {
92fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Profiling only: the count and weight (arbitrary meaning) for
93fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         this translation.  Weight is a property of the translation
94fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         itself and computed once when the translation is created.
95fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         Count is an entry count for the translation and is
96fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         incremented by 1 every time the translation is used, if we
97fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         are profiling. */
98fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      UInt     count;
99fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      UShort   weight;
100fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
101fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Status of the slot.  Note, we need to be able to do lazy
102fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         deletion, hence the Deleted state. */
103fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      enum { InUse, Deleted, Empty } status;
104fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1055f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      /* 64-bit aligned pointer to one or more 64-bit words containing
1065f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         the corresponding host code (must be in the same sector!)
1075f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         This is a pointer into the sector's tc (code) area. */
1085f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      ULong* tcptr;
109fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
110fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This is the original guest address that purportedly is the
111fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         entry point of the translation.  You might think that .entry
112fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         should be the same as .vge->base[0], and most of the time it
113fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         is.  However, when doing redirections, that is not the case.
114fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         .vge must always correctly describe the guest code sections
115fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         from which this translation was made.  However, .entry may or
116fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         may not be a lie, depending on whether or not we're doing
117fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         redirection. */
118fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Addr64 entry;
119fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
120fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This structure describes precisely what ranges of guest code
121fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         the translation covers, so we can decide whether or not to
122fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         delete it when translations of a given address range are
123fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         invalidated. */
124fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VexGuestExtents vge;
1256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Address range summary info: these are pointers back to
1276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         eclass[] entries in the containing Sector.  Those entries in
1286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         turn point back here -- the two structures are mutually
1296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         redundant but both necessary to make fast deletions work.
1306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         The eclass info is similar to, and derived from, this entry's
1316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         'vge' field, but it is not the same */
1326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort n_tte2ec;      // # tte2ec pointers (1 to 3)
1336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort tte2ec_ec[3];  // for each, the eclass #
1346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UInt   tte2ec_ix[3];  // and the index within the eclass.
1356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // for i in 0 .. n_tte2ec-1
1366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      //    sec->ec2tte[ tte2ec_ec[i] ][ tte2ec_ix[i] ]
1376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // should be the index
1386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // of this TTEntry in the containing Sector's tt array.
1396c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
1406c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   TTEntry;
1416c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1424ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
143fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself.  Each sector contains an array of
144fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   TCEntries, which hold code, and an array of TTEntries, containing
145fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   all required administrative info.  Profiling is supported using the
146fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   TTEntry .count and .weight fields, if required.  Each sector is
147fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   independent in that no cross-sector references are allowed.
1484ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
149fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   If the sector is not in use, all three pointers are NULL and
150fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tt_n_inuse is zero.
151fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
152fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef
153fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   struct {
154fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TCEntry area.  Size of this depends on the average
155fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         translation size.  We try and size it so it becomes full
156fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         precisely when this sector's translation table (tt) reaches
157fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         its load limit (SECTOR_TT_LIMIT_PERCENT). */
158fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc;
1594ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
160fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TTEntry array.  This is a fixed size, always containing
161fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         exactly N_TTES_PER_SECTOR entries. */
162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      TTEntry* tt;
1636c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
164fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This points to the current allocation point in tc. */
165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc_next;
166de4a1d01951937632098a6cda45859afa587a06fsewardj
167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The count of tt entries with state InUse. */
168fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Int tt_n_inuse;
1696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Expandable arrays of tt indices for each of the ECLASS_N
1716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         address range equivalence classes.  These hold indices into
1726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         the containing sector's tt array, which in turn should point
1736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         back here. */
1746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int     ec2tte_size[ECLASS_N];
1756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int     ec2tte_used[ECLASS_N];
1766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort* ec2tte[ECLASS_N];
177fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
178fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Sector;
179de4a1d01951937632098a6cda45859afa587a06fsewardj
180de4a1d01951937632098a6cda45859afa587a06fsewardj
1816c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/
1826c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
183fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors.  The index of the
184fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest sector is recorded, and new translations are put into that
185fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.  When it fills up, we move along to the next sector and
186fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   start to fill that up, wrapping around at the end of the array.
187fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   That way, once all N_TC_SECTORS have been bought into use for the
188fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   first time, and are full, we then re-use the oldest sector,
189fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   endlessly.
190fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
191fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   When running, youngest sector should be between >= 0 and <
192fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   N_TC_SECTORS.  The initial -1 value indicates the TT/TC system is
193fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   not yet initialised.
194fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
195fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Sector sectors[N_SECTORS];
196fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int    youngest_sector = -1;
1976c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
198fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area.  This is computed once
199fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   at startup and does not change. */
200fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int    tc_sector_szQ;
2016c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
2026c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
2035f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Fast helper for the TC.  A direct-mapped cache which holds a set of
2045f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   recently used (guest address, host address) pairs.  This array is
2055f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   referred to directly from m_dispatch/dispatch-<platform>.S.
2066c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
2075f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   Entries in tt_fast may refer to any valid TC entry, regardless of
208fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   which sector it's in.  Consequently we must be very careful to
209fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidate this cache when TC entries are changed or disappear.
210c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
2115f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   A special .guest address - TRANSTAB_BOGUS_GUEST_ADDR -- must be
2125f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   pointed at to cause that cache entry to miss.  This relies on the
2135f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   assumption that no guest code actually has that address, hence a
2145f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   value 0x1 seems good.  m_translate gives the client a synthetic
2155f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   segfault if it tries to execute at this address.
2165f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/
2175f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*
2185f76de086a6d643db51e50a4e623df7dfc9b6161sewardjtypedef
2195f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   struct {
2205f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      Addr guest;
2215f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      Addr host;
2225f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
2235f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   FastCacheEntry;
2245f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/
2255f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*global*/ __attribute__((aligned(16)))
2265f76de086a6d643db51e50a4e623df7dfc9b6161sewardj           FastCacheEntry VG_(tt_fast)[VG_TT_FAST_SIZE];
2275f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*
2285f76de086a6d643db51e50a4e623df7dfc9b6161sewardj#define TRANSTAB_BOGUS_GUEST_ADDR ((Addr)1)
229fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
23092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote
231fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* For profiling, we have a parallel array of pointers to .count
232fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   fields in TT entries.  Again, these pointers must be invalidated
233fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   when translations disappear.  A NULL pointer suffices to indicate
234fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   an unused slot.
2356c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
2365f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   When not profiling (the normal case, VG_(clo_profile_flags) == 0),
2375f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   all tt_fastN entries are set to NULL at startup and never read nor
2385f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   written after that.
2395f76de086a6d643db51e50a4e623df7dfc9b6161sewardj
2405f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   When profiling (VG_(clo_profile_flags) > 0), tt_fast and tt_fastN
2415f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   change together: if tt_fast[i].guest is TRANSTAB_BOGUS_GUEST_ADDR
2425f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   then the corresponding tt_fastN[i] must be null.  If
2435f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tt_fast[i].guest is any other value, then tt_fastN[i] *must* point
2445f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   to the .count field of the corresponding TT entry.
2456c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
246fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tt_fast and tt_fastN are referred to from assembly code
247fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   (dispatch.S).
248fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
249fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*global*/ UInt* VG_(tt_fastN)[VG_TT_FAST_SIZE];
250de4a1d01951937632098a6cda45859afa587a06fsewardj
251de4a1d01951937632098a6cda45859afa587a06fsewardj
252663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */
253663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False;
254663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
255663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
256fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/
257de4a1d01951937632098a6cda45859afa587a06fsewardj
258fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */
259fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_fast_flushes = 0;
260fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_fast_updates = 0;
26122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
262fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */
263fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_full_lookups = 0;
264fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_lookup_probes = 0;
26522854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
26626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj/* Number/osize/tsize of translations entered; also the number of
26726412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   those for which self-checking was requested. */
26826412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_count    = 0;
26926412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_osize    = 0;
27026412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_tsize    = 0;
27126412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_sc_count = 0;
272de4a1d01951937632098a6cda45859afa587a06fsewardj
273fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */
274fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_dump_count = 0;
275fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_dump_osize = 0;
276fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
277fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */
278fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_disc_count = 0;
279fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_disc_osize = 0;
280fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
281fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
2836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Address-range equivalence class stuff                 ---*/
2846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
2856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
2866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Return equivalence class number for a range. */
2876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
2886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Int range_to_eclass ( Addr64 start, UInt len )
2896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
2906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt mask   = (1 << ECLASS_WIDTH) - 1;
2916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt lo     = (UInt)start;
2926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt hi     = lo + len - 1;
2936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt loBits = (lo >> ECLASS_SHIFT) & mask;
2946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt hiBits = (hi >> ECLASS_SHIFT) & mask;
2956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (loBits == hiBits) {
2966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(loBits < ECLASS_N-1);
2976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return loBits;
2986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   } else {
2996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return ECLASS_MISC;
3006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
3016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
3026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Calculates the equivalence class numbers for any VexGuestExtent.
3056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   These are written in *eclasses, which must be big enough to hold 3
3066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Ints.  The number written, between 1 and 3, is returned.  The
3076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclasses are presented in order, and any duplicates are removed.
3086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj*/
3096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
3116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjInt vexGuestExtents_to_eclasses ( /*OUT*/Int* eclasses,
3126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                  VexGuestExtents* vge )
3136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
3146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  define SWAP(_lv1,_lv2) \
3156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      do { Int t = _lv1; _lv1 = _lv2; _lv2 = t; } while (0)
3166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, j, n_ec, r;
3186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
3206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_ec = 0;
3226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < vge->n_used; i++) {
3236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      r = range_to_eclass( vge->base[i], (UInt)vge->len[i] );
3246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (r == ECLASS_MISC)
3256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         goto bad;
3266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* only add if we haven't already seen it */
3276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < n_ec; j++)
3286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (eclasses[j] == r)
3296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            break;
3306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (j == n_ec)
3316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         eclasses[n_ec++] = r;
3326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
3336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 1)
3356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 1;
3366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 2) {
3386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* sort */
3396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[1])
3406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[1]);
3416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 2;
3426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
3436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 3) {
3456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* sort */
3466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[2])
3476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[2]);
3486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[1])
3496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[1]);
3506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[1] > eclasses[2])
3516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[1], eclasses[2]);
3526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 3;
3536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
3546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* NOTREACHED */
3566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(0);
3576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj  bad:
3596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclasses[0] = ECLASS_MISC;
3606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return 1;
3616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  undef SWAP
3636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
3646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Add tteno to the set of entries listed for equivalence class ec in
3676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   this sector.  Returns used location in eclass array. */
3686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
3706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjUInt addEClassNo ( /*MOD*/Sector* sec, Int ec, UShort tteno )
3716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
3726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int    old_sz, new_sz, i, r;
3736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort *old_ar, *new_ar;
3746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(ec >= 0 && ec < ECLASS_N);
3766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno < N_TTES_PER_SECTOR);
3776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (0) VG_(printf)("ec %d  gets %d\n", ec, (Int)tteno);
3796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->ec2tte_used[ec] >= sec->ec2tte_size[ec]) {
3816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->ec2tte_used[ec] == sec->ec2tte_size[ec]);
3836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      old_sz = sec->ec2tte_size[ec];
3856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      old_ar = sec->ec2tte[ec];
3866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      new_sz = old_sz==0 ? 8 : old_sz<64 ? 2*old_sz : (3*old_sz)/2;
3876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      new_ar = VG_(arena_malloc)(VG_AR_TTAUX, new_sz * sizeof(UShort));
3886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < old_sz; i++)
3896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         new_ar[i] = old_ar[i];
3906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (old_ar)
3916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         VG_(arena_free)(VG_AR_TTAUX, old_ar);
3926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte_size[ec] = new_sz;
3936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte[ec] = new_ar;
3946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (0) VG_(printf)("expand ec %d to %d\n", ec, new_sz);
3966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
3976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Common case */
3996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   r = sec->ec2tte_used[ec]++;
4006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(r >= 0 && r < sec->ec2tte_size[ec]);
4016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->ec2tte[ec][r] = tteno;
4026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return (UInt)r;
4036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
4046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* 'vge' is being added to 'sec' at TT entry 'tteno'.  Add appropriate
4076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclass entries to 'sec'. */
4086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
4106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjvoid upd_eclasses_after_add ( /*MOD*/Sector* sec, Int tteno )
4116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
4126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, r, eclasses[3];
4136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
4146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR);
4156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte = &sec->tt[tteno];
4176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   r = vexGuestExtents_to_eclasses( eclasses, &tte->vge );
4186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(r >= 1 && r <= 3);
4206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->n_tte2ec = r;
4216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < r; i++) {
4236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte->tte2ec_ec[i] = eclasses[i];
4246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte->tte2ec_ix[i] = addEClassNo( sec, eclasses[i], (UShort)tteno );
4256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
4266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
4276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Check the eclass info in 'sec' to ensure it is consistent.  Returns
4306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   True if OK, False if something's not right.  Expensive. */
4316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_eclasses_in_sector ( Sector* sec )
4336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
4346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  define BAD(_str) do { whassup = (_str); goto bad; } while (0)
4356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   HChar*   whassup = NULL;
4376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i, j, k, n, ec_num, ec_idx;
4386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
4396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort   tteno;
4406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   ULong*   tce;
4416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Basic checks on this sector */
4436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->tt_n_inuse < 0 || sec->tt_n_inuse > N_TTES_PER_SECTOR_USABLE)
4446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      BAD("invalid sec->tt_n_inuse");
4456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tce = sec->tc_next;
4466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (tce < &sec->tc[0] || tce > &sec->tc[tc_sector_szQ])
4476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      BAD("sec->tc_next points outside tc");
4486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* For each eclass ... */
4506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < ECLASS_N; i++) {
4516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_size[i] == 0 && sec->ec2tte[i] != NULL)
4526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("ec2tte_size/ec2tte mismatch(1)");
4536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_size[i] != 0 && sec->ec2tte[i] == NULL)
4546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("ec2tte_size/ec2tte mismatch(2)");
4556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_used[i] < 0
4566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj          || sec->ec2tte_used[i] > sec->ec2tte_size[i])
4576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("implausible ec2tte_used");
4586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_used[i] == 0)
4596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
4606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* For each tt reference in each eclass .. ensure the reference
4626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         is to a valid tt entry, and that the entry's address ranges
4636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         really include this eclass. */
4646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < sec->ec2tte_used[i]; j++) {
4666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         tteno = sec->ec2tte[i][j];
4676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tteno == EC2TTE_DELETED)
4686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
4696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tteno >= N_TTES_PER_SECTOR)
4706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("implausible tteno");
4716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         tte = &sec->tt[tteno];
4726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->status != InUse)
4736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tteno points to non-inuse tte");
4746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3)
4756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->n_tte2ec out of range");
4766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         /* Exactly least one of tte->eclasses[0 .. tte->n_eclasses-1]
4776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            must equal i.  Inspect tte's eclass info. */
4786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         n = 0;
4796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         for (k = 0; k < tte->n_tte2ec; k++) {
4806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (k < tte->n_tte2ec-1
4816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                && tte->tte2ec_ec[k] >= tte->tte2ec_ec[k+1])
4826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ec[..] out of order");
4836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            ec_num = tte->tte2ec_ec[k];
4846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_num < 0 || ec_num >= ECLASS_N)
4856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ec[..] out of range");
4866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_num != i)
4876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               continue;
4886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            ec_idx = tte->tte2ec_ix[k];
4896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[i])
4906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ix[..] out of range");
4916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_idx == j)
4926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               n++;
4936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
4946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (n != 1)
4956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tteno does not point back at eclass");
4966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
4976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
4986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
4996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* That establishes that for each forward pointer from TTEntrys
5006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      there is a corresponding backward pointer from the eclass[]
5016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      arrays.  However, it doesn't rule out the possibility of other,
5026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      bogus pointers in the eclass[] arrays.  So do those similarly:
5036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      scan through them and check the TTEntryies they point at point
5046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      back. */
5056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < N_TTES_PER_SECTOR_USABLE; i++) {
5076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte = &sec->tt[i];
5096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tte->status == Empty || tte->status == Deleted) {
5106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->n_tte2ec != 0)
5116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->n_eclasses nonzero for unused tte");
5126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
5136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
5146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tte->status == InUse);
5166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3)
5186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("tte->n_eclasses out of range(2)");
5196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < tte->n_tte2ec; j++) {
5216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         ec_num = tte->tte2ec_ec[j];
5226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (ec_num < 0 || ec_num >= ECLASS_N)
5236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->eclass[..] out of range");
5246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         ec_idx = tte->tte2ec_ix[j];
5256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[ec_num])
5266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->ec_idx[..] out of range(2)");
5276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->ec2tte[ec_num][ec_idx] != i)
5286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("ec2tte does not point back to tte");
5296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
5306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
5316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return True;
5336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj  bad:
5356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (whassup)
5366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(0, "transtab", "eclass sanity fail: %s\n", whassup);
5376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  if 0
5396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   VG_(printf)("eclass = %d\n", i);
5406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   VG_(printf)("tteno = %d\n", (Int)tteno);
5416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   switch (tte->status) {
5426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case InUse:   VG_(printf)("InUse\n"); break;
5436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case Deleted: VG_(printf)("Deleted\n"); break;
5446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case Empty:   VG_(printf)("Empty\n"); break;
5456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
5466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (tte->status != Empty) {
5476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (k = 0; k < tte->vge.n_used; k++)
5486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         VG_(printf)("0x%llx %d\n", tte->vge.base[k],
5496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                    (Int)tte->vge.len[k]);
5506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
5516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  endif
5526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return False;
5546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  undef BAD
5566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
5576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Sanity check absolutely everything.  True == check passed. */
5606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
5615f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* forwards */
5620ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void );
5635f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic Bool sanity_check_fastcache ( void );
5640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
5656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_all_sectors ( void )
5666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
5676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int     sno;
5686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool    sane;
5696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
5706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (sno = 0; sno < N_SECTORS; sno++) {
5716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec = &sectors[sno];
5726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->tc == NULL)
5736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
5746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sane = sanity_check_eclasses_in_sector( sec );
5756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (!sane)
5766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         return False;
5776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
5785f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if ( !sanity_check_redir_tt_tc() )
5795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      return False;
5805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if ( !sanity_check_fastcache() )
5810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      return False;
5826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return True;
5836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
5846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
585fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
586fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
5876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Add/find translations                                 ---*/
588fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
589fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
590fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic UInt vge_osize ( VexGuestExtents* vge )
591c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{
592fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt i, n = 0;
593fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < vge->n_used; i++)
594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n += (UInt)vge->len[i];
595fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n;
596c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
597c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
598fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Bool isValidSector ( Int sector )
5996c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
600fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sector < 0 || sector >= N_SECTORS)
601fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
602fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
6036c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
604de4a1d01951937632098a6cda45859afa587a06fsewardj
605fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline UInt HASH_TT ( Addr64 key )
606de4a1d01951937632098a6cda45859afa587a06fsewardj{
607fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt kHi = (UInt)(key >> 32);
608fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt kLo = (UInt)key;
6096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt k32 = kHi ^ kLo;
6106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt ror = 7;
6116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (ror > 0)
6126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      k32 = (k32 >> ror) | (k32 << (32-ror));
6136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return k32 % N_TTES_PER_SECTOR;
614de4a1d01951937632098a6cda45859afa587a06fsewardj}
615de4a1d01951937632098a6cda45859afa587a06fsewardj
6165f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void setFastCacheEntry ( Addr64 key, ULong* tcptr, UInt* count )
617de4a1d01951937632098a6cda45859afa587a06fsewardj{
6183387dda4479102751d544c176a7bfc24f3766669sewardj   UInt cno = (UInt)VG_TT_FAST_HASH(key);
6195f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   VG_(tt_fast)[cno].guest = (Addr)key;
6205f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   VG_(tt_fast)[cno].host  = (Addr)tcptr;
6215f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if (VG_(clo_profile_flags) > 0)
6225f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fastN)[cno] = count;
623fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_updates++;
6245f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* This shouldn't fail.  It should be assured by m_translate
6255f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      which should reject any attempt to make translation of code
6265f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      starting at TRANSTAB_BOGUS_GUEST_ADDR. */
6275f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_(tt_fast)[cno].guest != TRANSTAB_BOGUS_GUEST_ADDR);
6286c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
629de4a1d01951937632098a6cda45859afa587a06fsewardj
6305f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Invalidate the fast cache's counter array, VG_(tt_fastN). */
6315f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastNCache ( void )
6326c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
633fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt j;
63465e193939481231a8f6699201258e0a2828357e8sewardj   vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0);
63565e193939481231a8f6699201258e0a2828357e8sewardj   for (j = 0; j < VG_TT_FAST_SIZE; j += 4) {
63665e193939481231a8f6699201258e0a2828357e8sewardj      VG_(tt_fastN)[j+0] = NULL;
63765e193939481231a8f6699201258e0a2828357e8sewardj      VG_(tt_fastN)[j+1] = NULL;
63865e193939481231a8f6699201258e0a2828357e8sewardj      VG_(tt_fastN)[j+2] = NULL;
63965e193939481231a8f6699201258e0a2828357e8sewardj      VG_(tt_fastN)[j+3] = NULL;
6406c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
64165e193939481231a8f6699201258e0a2828357e8sewardj   vg_assert(j == VG_TT_FAST_SIZE);
6425f76de086a6d643db51e50a4e623df7dfc9b6161sewardj}
6435f76de086a6d643db51e50a4e623df7dfc9b6161sewardj
6445f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Invalidate the fast cache VG_(tt_fast).  If profiling, also
6455f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   invalidate the fast cache's counter array VG_(tt_fastN), otherwise
6465f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   don't touch it. */
6475f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastCache ( void )
6485f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{
6495f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   UInt j;
6505f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* This loop is popular enough to make it worth unrolling a
6515f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      bit, at least on ppc32. */
6525f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0);
6535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   for (j = 0; j < VG_TT_FAST_SIZE; j += 4) {
6545f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+0].guest = TRANSTAB_BOGUS_GUEST_ADDR;
6555f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+1].guest = TRANSTAB_BOGUS_GUEST_ADDR;
6565f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+2].guest = TRANSTAB_BOGUS_GUEST_ADDR;
6575f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+3].guest = TRANSTAB_BOGUS_GUEST_ADDR;
6585f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
6595f76de086a6d643db51e50a4e623df7dfc9b6161sewardj
6605f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if (VG_(clo_profile_flags) > 0)
6615f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      invalidateFastNCache();
6625f76de086a6d643db51e50a4e623df7dfc9b6161sewardj
6635f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(j == VG_TT_FAST_SIZE);
664fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_flushes++;
6656c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
666de4a1d01951937632098a6cda45859afa587a06fsewardj
6675f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic Bool sanity_check_fastcache ( void )
6685f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{
6695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   UInt j;
6705f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if (0) VG_(printf)("sanity check fastcache\n");
6715f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if (VG_(clo_profile_flags) > 0) {
6725f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      /* profiling */
6735f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      for (j = 0; j < VG_TT_FAST_SIZE; j++) {
6745f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         if (VG_(tt_fastN)[j] == NULL
6755f76de086a6d643db51e50a4e623df7dfc9b6161sewardj             && VG_(tt_fast)[j].guest != TRANSTAB_BOGUS_GUEST_ADDR)
6765f76de086a6d643db51e50a4e623df7dfc9b6161sewardj            return False;
6775f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         if (VG_(tt_fastN)[j] != NULL
6785f76de086a6d643db51e50a4e623df7dfc9b6161sewardj             && VG_(tt_fast)[j].guest == TRANSTAB_BOGUS_GUEST_ADDR)
6795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj            return False;
6805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      }
6815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   } else {
6825f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      /* not profiling */
6835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      for (j = 0; j < VG_TT_FAST_SIZE; j++) {
6845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         if (VG_(tt_fastN)[j] != NULL)
6855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj            return False;
6865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      }
6875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
6885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   return True;
6895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj}
6905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj
691fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void initialiseSector ( Int sno )
6926c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
69345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int    i;
69445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes sres;
6956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
696fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(sno));
697fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
6986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec = &sectors[sno];
6996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
7006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->tc == NULL) {
7016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
702fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Sector has never been used before.  Need to allocate tt and
703fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         tc. */
7046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt == NULL);
7056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tc_next == NULL);
7066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt_n_inuse == 0);
7076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
7086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte_size[i] == 0);
7096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte_used[i] == 0);
7106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte[i] == NULL);
7116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
71245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
71345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(1,"transtab", "allocate sector %d\n", sno);
71445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
71545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ );
71645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (sres.isError) {
71745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TC)",
71845f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     8 * tc_sector_szQ );
71945f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
72045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
721e808930793aeddc4cfd3e7a94b665913bec2566csewardj      sec->tc = (ULong*)sres.res;
72245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
72345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)
72445f4e7c91119c7d01a59f5e827c67841632c9314sewardj                ( N_TTES_PER_SECTOR * sizeof(TTEntry) );
72545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (sres.isError) {
72645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TT)",
72745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     N_TTES_PER_SECTOR * sizeof(TTEntry) );
72845f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
72945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
730e808930793aeddc4cfd3e7a94b665913bec2566csewardj      sec->tt = (TTEntry*)sres.res;
7316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
7326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
7336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].status   = Empty;
7346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].n_tte2ec = 0;
7356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
73645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
737fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
738fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d", sno);
7396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
740fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   } else {
7416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
7426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Sector has been used before.  Dump the old contents. */
74345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(1,"transtab", "recycle sector %d\n", sno);
7446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt != NULL);
7456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tc_next != NULL);
7466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      n_dump_count += sec->tt_n_inuse;
7476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
7486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Visit each just-about-to-be-abandoned translation. */
749fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
7506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tt[i].status == InUse) {
7516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec >= 1);
7526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec <= 3);
7536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            n_dump_osize += vge_osize(&sec->tt[i].vge);
7543786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            /* Tell the tool too. */
7550b9d74abd0a663b530d290b2b788ddeda46e5400sewardj            if (VG_(needs).superblock_discards) {
7560b9d74abd0a663b530d290b2b788ddeda46e5400sewardj               VG_TDICT_CALL( tool_discard_superblock_info,
7574ba057cce1d81a949f5a899b5abb99e90a731bccsewardj                              sec->tt[i].entry,
7586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                              sec->tt[i].vge );
7593786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            }
7606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         } else {
7616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec == 0);
7626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
7636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].status   = Empty;
7646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].n_tte2ec = 0;
7656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
7666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
7676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Free up the eclass structures. */
7686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
7696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->ec2tte_size[i] == 0) {
7706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte_used[i] == 0);
7716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte[i] == NULL);
7726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         } else {
7736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte[i] != NULL);
7746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            VG_(arena_free)(VG_AR_TTAUX, sec->ec2tte[i]);
7756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte[i] = NULL;
7766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte_size[i] = 0;
7776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte_used[i] = 0;
778fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
779fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      }
7806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
781fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
782fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d", sno);
7836c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
7844ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
7856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tc_next = sec->tc;
7866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tt_n_inuse = 0;
787fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
788fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
7896c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
790de4a1d01951937632098a6cda45859afa587a06fsewardj
79110f08cf5b84882eebbb6712a7be890577650e8adsewardjstatic void invalidate_icache ( void *ptr, Int nbytes )
79285665ca6fa29dd64754dabe50eb98f25896e752acerion{
7932c48c7b0a453d32375a4df17e153011b797ef28csewardj#  if defined(VGA_ppc32) || defined(VGA_ppc64)
79410f08cf5b84882eebbb6712a7be890577650e8adsewardj   Addr startaddr = (Addr) ptr;
79510f08cf5b84882eebbb6712a7be890577650e8adsewardj   Addr endaddr   = startaddr + nbytes;
796e3826cfe34ec9a0caa570a0d15647b28711584a0sewardj   Addr cls;
79710f08cf5b84882eebbb6712a7be890577650e8adsewardj   Addr addr;
798e3826cfe34ec9a0caa570a0d15647b28711584a0sewardj   VexArchInfo vai;
799e3826cfe34ec9a0caa570a0d15647b28711584a0sewardj
8005f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if (nbytes == 0) return;
8015f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(nbytes > 0);
8025f76de086a6d643db51e50a4e623df7dfc9b6161sewardj
803e3826cfe34ec9a0caa570a0d15647b28711584a0sewardj   VG_(machine_get_VexArchInfo)( NULL, &vai );
8041f0d814045aba94e01e62e04e968ca8b970b3d44cerion   cls = vai.ppc_cache_line_szB;
80510f08cf5b84882eebbb6712a7be890577650e8adsewardj
8062bf6ba55b04ea9a58098f041c5ee149539c0f081sewardj   /* Stay sane .. */
80789230cace4f5acad8037e4cb4b3e49e83d3a275bsewardj   vg_assert(cls == 32 || cls == 64 || cls == 128);
80885665ca6fa29dd64754dabe50eb98f25896e752acerion
80985665ca6fa29dd64754dabe50eb98f25896e752acerion   startaddr &= ~(cls - 1);
81085665ca6fa29dd64754dabe50eb98f25896e752acerion   for (addr = startaddr; addr < endaddr; addr += cls)
81185665ca6fa29dd64754dabe50eb98f25896e752acerion      asm volatile("dcbst 0,%0" : : "r" (addr));
81285665ca6fa29dd64754dabe50eb98f25896e752acerion   asm volatile("sync");
81385665ca6fa29dd64754dabe50eb98f25896e752acerion   for (addr = startaddr; addr < endaddr; addr += cls)
81485665ca6fa29dd64754dabe50eb98f25896e752acerion      asm volatile("icbi 0,%0" : : "r" (addr));
81585665ca6fa29dd64754dabe50eb98f25896e752acerion   asm volatile("sync; isync");
81610f08cf5b84882eebbb6712a7be890577650e8adsewardj
81710f08cf5b84882eebbb6712a7be890577650e8adsewardj#  elif defined(VGA_x86)
81810f08cf5b84882eebbb6712a7be890577650e8adsewardj   /* no need to do anything, hardware provides coherence */
81910f08cf5b84882eebbb6712a7be890577650e8adsewardj
82010f08cf5b84882eebbb6712a7be890577650e8adsewardj#  elif defined(VGA_amd64)
82110f08cf5b84882eebbb6712a7be890577650e8adsewardj   /* no need to do anything, hardware provides coherence */
82210f08cf5b84882eebbb6712a7be890577650e8adsewardj
82310f08cf5b84882eebbb6712a7be890577650e8adsewardj#  else
82410f08cf5b84882eebbb6712a7be890577650e8adsewardj#    error "Unknown ARCH"
82510f08cf5b84882eebbb6712a7be890577650e8adsewardj#  endif
82685665ca6fa29dd64754dabe50eb98f25896e752acerion}
82785665ca6fa29dd64754dabe50eb98f25896e752acerion
828de4a1d01951937632098a6cda45859afa587a06fsewardj
829fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC.  The translation is temporarily
830fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   in code[0 .. code_len-1].
831de4a1d01951937632098a6cda45859afa587a06fsewardj
832fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   pre: youngest_sector points to a valid (although possibly full)
833fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.
834fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
8358bddf58af8cc7342d4bde6712c5a6a33bf2850d4njnvoid VG_(add_to_transtab)( VexGuestExtents* vge,
8368bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn                           Addr64           entry,
8378bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn                           AddrH            code,
83826412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                           UInt             code_len,
83926412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                           Bool             is_self_checking )
84022854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{
841fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int    tcAvailQ, reqdQ, y, i;
8425f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   ULong  *tcptr, *tcptr2;
843fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* srcP;
844fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* dstP;
845fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
846663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
847fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
848e808930793aeddc4cfd3e7a94b665913bec2566csewardj
849e808930793aeddc4cfd3e7a94b665913bec2566csewardj   /* 60000: should agree with N_TMPBUF in m_translate.c. */
850e808930793aeddc4cfd3e7a94b665913bec2566csewardj   vg_assert(code_len > 0 && code_len < 60000);
851fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
852fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (0)
8538bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn      VG_(printf)("add_to_transtab(entry = 0x%llx, len = %d)\n",
854fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                  entry, code_len);
855fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
856fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_count++;
857fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_tsize += code_len;
858fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_osize += vge_osize(vge);
85926412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   if (is_self_checking)
86026412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj      n_in_sc_count++;
861fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
862fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   y = youngest_sector;
863fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(y));
864fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
865fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sectors[y].tc == NULL)
866fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
867fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
868fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Try putting the translation in this sector. */
8695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   reqdQ = (code_len + 7) >> 3;
870fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
871fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Will it fit in tc? */
872fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
873fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
874fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
875fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
876fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
877fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (tcAvailQ < reqdQ
878fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj       || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR_USABLE) {
879fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* No.  So move on to the next sector.  Either it's never been
880fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         used before, in which case it will get its tt/tc allocated
881fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         now, or it has been used before, in which case it is set to be
882fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         empty, hence throwing out the oldest sector. */
883a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj      vg_assert(tc_sector_szQ > 0);
884a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj      VG_(debugLog)(1,"transtab",
885a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      "declare sector %d full "
886a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      "(TT loading %2d%%, TC loading %2d%%)\n",
887a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      y,
888a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      (100 * sectors[y].tt_n_inuse)
889a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                         / N_TTES_PER_SECTOR,
890a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      (100 * (tc_sector_szQ - tcAvailQ))
891a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                         / tc_sector_szQ);
892fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      youngest_sector++;
893fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (youngest_sector >= N_SECTORS)
894fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         youngest_sector = 0;
895fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      y = youngest_sector;
896fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
897fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
89822854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
899fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Be sure ... */
900fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
901fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
902fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
903fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
904fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= reqdQ);
905fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR_USABLE);
906fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse >= 0);
907fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
908fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Copy into tc. */
9095f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tcptr = sectors[y].tc_next;
9105f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr >= &sectors[y].tc[0]);
9115f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr <= &sectors[y].tc[tc_sector_szQ]);
912fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
9135f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   dstP = (UChar*)tcptr;
914fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   srcP = (UChar*)code;
915fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < code_len; i++)
916fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      dstP[i] = srcP[i];
917fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tc_next += reqdQ;
918fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt_n_inuse++;
919fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
92085665ca6fa29dd64754dabe50eb98f25896e752acerion   invalidate_icache( dstP, code_len );
92185665ca6fa29dd64754dabe50eb98f25896e752acerion
922fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* more paranoia */
9235f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tcptr2 = sectors[y].tc_next;
9245f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 >= &sectors[y].tc[0]);
9255f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 <= &sectors[y].tc[tc_sector_szQ]);
926fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
927fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find an empty tt slot, and use it.  There must be such a slot
928fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      since tt is never allowed to get completely full. */
929fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   i = HASH_TT(entry);
930fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(i >= 0 && i < N_TTES_PER_SECTOR);
93122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj   while (True) {
932fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[y].tt[i].status == Empty
933fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          || sectors[y].tt[i].status == Deleted)
934fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         break;
935fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      i++;
936fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (i >= N_TTES_PER_SECTOR)
937fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         i = 0;
93822854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj   }
939fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
940fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].status = InUse;
9415f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   sectors[y].tt[i].tcptr  = tcptr;
942fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].count  = 0;
943fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].weight = 1;
944fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].vge    = *vge;
945fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].entry  = entry;
946fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
9476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Update the fast-cache. */
9485f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   setFastCacheEntry( entry, tcptr, &sectors[y].tt[i].count );
9496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Note the eclass numbers for this translation. */
9516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   upd_eclasses_after_add( &sectors[y], i );
95222854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj}
95322854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
954fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
955fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address.  If
956fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   requested, a successful search can also cause the fast-caches to be
957fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   updated.
958fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
959fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjBool VG_(search_transtab) ( /*OUT*/AddrH* result,
960fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                            Addr64        guest_addr,
961fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                            Bool          upd_cache )
9626c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
963fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int i, j, k, kstart, sno;
964663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
965663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
966fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find the initial probe point just once.  It will be the same in
967fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      all sectors and avoids multiple expensive % operations. */
968fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_full_lookups++;
969fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   k      = -1;
970fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   kstart = HASH_TT(guest_addr);
971fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(kstart >= 0 && kstart < N_TTES_PER_SECTOR);
972fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
973fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Search in all the sectors.  Although the order should not matter,
974fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      it might be most efficient to search in the order youngest to
975fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      oldest. */
976fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sno = youngest_sector;
977fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < N_SECTORS; i++) {
978fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
979fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[sno].tc == NULL)
980fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         goto notfound; /* sector not in use. */
981fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
982fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      k = kstart;
983fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (j = 0; j < N_TTES_PER_SECTOR; j++) {
984fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         n_lookup_probes++;
985fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[k].status == InUse
986fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             && sectors[sno].tt[k].entry == guest_addr) {
987fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            /* found it */
988fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (upd_cache)
989fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               setFastCacheEntry(
9905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj                  guest_addr, sectors[sno].tt[k].tcptr,
991fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                              &sectors[sno].tt[k].count );
992fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (result)
9935f76de086a6d643db51e50a4e623df7dfc9b6161sewardj               *result = (AddrH)sectors[sno].tt[k].tcptr;
994fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            return True;
995fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
996fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[k].status == Empty)
997fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            break; /* not found in this sector */
998fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         k++;
999fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (k == N_TTES_PER_SECTOR)
1000fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            k = 0;
10016c3769f487145a08c01b58d6e5db3ba274062ad4sewardj      }
1002fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1003fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* If we fall off the end, all entries are InUse and not
1004fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         matching, or Deleted.  In any case we did not find it in this
1005fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         sector. */
1006fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1007fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj     notfound:
1008fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* move to the next oldest sector */
1009fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sno = sno==0 ? (N_SECTORS-1) : (sno-1);
10106c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
1011fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1012fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Not found in any sector. */
1013fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
10146c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1015de4a1d01951937632098a6cda45859afa587a06fsewardj
1016de4a1d01951937632098a6cda45859afa587a06fsewardj
10176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
10186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Delete translations.                                  ---*/
10196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
10206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* forward */
10220ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void unredir_discard_translations( Addr64, ULong );
10230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
10246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Stuff for deleting translations which intersect with a given
10256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   address range.  Unfortunately, to make this run at a reasonable
10266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   speed, it is complex. */
1027fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1028fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
1029a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlap1 ( Addr64 s1, ULong r1, Addr64 s2, ULong r2 )
10306c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1031a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj   Addr64 e1 = s1 + r1 - 1ULL;
1032a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj   Addr64 e2 = s2 + r2 - 1ULL;
1033fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (e1 < s2 || e2 < s1)
1034fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1035fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
10366c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1037de4a1d01951937632098a6cda45859afa587a06fsewardj
1038fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
1039a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlaps ( Addr64 start, ULong range, VexGuestExtents* vge )
10406c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1041fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[0], (UInt)vge->len[0]))
1042fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1043fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 2)
1044fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1045fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[1], (UInt)vge->len[1]))
1046fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1047fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 3)
1048fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1049fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[2], (UInt)vge->len[2]))
1050fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1051fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
10526c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1053de4a1d01951937632098a6cda45859afa587a06fsewardj
1054de4a1d01951937632098a6cda45859afa587a06fsewardj
10556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete a tt entry, and update all the eclass data accordingly. */
10566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic void delete_tte ( /*MOD*/Sector* sec, Int tteno )
10586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
10596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i, ec_num, ec_idx;
10606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
10616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR);
10636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte = &sec->tt[tteno];
10646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tte->status == InUse);
10656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tte->n_tte2ec >= 1 && tte->n_tte2ec <= 3);
10666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Deal with the ec-to-tte links first. */
10686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < tte->n_tte2ec; i++) {
10696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec_num = (Int)tte->tte2ec_ec[i];
10706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec_idx = tte->tte2ec_ix[i];
10716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_num >= 0 && ec_num < ECLASS_N);
10726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_idx >= 0);
10736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_idx < sec->ec2tte_used[ec_num]);
10746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Assert that the two links point at each other. */
10756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->ec2tte[ec_num][ec_idx] == (UShort)tteno);
10766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* "delete" the pointer back to here. */
10776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte[ec_num][ec_idx] = EC2TTE_DELETED;
10786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Now fix up this TTEntry. */
10816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->status   = Deleted;
10826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->n_tte2ec = 0;
10836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Stats .. */
10856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tt_n_inuse--;
10866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_disc_count++;
10876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_disc_osize += vge_osize(&tte->vge);
10886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Tell the tool too. */
10900b9d74abd0a663b530d290b2b788ddeda46e5400sewardj   if (VG_(needs).superblock_discards) {
10910b9d74abd0a663b530d290b2b788ddeda46e5400sewardj      VG_TDICT_CALL( tool_discard_superblock_info,
10924ba057cce1d81a949f5a899b5abb99e90a731bccsewardj                     tte->entry,
10936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                     tte->vge );
10946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
10966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, but
10996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   only consider translations in the specified eclass. */
11006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
11026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjBool delete_translations_in_sector_eclass ( /*MOD*/Sector* sec,
11036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                            Addr64 guest_start, ULong range,
11046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                            Int ec )
11056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
11066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i;
11076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort   tteno;
11086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool     anyDeld = False;
11096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
11106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(ec >= 0 && ec < ECLASS_N);
11126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < sec->ec2tte_used[ec]; i++) {
11146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tteno = sec->ec2tte[ec][i];
11166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tteno == EC2TTE_DELETED) {
11176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         /* already deleted */
11186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
11196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tteno < N_TTES_PER_SECTOR);
11226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte = &sec->tt[tteno];
11246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tte->status == InUse);
11256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (overlaps( guest_start, range, &tte->vge )) {
11276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeld = True;
11286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         delete_tte( sec, (Int)tteno );
11296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return anyDeld;
11346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
11356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, the
11386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   slow way, by inspecting all translations in sec. */
11396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
11416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjBool delete_translations_in_sector ( /*MOD*/Sector* sec,
11426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                     Addr64 guest_start, ULong range )
11436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
11446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int  i;
11456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool anyDeld = False;
11466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < N_TTES_PER_SECTOR; i++) {
11486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->tt[i].status == InUse
11496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj          && overlaps( guest_start, range, &sec->tt[i].vge )) {
11506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeld = True;
11516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         delete_tte( sec, i );
11526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return anyDeld;
11566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
11576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
115945f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid VG_(discard_translations) ( Addr64 guest_start, ULong range,
116045f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                 HChar* who )
11616c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
11626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
11636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int     sno, ec;
11646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool    anyDeleted = False;
11656c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1166663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1167663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
1168a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj   VG_(debugLog)(2, "transtab",
116945f4e7c91119c7d01a59f5e827c67841632c9314sewardj                    "discard_translations(0x%llx, %lld) req by %s\n",
117045f4e7c91119c7d01a59f5e827c67841632c9314sewardj                    guest_start, range, who );
117145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
11726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Pre-deletion sanity check */
11736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (VG_(clo_sanity_level >= 4)) {
11746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Bool sane = sanity_check_all_sectors();
11756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sane);
11766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (range == 0)
11796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return;
11806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* There are two different ways to do this.
11826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      If the range fits within a single address-range equivalence
11846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class, as will be the case for a cache line sized invalidation,
11856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      then we only have to inspect the set of translations listed in
11866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      that equivalence class, and also in the "sin-bin" equivalence
11876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class ECLASS_MISC.
11886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Otherwise, the invalidation is of a larger range and probably
11906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      results from munmap.  In this case it's (probably!) faster just
11916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      to inspect all translations, dump those we don't want, and
11926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      regenerate the equivalence class information (since modifying it
11936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      in-situ is even more expensive).
11946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   */
11956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* First off, figure out if the range falls within a single class,
11976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      and if so which one. */
11986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   ec = ECLASS_MISC;
12006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (range < (1ULL << ECLASS_SHIFT))
12016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec = range_to_eclass( guest_start, (UInt)range );
12026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* if ec is ECLASS_MISC then we aren't looking at just a single
12046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class, so use the slow scheme.  Else use the fast scheme,
12056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      examining 'ec' and ECLASS_MISC. */
12066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (ec != ECLASS_MISC) {
12086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(2, "transtab",
12106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                       "                    FAST, ec = %d\n", ec);
12116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Fast scheme */
12136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec >= 0 && ec < ECLASS_MISC);
12146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (sno = 0; sno < N_SECTORS; sno++) {
12166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
12176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
12186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
12196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector_eclass(
12206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                         sec, guest_start, range, ec );
12216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector_eclass(
12226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                         sec, guest_start, range, ECLASS_MISC );
12236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
12246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   } else {
12266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* slow scheme */
12286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(2, "transtab",
12306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                       "                    SLOW, ec = %d\n", ec);
12316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (sno = 0; sno < N_SECTORS; sno++) {
12336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
12346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
12356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
12366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector(
12376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                         sec, guest_start, range );
12386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
12396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1240de4a1d01951937632098a6cda45859afa587a06fsewardj   }
1241de4a1d01951937632098a6cda45859afa587a06fsewardj
1242fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (anyDeleted)
1243fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      invalidateFastCache();
12446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* don't forget the no-redir cache */
12460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_discard_translations( guest_start, range );
12470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
12486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Post-deletion sanity check */
12496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (VG_(clo_sanity_level >= 4)) {
12506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int      i;
12516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      TTEntry* tte;
12526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Bool     sane = sanity_check_all_sectors();
12536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sane);
12546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* But now, also check the requested address range isn't
12556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         present anywhere. */
12566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (sno = 0; sno < N_SECTORS; sno++) {
12576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
12586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
12596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
12606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         for (i = 0; i < N_TTES_PER_SECTOR; i++) {
12616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            tte = &sec->tt[i];
12626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (tte->status != InUse)
12636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               continue;
12646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(!overlaps( guest_start, range, &tte->vge ));
12656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
12666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
12676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
1268fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
12696c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
12706c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1271fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
12720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*--- AUXILIARY: the unredirected TT/TC                    ---*/
12730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/
12740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
12750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* A very simple translation cache which holds a small number of
12760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredirected translations.  This is completely independent of the
12770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   main tt/tc structures.  When unredir_tc or unredir_tt becomes full,
12780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   both structures are simply dumped and we start over.
12790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
12800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Since these translations are unredirected, the search key is (by
12810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   definition) the first address entry in the .vge field. */
12820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
12830ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Sized to hold 500 translations of average size 1000 bytes. */
12840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
12850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define UNREDIR_SZB   1000
12860ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
12870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TT  500
12880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TCQ (N_UNREDIR_TT * UNREDIR_SZB / sizeof(ULong))
12890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
12900ec07f32bbbb209d749b9974408e6f025ad40b31sewardjtypedef
12910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   struct {
12920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      VexGuestExtents vge;
12930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      Addr            hcode;
12940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      Bool            inUse;
12950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
12960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   UTCEntry;
12970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
12980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* We just allocate forwards in _tc, never deleting. */
129978c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic ULong    *unredir_tc;
130078c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic Int      unredir_tc_used = N_UNREDIR_TCQ;
13010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Slots in _tt can come into use and out again (.inUse).
13030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Nevertheless _tt_highwater is maintained so that invalidations
13040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   don't have to scan all the slots when only a few are in use.
13050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   _tt_highwater holds the index of the highest ever allocated
13060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   slot. */
13070ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic UTCEntry unredir_tt[N_UNREDIR_TT];
13080ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Int      unredir_tt_highwater;
13090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13110ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void init_unredir_tt_tc ( void )
13120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
13130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
131478c0c09d429c95115e826ef769ecaa6cff2ac338tom   if (unredir_tc == NULL) {
131578c0c09d429c95115e826ef769ecaa6cff2ac338tom      SysRes sres = VG_(am_mmap_anon_float_valgrind)( N_UNREDIR_TT * UNREDIR_SZB );
131678c0c09d429c95115e826ef769ecaa6cff2ac338tom      if (sres.isError) {
131778c0c09d429c95115e826ef769ecaa6cff2ac338tom         VG_(out_of_memory_NORETURN)("init_unredir_tt_tc", N_UNREDIR_TT * UNREDIR_SZB);
131878c0c09d429c95115e826ef769ecaa6cff2ac338tom         /*NOTREACHED*/
131978c0c09d429c95115e826ef769ecaa6cff2ac338tom      }
1320e808930793aeddc4cfd3e7a94b665913bec2566csewardj      unredir_tc = (ULong *)sres.res;
132178c0c09d429c95115e826ef769ecaa6cff2ac338tom   }
13220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tc_used = 0;
13230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++)
13240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      unredir_tt[i].inUse = False;
13250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt_highwater = -1;
13260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
13270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Do a sanity check; return False on failure. */
13290ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void )
13300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
13310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
13320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tt_highwater < -1) return False;
13330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tt_highwater >= N_UNREDIR_TT) return False;
13340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = unredir_tt_highwater+1; i < N_UNREDIR_TT; i++)
13360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].inUse)
13370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         return False;
13380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tc_used < 0) return False;
13400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tc_used > N_UNREDIR_TCQ) return False;
13410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   return True;
13430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
13440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Add an UNREDIRECTED translation of vge to TT/TC.  The translation
13470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   is temporarily in code[0 .. code_len-1].
13480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj*/
13490ec07f32bbbb209d749b9974408e6f025ad40b31sewardjvoid VG_(add_to_unredir_transtab)( VexGuestExtents* vge,
13500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                   Addr64           entry,
13510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                   AddrH            code,
13520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                   UInt             code_len,
13530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                   Bool             is_self_checking )
13540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
13550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int   i, j, code_szQ;
13560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   HChar *srcP, *dstP;
13570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(sanity_check_redir_tt_tc());
13590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* This is the whole point: it's not redirected! */
13610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(entry == vge->base[0]);
13620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* How many unredir_tt slots are needed */
13640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   code_szQ = (code_len + 7) / 8;
13650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* Look for an empty unredir_tc slot */
13670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++)
13680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (!unredir_tt[i].inUse)
13690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         break;
13700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (i >= N_UNREDIR_TT || code_szQ > (N_UNREDIR_TCQ - unredir_tc_used)) {
13720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      /* It's full; dump everything we currently have */
13730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      init_unredir_tt_tc();
13740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      i = 0;
13750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
13760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used >= 0);
13780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used <= N_UNREDIR_TCQ);
13790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(code_szQ > 0);
13800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(code_szQ + unredir_tc_used <= N_UNREDIR_TCQ);
13810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(i >= 0 && i < N_UNREDIR_TT);
13820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tt[i].inUse == False);
13830ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (i > unredir_tt_highwater)
13850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      unredir_tt_highwater = i;
13860ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   dstP = (HChar*)&unredir_tc[unredir_tc_used];
13880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   srcP = (HChar*)code;
13890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (j = 0; j < code_len; j++)
13900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      dstP[j] = srcP[j];
13910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
1392c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj   invalidate_icache( dstP, code_len );
1393c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj
13940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].inUse = True;
13950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].vge   = *vge;
13960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].hcode = (Addr)dstP;
13970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
13980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tc_used += code_szQ;
13990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used >= 0);
14000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used <= N_UNREDIR_TCQ);
14010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
14020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(&dstP[code_len] <= (HChar*)&unredir_tc[unredir_tc_used]);
14030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
14040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
14050ec07f32bbbb209d749b9974408e6f025ad40b31sewardjBool VG_(search_unredir_transtab) ( /*OUT*/AddrH* result,
14060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                    Addr64        guest_addr )
14070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
14080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
14090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++) {
14100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (!unredir_tt[i].inUse)
14110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         continue;
14120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].vge.base[0] == guest_addr) {
14130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         *result = (AddrH)unredir_tt[i].hcode;
14140ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         return True;
14150ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      }
14160ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
14170ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   return False;
14180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
14190ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
14200ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void unredir_discard_translations( Addr64 guest_start, ULong range )
14210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
14220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
14230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
14240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(sanity_check_redir_tt_tc());
14250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
14260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i <= unredir_tt_highwater; i++) {
14270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].inUse
14280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj          && overlaps( guest_start, range, &unredir_tt[i].vge))
14290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         unredir_tt[i].inUse = False;
14300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
14310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
14320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
14330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
14340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/
1435fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation.                                      ---*/
1436fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
1437fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1438fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void )
14396c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
14406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, j, avg_codeszQ;
1441de4a1d01951937632098a6cda45859afa587a06fsewardj
1442663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(!init_done);
1443663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   init_done = True;
1444663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
1445fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Otherwise lots of things go wrong... */
1446fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sizeof(ULong) == 8);
1447fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sizeof(Addr64) == 8);
14485f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache entries really are 2 words long */
14495f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof(Addr) == sizeof(void*));
14505f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof(FastCacheEntry) == 2 * sizeof(Addr));
14515f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache entries are packed back-to-back with no spaces */
14525f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof( VG_(tt_fast) ) == VG_TT_FAST_SIZE * sizeof(FastCacheEntry));
14535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache is aligned as we requested.  Not fatal if it
14545f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      isn't, but we might as well make sure. */
14555f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_IS_16_ALIGNED( ((Addr) & VG_(tt_fast)[0]) ));
1456de4a1d01951937632098a6cda45859afa587a06fsewardj
1457fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (VG_(clo_verbosity) > 2)
1458fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
1459fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                   "TT/TC: VG_(init_tt_tc) "
1460fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                   "(startup of code management)");
1461fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1462fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Figure out how big each tc area should be.  */
146343b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   avg_codeszQ   = (VG_(details).avg_translation_sizeB + 7) / 8;
146443b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   tc_sector_szQ = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ);
1465fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1466fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Ensure the calculated value is not way crazy. */
1467fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR_USABLE);
1468e808930793aeddc4cfd3e7a94b665913bec2566csewardj   vg_assert(tc_sector_szQ <= 80 * N_TTES_PER_SECTOR_USABLE);
1469fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1470fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Initialise the sectors */
1471fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest_sector = 0;
1472fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < N_SECTORS; i++) {
1473fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tc = NULL;
1474fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tt = NULL;
1475fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tc_next = NULL;
1476fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tt_n_inuse = 0;
14776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < ECLASS_N; j++) {
14786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sectors[i].ec2tte_size[j] = 0;
14796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sectors[i].ec2tte_used[j] = 0;
14806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sectors[i].ec2tte[j] = NULL;
14816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
14826c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
14834ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
14845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* Initialise the fast caches.  If not profiling (the usual case),
14855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      we have to explicitly invalidate the fastN cache as
14865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      invalidateFastCache() won't do that for us. */
1487fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
14885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if (VG_(clo_profile_flags) == 0)
14895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      invalidateFastNCache();
1490fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
14910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* and the unredir tt/tc */
14920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   init_unredir_tt_tc();
14930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
1494fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (VG_(clo_verbosity) > 2) {
1495fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
1496fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         "TT/TC: cache: %d sectors of %d bytes each = %d total",
1497fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          N_SECTORS, 8 * tc_sector_szQ,
1498fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          N_SECTORS * 8 * tc_sector_szQ );
1499fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
1500fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         "TT/TC: table: %d total entries, max occupancy %d (%d%%)",
1501fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         N_SECTORS * N_TTES_PER_SECTOR,
1502fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         N_SECTORS * N_TTES_PER_SECTOR_USABLE,
1503fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         SECTOR_TT_LIMIT_PERCENT );
1504fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
150545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
150645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "transtab",
150745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      "cache: %d sectors of %d bytes each = %d total\n",
150845f4e7c91119c7d01a59f5e827c67841632c9314sewardj       N_SECTORS, 8 * tc_sector_szQ,
150945f4e7c91119c7d01a59f5e827c67841632c9314sewardj       N_SECTORS * 8 * tc_sector_szQ );
151045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "transtab",
151145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      "table: %d total entries, max occupancy %d (%d%%)\n",
151245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      N_SECTORS * N_TTES_PER_SECTOR,
151345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      N_SECTORS * N_TTES_PER_SECTOR_USABLE,
151445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      SECTOR_TT_LIMIT_PERCENT );
1515de4a1d01951937632098a6cda45859afa587a06fsewardj}
1516de4a1d01951937632098a6cda45859afa587a06fsewardj
15174ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
1518fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
1519fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics.                             ---*/
1520fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
1521fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1522fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong safe_idiv( ULong a, ULong b )
152392e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
152492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   return (b == 0 ? 0 : a / b);
152592e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
152692e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote
1527fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void )
1528fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
1529fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n_in_count;
1530fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
1531fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1532fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void )
153392e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
153492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
1535a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      "    tt/tc: %'llu tt lookups requiring %'llu probes",
1536fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_full_lookups, n_lookup_probes );
153792e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
1538a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      "    tt/tc: %'llu fast-cache updates, %'llu flushes",
1539fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_fast_updates, n_fast_flushes );
1540fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
154192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
1542a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                " transtab: new        %'lld "
1543a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                "(%'llu -> %'llu; ratio %'llu:10) [%'llu scs]",
1544fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_in_count, n_in_osize, n_in_tsize,
154526412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                safe_idiv(10*n_in_tsize, n_in_osize),
154626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                n_in_sc_count);
154792e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
1548a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                " transtab: dumped     %'llu (%'llu -> ?" "?)",
1549fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_dump_count, n_dump_osize );
1550fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   VG_(message)(Vg_DebugMsg,
1551a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                " transtab: discarded  %'llu (%'llu -> ?" "?)",
1552fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_disc_count, n_disc_osize );
15536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
15546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (0) {
15556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int i;
15566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(printf)("\n");
15576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
15586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         VG_(printf)(" %4d", sectors[0].ec2tte_used[i]);
15596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (i % 16 == 15)
15606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            VG_(printf)("\n");
15616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
15626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(printf)("\n\n");
15636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
156492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
1565de4a1d01951937632098a6cda45859afa587a06fsewardj
1566fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
1567fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results.                   ---*/
1568fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
15694ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
1570fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong score ( TTEntry* tte )
1571fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
1572fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return ((ULong)tte->weight) * ((ULong)tte->count);
1573de4a1d01951937632098a6cda45859afa587a06fsewardj}
1574de4a1d01951937632098a6cda45859afa587a06fsewardj
15752025cf98a3210c175a90fc77cb599cca1643bd68njnULong VG_(get_BB_profile) ( BBProfEntry tops[], UInt n_tops )
1576de4a1d01951937632098a6cda45859afa587a06fsewardj{
1577fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int   sno, i, r, s;
15782025cf98a3210c175a90fc77cb599cca1643bd68njn   ULong score_total;
1579fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1580fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* First, compute the total weighted count, and find the top N
15812025cf98a3210c175a90fc77cb599cca1643bd68njn      ttes.  tops contains pointers to the most-used n_tops blocks, in
1582fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      descending order (viz, tops[0] is the highest scorer). */
15832025cf98a3210c175a90fc77cb599cca1643bd68njn   for (i = 0; i < n_tops; i++) {
15842025cf98a3210c175a90fc77cb599cca1643bd68njn      tops[i].addr  = 0;
15852025cf98a3210c175a90fc77cb599cca1643bd68njn      tops[i].score = 0;
15862025cf98a3210c175a90fc77cb599cca1643bd68njn   }
1587fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1588fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   score_total = 0;
1589fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1590fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (sno = 0; sno < N_SECTORS; sno++) {
1591fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[sno].tc == NULL)
159218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         continue;
1593fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
1594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[i].status != InUse)
1595fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            continue;
1596fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         score_total += score(&sectors[sno].tt[i]);
1597fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* Find the rank for sectors[sno].tt[i]. */
15982025cf98a3210c175a90fc77cb599cca1643bd68njn         r = n_tops-1;
1599fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         while (True) {
1600fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (r == -1)
1601fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               break;
16022025cf98a3210c175a90fc77cb599cca1643bd68njn             if (tops[r].addr == 0) {
1603fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               r--;
1604fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               continue;
1605fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
16062025cf98a3210c175a90fc77cb599cca1643bd68njn             if ( score(&sectors[sno].tt[i]) > tops[r].score ) {
1607fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                r--;
1608fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                continue;
1609fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
1610fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             break;
1611fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
1612fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         r++;
16132025cf98a3210c175a90fc77cb599cca1643bd68njn         vg_assert(r >= 0 && r <= n_tops);
1614fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* This bb should be placed at r, and bbs above it shifted
1615fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            upwards one slot. */
16162025cf98a3210c175a90fc77cb599cca1643bd68njn         if (r < n_tops) {
16172025cf98a3210c175a90fc77cb599cca1643bd68njn            for (s = n_tops-1; s > r; s--)
1618fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               tops[s] = tops[s-1];
16192025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].addr  = sectors[sno].tt[i].entry;
16202025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].score = score( &sectors[sno].tt[i] );
1621fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
1622de4a1d01951937632098a6cda45859afa587a06fsewardj      }
1623de4a1d01951937632098a6cda45859afa587a06fsewardj   }
1624de4a1d01951937632098a6cda45859afa587a06fsewardj
16252025cf98a3210c175a90fc77cb599cca1643bd68njn   return score_total;
1626c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
1627c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
1628de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
16298bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end                                                          ---*/
1630de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
1631