85
85
/*------------------ TYPES ------------------*/
87
/* A translation-cache entry is two parts:
88
- The guest address of the first (entry) bb in the translation,
90
- One or more 64-bit words containing the code.
91
It is supposed to be 64-bit aligned.
102
87
/* A translation-table entry. This indicates precisely which areas of
103
88
guest code are included in the translation, and contains all other
104
89
auxiliary info too. */
117
102
deletion, hence the Deleted state. */
118
103
enum { InUse, Deleted, Empty } status;
120
/* Pointer to the corresponding TCEntry (must be in the same
105
/* 64-bit aligned pointer to one or more 64-bit words containing
106
the corresponding host code (must be in the same sector!)
107
This is a pointer into the sector's tc (code) area. */
124
110
/* This is the original guest address that purportedly is the
125
111
entry point of the translation. You might think that .entry
214
200
static Int tc_sector_szQ;
217
/* Fast helper for the TC. A direct-mapped cache which holds a
218
pointer to a TC entry which may or may not be the correct one, but
219
which we hope usually is. This array is referred to directly from
203
/* Fast helper for the TC. A direct-mapped cache which holds a set of
204
recently used (guest address, host address) pairs. This array is
205
referred to directly from m_dispatch/dispatch-<platform>.S.
222
Entries in tt_fast may point to any valid TC entry, regardless of
207
Entries in tt_fast may refer to any valid TC entry, regardless of
223
208
which sector it's in. Consequently we must be very careful to
224
209
invalidate this cache when TC entries are changed or disappear.
226
A special TCEntry -- bogus_tc_entry -- must be pointed at to cause
227
that cache entry to miss. This relies on the assumption that no
228
guest code actually has an address of 0x1.
230
/*global*/ ULong* VG_(tt_fast)[VG_TT_FAST_SIZE];
232
static ULong bogus_tc_entry = (Addr64)1;
211
A special .guest address - TRANSTAB_BOGUS_GUEST_ADDR -- must be
212
pointed at to cause that cache entry to miss. This relies on the
213
assumption that no guest code actually has that address, hence a
214
value 0x1 seems good. m_translate gives the client a synthetic
215
segfault if it tries to execute at this address.
225
/*global*/ __attribute__((aligned(16)))
226
FastCacheEntry VG_(tt_fast)[VG_TT_FAST_SIZE];
228
#define TRANSTAB_BOGUS_GUEST_ADDR ((Addr)1)
235
231
/* For profiling, we have a parallel array of pointers to .count
236
232
fields in TT entries. Again, these pointers must be invalidated
237
233
when translations disappear. A NULL pointer suffices to indicate
240
tt_fast and tt_fastN change together: if tt_fast[i] points to
241
bogus_tc_entry then the corresponding tt_fastN[i] must be null. If
242
tt_fast[i] points to some TC entry somewhere, then tt_fastN[i]
243
*must* point to the .count field of the corresponding TT entry.
236
When not profiling (the normal case, VG_(clo_profile_flags) == 0),
237
all tt_fastN entries are set to NULL at startup and never read nor
240
When profiling (VG_(clo_profile_flags) > 0), tt_fast and tt_fastN
241
change together: if tt_fast[i].guest is TRANSTAB_BOGUS_GUEST_ADDR
242
then the corresponding tt_fastN[i] must be null. If
243
tt_fast[i].guest is any other value, then tt_fastN[i] *must* point
244
to the .count field of the corresponding TT entry.
245
246
tt_fast and tt_fastN are referred to from assembly code
609
613
return k32 % N_TTES_PER_SECTOR;
612
static void setFastCacheEntry ( Addr64 key, ULong* tce, UInt* count )
616
static void setFastCacheEntry ( Addr64 key, ULong* tcptr, UInt* count )
614
618
UInt cno = (UInt)VG_TT_FAST_HASH(key);
615
VG_(tt_fast)[cno] = tce;
616
VG_(tt_fastN)[cno] = count;
619
VG_(tt_fast)[cno].guest = (Addr)key;
620
VG_(tt_fast)[cno].host = (Addr)tcptr;
621
if (VG_(clo_profile_flags) > 0)
622
VG_(tt_fastN)[cno] = count;
617
623
n_fast_updates++;
624
/* This shouldn't fail. It should be assured by m_translate
625
which should reject any attempt to make translation of code
626
starting at TRANSTAB_BOGUS_GUEST_ADDR. */
627
vg_assert(VG_(tt_fast)[cno].guest != TRANSTAB_BOGUS_GUEST_ADDR);
620
static void invalidateFastCache ( void )
630
/* Invalidate the fast cache's counter array, VG_(tt_fastN). */
631
static void invalidateFastNCache ( void )
623
/* This loop is popular enough to make it worth unrolling a
624
bit, at least on ppc32. */
625
634
vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0);
626
635
for (j = 0; j < VG_TT_FAST_SIZE; j += 4) {
627
VG_(tt_fast)[j+0] = &bogus_tc_entry;
628
VG_(tt_fast)[j+1] = &bogus_tc_entry;
629
VG_(tt_fast)[j+2] = &bogus_tc_entry;
630
VG_(tt_fast)[j+3] = &bogus_tc_entry;
631
636
VG_(tt_fastN)[j+0] = NULL;
632
637
VG_(tt_fastN)[j+1] = NULL;
633
638
VG_(tt_fastN)[j+2] = NULL;
634
639
VG_(tt_fastN)[j+3] = NULL;
636
641
vg_assert(j == VG_TT_FAST_SIZE);
644
/* Invalidate the fast cache VG_(tt_fast). If profiling, also
645
invalidate the fast cache's counter array VG_(tt_fastN), otherwise
647
static void invalidateFastCache ( void )
650
/* This loop is popular enough to make it worth unrolling a
651
bit, at least on ppc32. */
652
vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0);
653
for (j = 0; j < VG_TT_FAST_SIZE; j += 4) {
654
VG_(tt_fast)[j+0].guest = TRANSTAB_BOGUS_GUEST_ADDR;
655
VG_(tt_fast)[j+1].guest = TRANSTAB_BOGUS_GUEST_ADDR;
656
VG_(tt_fast)[j+2].guest = TRANSTAB_BOGUS_GUEST_ADDR;
657
VG_(tt_fast)[j+3].guest = TRANSTAB_BOGUS_GUEST_ADDR;
660
if (VG_(clo_profile_flags) > 0)
661
invalidateFastNCache();
663
vg_assert(j == VG_TT_FAST_SIZE);
637
664
n_fast_flushes++;
667
static Bool sanity_check_fastcache ( void )
670
if (0) VG_(printf)("sanity check fastcache\n");
671
if (VG_(clo_profile_flags) > 0) {
673
for (j = 0; j < VG_TT_FAST_SIZE; j++) {
674
if (VG_(tt_fastN)[j] == NULL
675
&& VG_(tt_fast)[j].guest != TRANSTAB_BOGUS_GUEST_ADDR)
677
if (VG_(tt_fastN)[j] != NULL
678
&& VG_(tt_fast)[j].guest == TRANSTAB_BOGUS_GUEST_ADDR)
683
for (j = 0; j < VG_TT_FAST_SIZE; j++) {
684
if (VG_(tt_fastN)[j] != NULL)
640
691
static void initialiseSector ( Int sno )
785
839
Bool is_self_checking )
787
841
Int tcAvailQ, reqdQ, y, i;
842
ULong *tcptr, *tcptr2;
792
846
vg_assert(init_done);
793
847
vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
794
vg_assert(code_len > 0 && code_len < 20000);
849
/* 60000: should agree with N_TMPBUF in m_translate.c. */
850
vg_assert(code_len > 0 && code_len < 60000);
797
853
VG_(printf)("add_to_transtab(entry = 0x%llx, len = %d)\n",
850
906
vg_assert(sectors[y].tt_n_inuse >= 0);
852
908
/* Copy into tc. */
853
tce = sectors[y].tc_next;
854
vg_assert(tce >= §ors[y].tc[0]);
855
vg_assert(tce <= §ors[y].tc[tc_sector_szQ]);
909
tcptr = sectors[y].tc_next;
910
vg_assert(tcptr >= §ors[y].tc[0]);
911
vg_assert(tcptr <= §ors[y].tc[tc_sector_szQ]);
858
dstP = (UChar*)(&tce[1]);
913
dstP = (UChar*)tcptr;
859
914
srcP = (UChar*)code;
860
915
for (i = 0; i < code_len; i++)
861
916
dstP[i] = srcP[i];
865
920
invalidate_icache( dstP, code_len );
867
922
/* more paranoia */
868
tce2 = sectors[y].tc_next;
869
vg_assert(tce2 >= §ors[y].tc[0]);
870
vg_assert(tce2 <= §ors[y].tc[tc_sector_szQ]);
923
tcptr2 = sectors[y].tc_next;
924
vg_assert(tcptr2 >= §ors[y].tc[0]);
925
vg_assert(tcptr2 <= §ors[y].tc[tc_sector_szQ]);
872
927
/* Find an empty tt slot, and use it. There must be such a slot
873
928
since tt is never allowed to get completely full. */
885
940
sectors[y].tt[i].status = InUse;
886
sectors[y].tt[i].tce = tce;
941
sectors[y].tt[i].tcptr = tcptr;
887
942
sectors[y].tt[i].count = 0;
888
943
sectors[y].tt[i].weight = 1;
889
944
sectors[y].tt[i].vge = *vge;
890
945
sectors[y].tt[i].entry = entry;
892
947
/* Update the fast-cache. */
893
setFastCacheEntry( entry, tce, §ors[y].tt[i].count );
948
setFastCacheEntry( entry, tcptr, §ors[y].tt[i].count );
895
950
/* Note the eclass numbers for this translation. */
896
951
upd_eclasses_after_add( §ors[y], i );
1390
1445
/* Otherwise lots of things go wrong... */
1391
1446
vg_assert(sizeof(ULong) == 8);
1392
1447
vg_assert(sizeof(Addr64) == 8);
1448
/* check fast cache entries really are 2 words long */
1449
vg_assert(sizeof(Addr) == sizeof(void*));
1450
vg_assert(sizeof(FastCacheEntry) == 2 * sizeof(Addr));
1451
/* check fast cache entries are packed back-to-back with no spaces */
1452
vg_assert(sizeof( VG_(tt_fast) ) == VG_TT_FAST_SIZE * sizeof(FastCacheEntry));
1453
/* check fast cache is aligned as we requested. Not fatal if it
1454
isn't, but we might as well make sure. */
1455
vg_assert(VG_IS_16_ALIGNED( ((Addr) & VG_(tt_fast)[0]) ));
1394
1457
if (VG_(clo_verbosity) > 2)
1395
1458
VG_(message)(Vg_DebugMsg,