28 return (Gpa >> 12) & (Cache->LinesCount - 1);
75 QWORD totalHitCount = 0;
79 NLOG(
"Number of lines: %d\n", Cache->LinesCount);
80 NLOG(
"Entries per line: %d\n", Cache->EntriesCount);
83 for (i = 0; i < Cache->LinesCount; i++)
85 QWORD lineHitCount = 0;
87 for (j = 0; j < Cache->EntriesCount; j++)
89 if (Cache->Lines[i].Entries[j].Valid)
91 NLOG(
"%04d:%02d: 0x%016llx:%p, %04d %04d %d\n",
93 Cache->Lines[i].Entries[j].Gpa,
94 Cache->Lines[i].Entries[j].Hva,
95 Cache->Lines[i].Entries[j].HitCount,
96 Cache->Lines[i].Entries[j].UseCount,
97 Cache->Lines[i].Entries[j].Valid);
99 totalHitCount += Cache->Lines[i].Entries[j].HitCount;
100 lineHitCount += Cache->Lines[i].Entries[j].HitCount;
104 if (lineHitCount > 0)
106 NLOG(
" HitCount: %lld\n", lineHitCount);
110 NLOG(
"TOTALHC: %lld\n", totalHitCount);
145 if (0 != (LinesCount & (LinesCount - 1)))
160 if (NULL == pCache->
Lines)
163 goto cleanup_and_exit;
166 for (
DWORD i = 0; i < LinesCount; i++)
172 goto cleanup_and_exit;
185 if (NULL != pCache->
Lines)
187 for (
DWORD i = 0; i < LinesCount; i++)
257 while (list != &pCache->
Victims)
305 DWORD line, entry, minHits;
309 minHits = 0xFFFFFFFF;
314 for (
DWORD i = 0; i < Cache->EntriesCount; i++)
316 if (!Cache->Lines[line].Entries[i].Valid)
324 if ((minHits > Cache->Lines[line].Entries[i].HitCount) && (0 == Cache->Lines[line].Entries[i].UseCount))
326 minHits = Cache->Lines[line].Entries[i].HitCount;
333 if (minHits == 0xFFFFFFFF)
335 entry =
__rdtsc() % Cache->EntriesCount;
339 if (Cache->Lines[line].Entries[entry].Valid && (Cache->Lines[line].Entries[entry].UseCount > 0))
341 TRACE(
"[GPACACHE] Adding victim entry for GPA %llx, use count %d...\n",
342 Cache->Lines[line].Entries[entry].Gpa, Cache->Lines[line].Entries[entry].UseCount);
347 ERROR(
"[ERROR] IntGpaCacheAddVictim failed: 0x%08x\n", status);
348 goto cleanup_and_exit;
351 else if (Cache->Lines[line].Entries[entry].Valid && (Cache->Lines[line].Entries[entry].UseCount == 0))
361 Cache->Lines[line].Entries[entry].Valid =
TRUE;
362 Cache->Lines[line].Entries[entry].HitCount = 0;
363 Cache->Lines[line].Entries[entry].UseCount = 0;
364 Cache->Lines[line].Entries[entry].Gpa = Gpa;
368 Cache->Lines[line].Entries[entry].Valid =
FALSE;
369 Cache->Lines[line].Entries[entry].Gpa = 0;
372 *Entry = &Cache->Lines[line].Entries[entry];
409 for (i = 0; i < Cache->EntriesCount; i++)
411 if (Cache->Lines[line].Entries[i].Valid && (Cache->Lines[line].Entries[i].Gpa == Gpa))
413 *Entry = &Cache->Lines[line].Entries[i];
423 list = Cache->Victims.
Flink;
425 while (list != &Cache->Victims)
433 TRACE(
"[GPACACHE] Entry %llx found in victim cache, will not add it back...\n", Gpa);
434 *Entry = &pVictim->
Entry;
584 memcpy(Buffer, data, Size);
669 memcpy(data, Buffer, Size);
715 for (i = 0; i < Cache->EntriesCount; i++)
717 if (Cache->Lines[line].Entries[i].Valid && (Cache->Lines[line].Entries[i].Gpa == Gpa))
719 if (Cache->Lines[line].Entries[i].UseCount > 0)
721 Cache->Lines[line].Entries[i].UseCount--;
731 TRACE(
"[GPACACHE] Entry %llx not found in main cache, searching victim cache...\n", Gpa);
733 list = Cache->Victims.
Flink;
735 while (list != &Cache->Victims)
800 for (i = 0; i < Cache->LinesCount; i++)
802 for (j = 0; j < Cache->EntriesCount; j++)
804 if (Cache->Lines[i].Entries[j].Valid)
806 if (Cache->Lines[i].Entries[j].UseCount == 0)
815 ERROR(
"[ERROR] IntGpaCacheAddVictim failed: 0x%08x\n", status);
819 Cache->Lines[i].Entries[j].Valid =
FALSE;
820 Cache->Lines[i].Entries[j].Gpa = 0;
821 Cache->Lines[i].Entries[j].HitCount = 0;
822 Cache->Lines[i].Entries[j].UseCount = 0;
#define CONTAINING_RECORD(List, Type, Member)
static INTSTATUS IntGpaCacheLookupEntry(PGPA_CACHE Cache, QWORD Gpa, PGPA_CACHE_ENTRY *Entry)
Search an entry in the GPA cache.
INTSTATUS IntGpaCacheRelease(PGPA_CACHE Cache, QWORD Gpa)
Release a previously used cached entry.
#define INT_STATUS_SUCCESS
GPA_CACHE_ENTRY Entry
The actual cache entry.
void IntGpaCacheDump(PGPA_CACHE Cache)
Dumps the entire contents of the GPA cache.
struct _LIST_ENTRY * Flink
#define INT_SUCCESS(Status)
DWORD UseCount
Reference count, incremented by calls to IntGpaCacheFindAndAdd.
#define HpAllocWithTag(Len, Tag)
#define PHYS_MAP_FLG_NO_FASTMAP
Indicates that IntPhysMemMap should not use the fast memory mapping mechanism.
int INTSTATUS
The status data type.
#define INT_STATUS_NOT_FOUND
INTSTATUS IntGpaCacheFindAndAdd(PGPA_CACHE Cache, QWORD Gpa, void **Hva)
Search for an entry in the GPA cache, and add it, if it wasn't found.
LIST_ENTRY Victims
List of victim entries evicted from the cache while UseCount is not 0.
QWORD Gpa
Gpa this entry maps to.
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
#define INT_STATUS_INVALID_PARAMETER_4
GPA_CACHE_LINE * Lines
Actual array of cache lines.
LIST_ENTRY Link
Linked list entry.
#define HpFreeAndNullWithTag(Add, Tag)
static INTSTATUS IntGpaCacheAddVictim(PGPA_CACHE Cache, PGPA_CACHE_ENTRY Entry)
Add an entry in the victim cache.
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
static void InitializeListHead(LIST_ENTRY *ListHead)
static uint64_t __rdtsc(void)
void * Hva
Host pointer which maps to Gpa.
DWORD HitCount
Number of times this entry was accessed.
static INTSTATUS IntGpaCacheAddEntry(PGPA_CACHE Cache, QWORD Gpa, PGPA_CACHE_ENTRY *Entry)
Add a new entry inside the GPA cache.
static __inline DWORD IntGpaCacheHashLine(PGPA_CACHE Cache, QWORD Gpa)
Compute the line index for a given address.
INTSTATUS IntGpaCacheFetchAndAdd(PGPA_CACHE Cache, QWORD Gpa, DWORD Size, PBYTE Buffer)
Fetch data from a cached entry, or add it to the cache, of not already present.
INTSTATUS IntGpaCacheUnInit(PGPA_CACHE *Cache)
Uninit a GPA cache.
__must_check INTSTATUS IntPhysMemMap(QWORD PhysAddress, DWORD Length, DWORD Flags, void **HostPtr)
Maps a guest physical address inside Introcore VA space.
#define INT_STATUS_NOT_INITIALIZED_HINT
#define INT_STATUS_INVALID_PARAMETER_1
#define INT_STATUS_NOT_SUPPORTED
INTSTATUS IntGpaCacheFlush(PGPA_CACHE Cache)
Flush the entire GPA cache.
INTSTATUS IntGpaCacheInit(PGPA_CACHE *Cache, DWORD LinesCount, DWORD EntriesCount)
Initialize a GPA cache.
DWORD LinesCount
Number of lines.
GPA_CACHE_ENTRY * Entries
An array of cache entries.
unsigned long long * PQWORD
DWORD EntriesCount
Number of entries per line.
INTSTATUS IntPhysMemUnmap(void **HostPtr)
Unmaps an address previously mapped with IntPhysMemMap.
INTSTATUS IntGpaCachePatchAndAdd(PGPA_CACHE Cache, QWORD Gpa, DWORD Size, PBYTE Buffer)
Patch data in a cached entry, or add it to the cache, of not already present.
BOOLEAN Valid
True if the entry is valid, false otherwise.
#define INT_STATUS_INSUFFICIENT_RESOURCES
#define INT_STATUS_INVALID_PARAMETER_3