m_transtab.c revision 3786772222c5b31fd6cc5586bcd1ce0da58f1dbe
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
11fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Copyright (C) 2000-2005 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"
3410f08cf5b84882eebbb6712a7be890577650e8adsewardj#include "pub_core_machine.h"    // ppc32: VG_(cache_line_size_ppc32)
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
58fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   number to work properly, and it is strongly recommended not to
59fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   change this. */
6034483bcaeda3136ec238bcfd7f9e691cf8a6d0dcsewardj#define N_TTES_PER_SECTOR /*30011*/ /*40009*/ 80021
61de4a1d01951937632098a6cda45859afa587a06fsewardj
62fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to
63fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   specify the maximum allowable loading, after which the sector is
64fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   deemed full. */
6534483bcaeda3136ec238bcfd7f9e691cf8a6d0dcsewardj#define SECTOR_TT_LIMIT_PERCENT 66
66de4a1d01951937632098a6cda45859afa587a06fsewardj
67fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */
68fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_TTES_PER_SECTOR_USABLE \
69fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj           ((N_TTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100)
706c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
71de4a1d01951937632098a6cda45859afa587a06fsewardj
726c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/
73de4a1d01951937632098a6cda45859afa587a06fsewardj
74fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-cache entry is two parts:
75fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   - The guest address of the first (entry) bb in the translation,
76fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj     as a 64-bit word.
77fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   - One or more 64-bit words containing the code.
78fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   It is supposed to be 64-bit aligned.
79fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
80fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*
816c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef
82fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   struct {
83fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Addr64 orig_addr;
84fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong  code[0];
856c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
866c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   TCEntry;
87fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
886c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
89fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry.  This indicates precisely which areas of
90fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   guest code are included in the translation, and contains all other
91fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   auxiliary info too.  */
926c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef
936c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   struct {
94fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Profiling only: the count and weight (arbitrary meaning) for
95fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         this translation.  Weight is a property of the translation
96fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         itself and computed once when the translation is created.
97fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         Count is an entry count for the translation and is
98fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         incremented by 1 every time the translation is used, if we
99fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         are profiling. */
100fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      UInt     count;
101fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      UShort   weight;
102fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
103fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Status of the slot.  Note, we need to be able to do lazy
104fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         deletion, hence the Deleted state. */
105fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      enum { InUse, Deleted, Empty } status;
106fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
107fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Pointer to the corresponding TCEntry (must be in the same
108fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         sector!) */
109fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tce;
110fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
111fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This is the original guest address that purportedly is the
112fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         entry point of the translation.  You might think that .entry
113fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         should be the same as .vge->base[0], and most of the time it
114fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         is.  However, when doing redirections, that is not the case.
115fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         .vge must always correctly describe the guest code sections
116fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         from which this translation was made.  However, .entry may or
117fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         may not be a lie, depending on whether or not we're doing
118fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         redirection. */
119fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Addr64 entry;
120fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
121fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This structure describes precisely what ranges of guest code
122fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         the translation covers, so we can decide whether or not to
123fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         delete it when translations of a given address range are
124fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         invalidated. */
125fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VexGuestExtents vge;
1266c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
1276c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   TTEntry;
1286c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1294ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
130fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself.  Each sector contains an array of
131fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   TCEntries, which hold code, and an array of TTEntries, containing
132fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   all required administrative info.  Profiling is supported using the
133fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   TTEntry .count and .weight fields, if required.  Each sector is
134fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   independent in that no cross-sector references are allowed.
1354ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
136fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   If the sector is not in use, all three pointers are NULL and
137fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tt_n_inuse is zero.
138fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
139fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef
140fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   struct {
141fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TCEntry area.  Size of this depends on the average
142fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         translation size.  We try and size it so it becomes full
143fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         precisely when this sector's translation table (tt) reaches
144fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         its load limit (SECTOR_TT_LIMIT_PERCENT). */
145fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc;
1464ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
147fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TTEntry array.  This is a fixed size, always containing
148fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         exactly N_TTES_PER_SECTOR entries. */
149fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      TTEntry* tt;
1506c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
151fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This points to the current allocation point in tc. */
152fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc_next;
153de4a1d01951937632098a6cda45859afa587a06fsewardj
154fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The count of tt entries with state InUse. */
155fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Int tt_n_inuse;
156fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
157fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Sector;
158de4a1d01951937632098a6cda45859afa587a06fsewardj
159de4a1d01951937632098a6cda45859afa587a06fsewardj
1606c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/
1616c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors.  The index of the
163fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest sector is recorded, and new translations are put into that
164fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.  When it fills up, we move along to the next sector and
165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   start to fill that up, wrapping around at the end of the array.
166fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   That way, once all N_TC_SECTORS have been bought into use for the
167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   first time, and are full, we then re-use the oldest sector,
168fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   endlessly.
169fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
170fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   When running, youngest sector should be between >= 0 and <
171fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   N_TC_SECTORS.  The initial -1 value indicates the TT/TC system is
172fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   not yet initialised.
173fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
174fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Sector sectors[N_SECTORS];
175fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int    youngest_sector = -1;
1766c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
177fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area.  This is computed once
178fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   at startup and does not change. */
179fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int    tc_sector_szQ;
1806c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1816c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
182fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Fast helper for the TC.  A direct-mapped cache which holds a
183fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   pointer to a TC entry which may or may not be the correct one, but
184fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   which we hope usually is.  This array is referred to directly from
185fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   <arch>/dispatch.S.
1866c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
187fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Entries in tt_fast may point to any valid TC entry, regardless of
188fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   which sector it's in.  Consequently we must be very careful to
189fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidate this cache when TC entries are changed or disappear.
190c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
191fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   A special TCEntry -- bogus_tc_entry -- must be pointed at to cause
192fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   that cache entry to miss.  This relies on the assumption that no
193fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   guest code actually has an address of 0x1.
194fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
195fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*global*/ ULong* VG_(tt_fast)[VG_TT_FAST_SIZE];
19692e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote
197fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong bogus_tc_entry = (Addr64)1;
19892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote
19992e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote
200fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* For profiling, we have a parallel array of pointers to .count
201fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   fields in TT entries.  Again, these pointers must be invalidated
202fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   when translations disappear.  A NULL pointer suffices to indicate
203fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   an unused slot.
2046c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
205fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tt_fast and tt_fastN change together: if tt_fast[i] points to
206fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   bogus_tc_entry then the corresponding tt_fastN[i] must be null.  If
207fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tt_fast[i] points to some TC entry somewhere, then tt_fastN[i]
208fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   *must* point to the .count field of the corresponding TT entry.
2096c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
210fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tt_fast and tt_fastN are referred to from assembly code
211fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   (dispatch.S).
212fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
213fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*global*/ UInt* VG_(tt_fastN)[VG_TT_FAST_SIZE];
214de4a1d01951937632098a6cda45859afa587a06fsewardj
215de4a1d01951937632098a6cda45859afa587a06fsewardj
216663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */
217663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False;
218663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
219663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
220fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/
221de4a1d01951937632098a6cda45859afa587a06fsewardj
222fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */
223fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_fast_flushes = 0;
224fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_fast_updates = 0;
22522854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
226fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */
227fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_full_lookups = 0;
228fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_lookup_probes = 0;
22922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
23026412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj/* Number/osize/tsize of translations entered; also the number of
23126412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   those for which self-checking was requested. */
23226412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_count    = 0;
23326412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_osize    = 0;
23426412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_tsize    = 0;
23526412bd2c4ef3e55683141f132ebd1eb32d8530bsewardjULong n_in_sc_count = 0;
236de4a1d01951937632098a6cda45859afa587a06fsewardj
237fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */
238fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_dump_count = 0;
239fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_dump_osize = 0;
240fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
241fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */
242fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_disc_count = 0;
243fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjULong n_disc_osize = 0;
244fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
245fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
246fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
247fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
248fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Add/delete/find translations                          ---*/
249fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
250fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
251fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic UInt vge_osize ( VexGuestExtents* vge )
252c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{
253fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt i, n = 0;
254fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < vge->n_used; i++)
255fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n += (UInt)vge->len[i];
256fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n;
257c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
258c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
259fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Bool isValidSector ( Int sector )
2606c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
261fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sector < 0 || sector >= N_SECTORS)
262fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
263fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
2646c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
265de4a1d01951937632098a6cda45859afa587a06fsewardj
266fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline UInt HASH_TT ( Addr64 key )
267de4a1d01951937632098a6cda45859afa587a06fsewardj{
268fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt kHi = (UInt)(key >> 32);
269fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt kLo = (UInt)key;
270fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return (kHi ^ kLo) % N_TTES_PER_SECTOR;
271de4a1d01951937632098a6cda45859afa587a06fsewardj}
272de4a1d01951937632098a6cda45859afa587a06fsewardj
273fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void setFastCacheEntry ( Addr64 key, ULong* tce, UInt* count )
274de4a1d01951937632098a6cda45859afa587a06fsewardj{
275fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt cno = ((UInt)key) & VG_TT_FAST_MASK;
276fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   VG_(tt_fast)[cno]  = tce;
277fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   VG_(tt_fastN)[cno] = count;
278fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_updates++;
2796c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
280de4a1d01951937632098a6cda45859afa587a06fsewardj
281fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void invalidateFastCache ( void )
2826c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
283fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt j;
284fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (j = 0; j < VG_TT_FAST_SIZE; j++) {
285fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(tt_fast)[j]  = &bogus_tc_entry;
286fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(tt_fastN)[j] = NULL;
2876c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
288fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_flushes++;
2896c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
290de4a1d01951937632098a6cda45859afa587a06fsewardj
291fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void initialiseSector ( Int sno )
2926c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
29345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int    i;
29445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes sres;
295fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(sno));
296fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sectors[sno].tc == NULL) {
298fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Sector has never been used before.  Need to allocate tt and
299fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         tc. */
300fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      vg_assert(sectors[sno].tt == NULL);
301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      vg_assert(sectors[sno].tc_next == NULL);
302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      vg_assert(sectors[sno].tt_n_inuse == 0);
30345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
30445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(1,"transtab", "allocate sector %d\n", sno);
30545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
30645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ );
30745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (sres.isError) {
30845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TC)",
30945f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     8 * tc_sector_szQ );
31045f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
31145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
31245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sectors[sno].tc = (ULong*)sres.val;
31345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
31445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)
31545f4e7c91119c7d01a59f5e827c67841632c9314sewardj                ( N_TTES_PER_SECTOR * sizeof(TTEntry) );
31645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (sres.isError) {
31745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TT)",
31845f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     N_TTES_PER_SECTOR * sizeof(TTEntry) );
31945f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
32045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
32145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sectors[sno].tt = (TTEntry*)sres.val;
32245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
323fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
324fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d", sno);
325fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   } else {
326fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Sector has been used before. */
32745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(1,"transtab", "recycle sector %d\n", sno);
328fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      vg_assert(sectors[sno].tt != NULL);
329fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      vg_assert(sectors[sno].tc_next != NULL);
330fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_dump_count += sectors[sno].tt_n_inuse;
331fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
332fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[i].status == InUse) {
333fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            n_dump_osize += vge_osize(&sectors[sno].tt[i].vge);
3343786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            /* Tell the tool too. */
3353786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            if (VG_(needs).basic_block_discards) {
3363786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj               VG_TDICT_CALL( tool_discard_basic_block_info,
3373786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj                              sectors[sno].tt[i].vge );
3383786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            }
339fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
340fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      }
341fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
342fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d", sno);
3436c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
3444ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[sno].tc_next = sectors[sno].tc;
346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[sno].tt_n_inuse = 0;
347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < N_TTES_PER_SECTOR; i++)
348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[sno].tt[i].status = Empty;
349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
350fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
3516c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
352de4a1d01951937632098a6cda45859afa587a06fsewardj
35310f08cf5b84882eebbb6712a7be890577650e8adsewardjstatic void invalidate_icache ( void *ptr, Int nbytes )
35485665ca6fa29dd64754dabe50eb98f25896e752acerion{
35510f08cf5b84882eebbb6712a7be890577650e8adsewardj#  if defined(VGA_ppc32)
35610f08cf5b84882eebbb6712a7be890577650e8adsewardj   Addr startaddr = (Addr) ptr;
35710f08cf5b84882eebbb6712a7be890577650e8adsewardj   Addr endaddr   = startaddr + nbytes;
35810f08cf5b84882eebbb6712a7be890577650e8adsewardj   Addr cls       = VG_(cache_line_size_ppc32);
35910f08cf5b84882eebbb6712a7be890577650e8adsewardj   Addr addr;
36010f08cf5b84882eebbb6712a7be890577650e8adsewardj
3612bf6ba55b04ea9a58098f041c5ee149539c0f081sewardj   /* Stay sane .. */
3622bf6ba55b04ea9a58098f041c5ee149539c0f081sewardj   vg_assert(cls == 32 || cls == 128);
36385665ca6fa29dd64754dabe50eb98f25896e752acerion
36485665ca6fa29dd64754dabe50eb98f25896e752acerion   startaddr &= ~(cls - 1);
36585665ca6fa29dd64754dabe50eb98f25896e752acerion   for (addr = startaddr; addr < endaddr; addr += cls)
36685665ca6fa29dd64754dabe50eb98f25896e752acerion      asm volatile("dcbst 0,%0" : : "r" (addr));
36785665ca6fa29dd64754dabe50eb98f25896e752acerion   asm volatile("sync");
36885665ca6fa29dd64754dabe50eb98f25896e752acerion   for (addr = startaddr; addr < endaddr; addr += cls)
36985665ca6fa29dd64754dabe50eb98f25896e752acerion      asm volatile("icbi 0,%0" : : "r" (addr));
37085665ca6fa29dd64754dabe50eb98f25896e752acerion   asm volatile("sync; isync");
37110f08cf5b84882eebbb6712a7be890577650e8adsewardj
37210f08cf5b84882eebbb6712a7be890577650e8adsewardj#  elif defined(VGA_x86)
37310f08cf5b84882eebbb6712a7be890577650e8adsewardj   /* no need to do anything, hardware provides coherence */
37410f08cf5b84882eebbb6712a7be890577650e8adsewardj
37510f08cf5b84882eebbb6712a7be890577650e8adsewardj#  elif defined(VGA_amd64)
37610f08cf5b84882eebbb6712a7be890577650e8adsewardj   /* no need to do anything, hardware provides coherence */
37710f08cf5b84882eebbb6712a7be890577650e8adsewardj
37810f08cf5b84882eebbb6712a7be890577650e8adsewardj#  else
37910f08cf5b84882eebbb6712a7be890577650e8adsewardj#    error "Unknown ARCH"
38010f08cf5b84882eebbb6712a7be890577650e8adsewardj#  endif
38185665ca6fa29dd64754dabe50eb98f25896e752acerion}
38285665ca6fa29dd64754dabe50eb98f25896e752acerion
383de4a1d01951937632098a6cda45859afa587a06fsewardj
384fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC.  The translation is temporarily
385fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   in code[0 .. code_len-1].
386de4a1d01951937632098a6cda45859afa587a06fsewardj
387fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   pre: youngest_sector points to a valid (although possibly full)
388fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.
389fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
3908bddf58af8cc7342d4bde6712c5a6a33bf2850d4njnvoid VG_(add_to_transtab)( VexGuestExtents* vge,
3918bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn                           Addr64           entry,
3928bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn                           AddrH            code,
39326412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                           UInt             code_len,
39426412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                           Bool             is_self_checking )
39522854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{
396fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int    tcAvailQ, reqdQ, y, i;
397fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   ULong  *tce, *tce2;
398fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* srcP;
399fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* dstP;
400fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
401663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
402fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
403fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(code_len > 0 && code_len < 20000);
404fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
405fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (0)
4068bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn      VG_(printf)("add_to_transtab(entry = 0x%llx, len = %d)\n",
407fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                  entry, code_len);
408fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
409fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_count++;
410fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_tsize += code_len;
411fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_osize += vge_osize(vge);
41226412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   if (is_self_checking)
41326412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj      n_in_sc_count++;
414fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
415fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   y = youngest_sector;
416fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(y));
417fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
418fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sectors[y].tc == NULL)
419fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
420fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
421fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Try putting the translation in this sector. */
422fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   reqdQ = 1 + ((code_len + 7) >> 3);
423fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
424fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Will it fit in tc? */
425fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
426fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
427fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
428fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
429fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
430fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (tcAvailQ < reqdQ
431fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj       || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR_USABLE) {
432fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* No.  So move on to the next sector.  Either it's never been
433fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         used before, in which case it will get its tt/tc allocated
434fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         now, or it has been used before, in which case it is set to be
435fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         empty, hence throwing out the oldest sector. */
436a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj      vg_assert(tc_sector_szQ > 0);
437a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj      VG_(debugLog)(1,"transtab",
438a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      "declare sector %d full "
439a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      "(TT loading %2d%%, TC loading %2d%%)\n",
440a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      y,
441a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      (100 * sectors[y].tt_n_inuse)
442a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                         / N_TTES_PER_SECTOR,
443a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      (100 * (tc_sector_szQ - tcAvailQ))
444a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                         / tc_sector_szQ);
445fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      youngest_sector++;
446fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (youngest_sector >= N_SECTORS)
447fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         youngest_sector = 0;
448fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      y = youngest_sector;
449fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
450fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
45122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
452fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Be sure ... */
453fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
454fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
455fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
456fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
457fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= reqdQ);
458fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR_USABLE);
459fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse >= 0);
460fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
461fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Copy into tc. */
462fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tce = sectors[y].tc_next;
463fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tce >= &sectors[y].tc[0]);
464fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tce <= &sectors[y].tc[tc_sector_szQ]);
465fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
466fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tce[0] = entry;
467fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   dstP = (UChar*)(&tce[1]);
468fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   srcP = (UChar*)code;
469fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < code_len; i++)
470fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      dstP[i] = srcP[i];
471fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tc_next += reqdQ;
472fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt_n_inuse++;
473fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
47485665ca6fa29dd64754dabe50eb98f25896e752acerion   invalidate_icache( dstP, code_len );
47585665ca6fa29dd64754dabe50eb98f25896e752acerion
476fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* more paranoia */
477fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tce2 = sectors[y].tc_next;
478fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tce2 >= &sectors[y].tc[0]);
479fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tce2 <= &sectors[y].tc[tc_sector_szQ]);
480fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
481fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find an empty tt slot, and use it.  There must be such a slot
482fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      since tt is never allowed to get completely full. */
483fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   i = HASH_TT(entry);
484fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(i >= 0 && i < N_TTES_PER_SECTOR);
48522854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj   while (True) {
486fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[y].tt[i].status == Empty
487fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          || sectors[y].tt[i].status == Deleted)
488fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         break;
489fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      i++;
490fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (i >= N_TTES_PER_SECTOR)
491fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         i = 0;
49222854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj   }
493fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
494fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].status = InUse;
495fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].tce    = tce;
496fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].count  = 0;
497fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].weight = 1;
498fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].vge    = *vge;
499fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].entry  = entry;
500fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
501fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   setFastCacheEntry( entry, tce, &sectors[y].tt[i].count );
50222854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj}
50322854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
504fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
505fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address.  If
506fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   requested, a successful search can also cause the fast-caches to be
507fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   updated.
508fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
509fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjBool VG_(search_transtab) ( /*OUT*/AddrH* result,
510fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                            Addr64        guest_addr,
511fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                            Bool          upd_cache )
5126c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
513fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int i, j, k, kstart, sno;
514663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
515663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
516fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find the initial probe point just once.  It will be the same in
517fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      all sectors and avoids multiple expensive % operations. */
518fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_full_lookups++;
519fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   k      = -1;
520fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   kstart = HASH_TT(guest_addr);
521fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(kstart >= 0 && kstart < N_TTES_PER_SECTOR);
522fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
523fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Search in all the sectors.  Although the order should not matter,
524fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      it might be most efficient to search in the order youngest to
525fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      oldest. */
526fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sno = youngest_sector;
527fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < N_SECTORS; i++) {
528fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
529fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[sno].tc == NULL)
530fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         goto notfound; /* sector not in use. */
531fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
532fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      k = kstart;
533fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (j = 0; j < N_TTES_PER_SECTOR; j++) {
534fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         n_lookup_probes++;
535fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[k].status == InUse
536fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             && sectors[sno].tt[k].entry == guest_addr) {
537fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            /* found it */
538fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (upd_cache)
539fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               setFastCacheEntry(
540fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                  guest_addr, sectors[sno].tt[k].tce,
541fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                              &sectors[sno].tt[k].count );
542fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (result)
543fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               *result = sizeof(Addr64) + (AddrH)sectors[sno].tt[k].tce;
544fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            return True;
545fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
546fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[k].status == Empty)
547fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            break; /* not found in this sector */
548fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         k++;
549fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (k == N_TTES_PER_SECTOR)
550fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            k = 0;
5516c3769f487145a08c01b58d6e5db3ba274062ad4sewardj      }
552fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
553fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* If we fall off the end, all entries are InUse and not
554fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         matching, or Deleted.  In any case we did not find it in this
555fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         sector. */
556fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
557fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj     notfound:
558fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* move to the next oldest sector */
559fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sno = sno==0 ? (N_SECTORS-1) : (sno-1);
5606c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
561fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
562fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Not found in any sector. */
563fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
5646c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
565de4a1d01951937632098a6cda45859afa587a06fsewardj
566de4a1d01951937632098a6cda45859afa587a06fsewardj
567fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Delete all translations which intersect with any part of the
568fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   specified guest address range.  Note, this is SLOW.
569fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
570fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
571fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
572a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlap1 ( Addr64 s1, ULong r1, Addr64 s2, ULong r2 )
5736c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
574a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj   Addr64 e1 = s1 + r1 - 1ULL;
575a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj   Addr64 e2 = s2 + r2 - 1ULL;
576fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (e1 < s2 || e2 < s1)
577fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
578fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
5796c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
580de4a1d01951937632098a6cda45859afa587a06fsewardj
581fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
582a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlaps ( Addr64 start, ULong range, VexGuestExtents* vge )
5836c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
584fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[0], (UInt)vge->len[0]))
585fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
586fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 2)
587fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
588fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[1], (UInt)vge->len[1]))
589fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
590fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 3)
591fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
592fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[2], (UInt)vge->len[2]))
593fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
5956c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
596de4a1d01951937632098a6cda45859afa587a06fsewardj
597de4a1d01951937632098a6cda45859afa587a06fsewardj
59845f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid VG_(discard_translations) ( Addr64 guest_start, ULong range,
59945f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                 HChar* who )
6006c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
601fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int sno, i;
602fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Bool anyDeleted = False;
6036c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
604663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
605663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
606a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj   VG_(debugLog)(2, "transtab",
60745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                    "discard_translations(0x%llx, %lld) req by %s\n",
60845f4e7c91119c7d01a59f5e827c67841632c9314sewardj                    guest_start, range, who );
60945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
610fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (sno = 0; sno < N_SECTORS; sno++) {
611fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[sno].tc == NULL)
612fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         continue;
613fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
614fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[i].status == InUse
615fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             && overlaps( guest_start, range, &sectors[sno].tt[i].vge )) {
616fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            sectors[sno].tt[i].status = Deleted;
617fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            sectors[sno].tt_n_inuse--;
6185155dec2ac1d0855fcdc5060503e1d98a281b26asewardj            anyDeleted = True;
619fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            n_disc_count++;
620fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            n_disc_osize += vge_osize(&sectors[sno].tt[i].vge);
6215155dec2ac1d0855fcdc5060503e1d98a281b26asewardj            /* Tell the tool too. */
6225155dec2ac1d0855fcdc5060503e1d98a281b26asewardj            if (VG_(needs).basic_block_discards) {
6235155dec2ac1d0855fcdc5060503e1d98a281b26asewardj               VG_TDICT_CALL( tool_discard_basic_block_info,
6245155dec2ac1d0855fcdc5060503e1d98a281b26asewardj                              sectors[sno].tt[i].vge );
6255155dec2ac1d0855fcdc5060503e1d98a281b26asewardj            }
626fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
627fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      }
628de4a1d01951937632098a6cda45859afa587a06fsewardj   }
629de4a1d01951937632098a6cda45859afa587a06fsewardj
630fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (anyDeleted)
631fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      invalidateFastCache();
632fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
6336c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
6346c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
635fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
636fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation.                                      ---*/
637fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
638fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
639fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void )
6406c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
641fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int i, avg_codeszQ;
642de4a1d01951937632098a6cda45859afa587a06fsewardj
643663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(!init_done);
644663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   init_done = True;
645663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
646fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Otherwise lots of things go wrong... */
647fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sizeof(ULong) == 8);
648fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sizeof(Addr64) == 8);
649de4a1d01951937632098a6cda45859afa587a06fsewardj
650fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (VG_(clo_verbosity) > 2)
651fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
652fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                   "TT/TC: VG_(init_tt_tc) "
653fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                   "(startup of code management)");
654fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
655fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Figure out how big each tc area should be.  */
65643b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   avg_codeszQ   = (VG_(details).avg_translation_sizeB + 7) / 8;
65743b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   tc_sector_szQ = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ);
658fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
659fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Ensure the calculated value is not way crazy. */
660fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR_USABLE);
661fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tc_sector_szQ <= 50 * N_TTES_PER_SECTOR_USABLE);
662fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
663fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Initialise the sectors */
664fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest_sector = 0;
665fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < N_SECTORS; i++) {
666fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tc = NULL;
667fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tt = NULL;
668fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tc_next = NULL;
669fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tt_n_inuse = 0;
6706c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
6714ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
672fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* and the fast caches. */
673fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
674fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
675fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (VG_(clo_verbosity) > 2) {
676fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
677fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         "TT/TC: cache: %d sectors of %d bytes each = %d total",
678fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          N_SECTORS, 8 * tc_sector_szQ,
679fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          N_SECTORS * 8 * tc_sector_szQ );
680fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
681fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         "TT/TC: table: %d total entries, max occupancy %d (%d%%)",
682fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         N_SECTORS * N_TTES_PER_SECTOR,
683fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         N_SECTORS * N_TTES_PER_SECTOR_USABLE,
684fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         SECTOR_TT_LIMIT_PERCENT );
685fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
68645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
68745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "transtab",
68845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      "cache: %d sectors of %d bytes each = %d total\n",
68945f4e7c91119c7d01a59f5e827c67841632c9314sewardj       N_SECTORS, 8 * tc_sector_szQ,
69045f4e7c91119c7d01a59f5e827c67841632c9314sewardj       N_SECTORS * 8 * tc_sector_szQ );
69145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "transtab",
69245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      "table: %d total entries, max occupancy %d (%d%%)\n",
69345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      N_SECTORS * N_TTES_PER_SECTOR,
69445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      N_SECTORS * N_TTES_PER_SECTOR_USABLE,
69545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      SECTOR_TT_LIMIT_PERCENT );
696de4a1d01951937632098a6cda45859afa587a06fsewardj}
697de4a1d01951937632098a6cda45859afa587a06fsewardj
6984ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
699fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
700fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics.                             ---*/
701fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
702fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
703fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong safe_idiv( ULong a, ULong b )
70492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
70592e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   return (b == 0 ? 0 : a / b);
70692e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
70792e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote
708fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void )
709fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
710fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n_in_count;
711fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
712fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
713fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void )
71492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
71592e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
7160fd92f4126a029b2c73fd217b337121c38070066njn      "    tt/tc: %,llu tt lookups requiring %,llu probes",
717fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_full_lookups, n_lookup_probes );
71892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
7190fd92f4126a029b2c73fd217b337121c38070066njn      "    tt/tc: %,llu fast-cache updates, %,llu flushes",
720fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_fast_updates, n_fast_flushes );
721fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
72292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
7230fd92f4126a029b2c73fd217b337121c38070066njn                "translate: new        %,lld "
7240fd92f4126a029b2c73fd217b337121c38070066njn                "(%,llu -> %,llu; ratio %,llu:10) [%,llu scs]",
725fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_in_count, n_in_osize, n_in_tsize,
72626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                safe_idiv(10*n_in_tsize, n_in_osize),
72726412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                n_in_sc_count);
72892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
7290fd92f4126a029b2c73fd217b337121c38070066njn                "translate: dumped     %,llu (%,llu -> ?" "?)",
730fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_dump_count, n_dump_osize );
731fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   VG_(message)(Vg_DebugMsg,
7320fd92f4126a029b2c73fd217b337121c38070066njn                "translate: discarded  %,llu (%,llu -> ?" "?)",
733fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_disc_count, n_disc_osize );
73492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
735de4a1d01951937632098a6cda45859afa587a06fsewardj
736fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
737fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results.                   ---*/
738fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
7394ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
740fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong score ( TTEntry* tte )
741fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
742fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return ((ULong)tte->weight) * ((ULong)tte->count);
743de4a1d01951937632098a6cda45859afa587a06fsewardj}
744de4a1d01951937632098a6cda45859afa587a06fsewardj
7452025cf98a3210c175a90fc77cb599cca1643bd68njnULong VG_(get_BB_profile) ( BBProfEntry tops[], UInt n_tops )
746de4a1d01951937632098a6cda45859afa587a06fsewardj{
747fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int   sno, i, r, s;
7482025cf98a3210c175a90fc77cb599cca1643bd68njn   ULong score_total;
749fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
750fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* First, compute the total weighted count, and find the top N
7512025cf98a3210c175a90fc77cb599cca1643bd68njn      ttes.  tops contains pointers to the most-used n_tops blocks, in
752fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      descending order (viz, tops[0] is the highest scorer). */
7532025cf98a3210c175a90fc77cb599cca1643bd68njn   for (i = 0; i < n_tops; i++) {
7542025cf98a3210c175a90fc77cb599cca1643bd68njn      tops[i].addr  = 0;
7552025cf98a3210c175a90fc77cb599cca1643bd68njn      tops[i].score = 0;
7562025cf98a3210c175a90fc77cb599cca1643bd68njn   }
757fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
758fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   score_total = 0;
759fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
760fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (sno = 0; sno < N_SECTORS; sno++) {
761fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[sno].tc == NULL)
76218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         continue;
763fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
764fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[i].status != InUse)
765fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            continue;
766fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         score_total += score(&sectors[sno].tt[i]);
767fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* Find the rank for sectors[sno].tt[i]. */
7682025cf98a3210c175a90fc77cb599cca1643bd68njn         r = n_tops-1;
769fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         while (True) {
770fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (r == -1)
771fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               break;
7722025cf98a3210c175a90fc77cb599cca1643bd68njn             if (tops[r].addr == 0) {
773fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               r--;
774fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               continue;
775fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
7762025cf98a3210c175a90fc77cb599cca1643bd68njn             if ( score(&sectors[sno].tt[i]) > tops[r].score ) {
777fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                r--;
778fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                continue;
779fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
780fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             break;
781fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
782fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         r++;
7832025cf98a3210c175a90fc77cb599cca1643bd68njn         vg_assert(r >= 0 && r <= n_tops);
784fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* This bb should be placed at r, and bbs above it shifted
785fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            upwards one slot. */
7862025cf98a3210c175a90fc77cb599cca1643bd68njn         if (r < n_tops) {
7872025cf98a3210c175a90fc77cb599cca1643bd68njn            for (s = n_tops-1; s > r; s--)
788fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               tops[s] = tops[s-1];
7892025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].addr  = sectors[sno].tt[i].entry;
7902025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].score = score( &sectors[sno].tt[i] );
791fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
792de4a1d01951937632098a6cda45859afa587a06fsewardj      }
793de4a1d01951937632098a6cda45859afa587a06fsewardj   }
794de4a1d01951937632098a6cda45859afa587a06fsewardj
7952025cf98a3210c175a90fc77cb599cca1643bd68njn   return score_total;
796c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
797c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
798de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
7998bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end                                                          ---*/
800de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
801