Bitdefender Hypervisor Memory Introspection
gpacache.c File Reference
#include "gpacache.h"
#include "glue.h"
#include "introcrt.h"

Go to the source code of this file.

Functions

static __inline DWORD IntGpaCacheHashLine (PGPA_CACHE Cache, QWORD Gpa)
 Compute the line index for a given address. More...
 
static INTSTATUS IntGpaCacheAddVictim (PGPA_CACHE Cache, PGPA_CACHE_ENTRY Entry)
 Add an entry in the victim cache. More...
 
void IntGpaCacheDump (PGPA_CACHE Cache)
 Dumps the entire contents of the GPA cache. More...
 
INTSTATUS IntGpaCacheInit (PGPA_CACHE *Cache, DWORD LinesCount, DWORD EntriesCount)
 Initialize a GPA cache. More...
 
INTSTATUS IntGpaCacheUnInit (PGPA_CACHE *Cache)
 Uninit a GPA cache. More...
 
static INTSTATUS IntGpaCacheAddEntry (PGPA_CACHE Cache, QWORD Gpa, PGPA_CACHE_ENTRY *Entry)
 Add a new entry inside the GPA cache. More...
 
static INTSTATUS IntGpaCacheLookupEntry (PGPA_CACHE Cache, QWORD Gpa, PGPA_CACHE_ENTRY *Entry)
 Search an entry in the GPA cache. More...
 
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. More...
 
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. More...
 
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. More...
 
INTSTATUS IntGpaCacheRelease (PGPA_CACHE Cache, QWORD Gpa)
 Release a previously used cached entry. More...
 
INTSTATUS IntGpaCacheFlush (PGPA_CACHE Cache)
 Flush the entire GPA cache. More...
 

Function Documentation

◆ IntGpaCacheAddEntry()

static INTSTATUS IntGpaCacheAddEntry ( PGPA_CACHE  Cache,
QWORD  Gpa,
PGPA_CACHE_ENTRY Entry 
)
static

Add a new entry inside the GPA cache.

Internal function used to add an entry to the GPA cache. This function will iterate the entries inside the Gpa cache line, and will select one of the following:

  • The first invalid entry, or
  • The entry with the lowest number of hits which is not in use, or
  • A random entry If the entry is valid, but not referenced, it will be evicted from the cache. If the entry is valid and referenced, it will be added to the victim cache. A new PGPA_CACHE_ENTRY structure will be allocated for the newly allocated entry, and it will be returned.
Parameters
[in]CacheThe GPA cache.
[in]GpaThe Gpa to be added in the cache.
[out]EntryThe freshly allocated GPA cache entry.
Returns
INT_STATUS_SUCCESS On success.

Definition at line 280 of file gpacache.c.

Referenced by IntGpaCacheFetchAndAdd(), IntGpaCacheFindAndAdd(), and IntGpaCachePatchAndAdd().

◆ IntGpaCacheAddVictim()

static INTSTATUS IntGpaCacheAddVictim ( PGPA_CACHE  Cache,
PGPA_CACHE_ENTRY  Entry 
)
static

Add an entry in the victim cache.

Adds a victim entry for the provided GPA cache. Victims are added when entries which are still referenced must be evicted to make space for other entries. The victim cache is simply a linked list of evicted entries.

Parameters
[in]CacheThe GPA cache.
[in]EntryThe cache entry that must be added to the victim cache.
Returns
INT_STATUS_SUCCESS On success.
INT_STATUS_INSUFFICIENT_RESOURCES If memory could not be allocated for the victim entry.

Definition at line 33 of file gpacache.c.

Referenced by IntGpaCacheAddEntry(), and IntGpaCacheFlush().

◆ IntGpaCacheDump()

void IntGpaCacheDump ( PGPA_CACHE  Cache)

Dumps the entire contents of the GPA cache.

Parameters
[in]CacheThe GPA cache to dump.

Definition at line 65 of file gpacache.c.

Referenced by DbgDumpGpaCache().

◆ IntGpaCacheFetchAndAdd()

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.

This function will search for the guest physical address Gpa inside the cache. If it is not present, it will be added to the cache. Afterwards, it will copy Size bytes from the given Gpa into the provided Buffer. Gpa doesn't have to be page aligned. This function assumes that Buffer is large enough to accommodate at least the required size.

Parameters
[in]CacheThe GPA cache.
[in]GpaThe Gpa to be accessed.
[in]SizeNumber of bytes to copy from Gpa into Buffer.
[out]BufferWill contain, upon successful return, Size bytes copied from Gpa.
Returns
INT_STATUS_SUCCESS On success.
INT_STATUS_INVALID_PARAMETER If an invalid parameter is supplied.
INT_STATUS_NOT_SUPPORTED If a page overrun is encountered (Gpa + Size points outside the page).

Definition at line 508 of file gpacache.c.

Referenced by IntHookPtsCreateEntry(), IntHookPtsHandleModification(), IntHookPtwEmulateWrite(), IntWinProcValidateSystemCr3(), and IntWinTokenFetchTokenAddress().

◆ IntGpaCacheFindAndAdd()

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.

Checks if the provided Gpa is inside the cache. If it is, it will return a pointer to an already mapped page pointing to the given Gpa. If it isn't, it will first add the entry to the cache, and then return a pointer to the mapped page. The pointer to the mapped page is reference-counted, meaning that once this function is called, the mapped Gpa will be locked (it will not be evicted from the cache and the returned pointer will not be unmapped). In order to properly release the mapped Gpa, IntGpaCacheRelease must be called on Gpa.

Parameters
[in]CacheThe GPA cache.
[in]GpaThe guest physical address that must be returned from the cache.
[out]HvaA mapped page tat points to the provided Gpa.
Returns
INT_STATUS_SUCCESS On success.
INT_STATUS_INVALID_PARAMETER If an invalid parameter has been supplied.

Definition at line 451 of file gpacache.c.

Referenced by IntDecEmulatePTWrite(), IntDispatchVeAsEpt(), IntIntegrityCheckAll(), and IntMapGpaForTranslation().

◆ IntGpaCacheFlush()

INTSTATUS IntGpaCacheFlush ( PGPA_CACHE  Cache)

Flush the entire GPA cache.

Flushes the entire GPA cache - unmaps & removes all the entries cached so far. Note that entries that are in use (GPAs for which IntGpaCacheFindAndAdd was called, without releasing them using IntGpaCacheRelease) will be moved inside the victim cache, and references to those pages will remain valid until the victim cache is flushed.

Parameters
[in]CacheThe GPA cache.
Returns
INT_STATUS_SUCCESS On success.
INT_STATUS_INVALID_PARAMETER If an invalid parameter is supplied.

Definition at line 776 of file gpacache.c.

Referenced by IntFlushGpaCache().

◆ IntGpaCacheHashLine()

static __inline DWORD IntGpaCacheHashLine ( PGPA_CACHE  Cache,
QWORD  Gpa 
)
static

Compute the line index for a given address.

Computes the line index from a Gpa. The lines index simply represents the lowest page number bits; for example, if 16 lines count are used, and the Gpa is 0x12345678, the hash/line index will be (0x12345678 >> 12) & (16 - 1) = 5.

Parameters
[in]CacheThe GPA cache.
[in]GpaThe Gpa for which we compute the line index.
Returns
The line index computed from the given Gpa.

Definition at line 11 of file gpacache.c.

Referenced by IntGpaCacheAddEntry(), IntGpaCacheLookupEntry(), and IntGpaCacheRelease().

◆ IntGpaCacheInit()

INTSTATUS IntGpaCacheInit ( PGPA_CACHE Cache,
DWORD  LinesCount,
DWORD  EntriesCount 
)

Initialize a GPA cache.

Initializes a new GPA cache. The GPA cache will have a layout given by LinesCount and EntriesCount: it will be EntriesCount associative, with LinesCount lines, for a total of EntriesCount * LinesCount entries.

Parameters
[in,out]CacheWill contain, upon successful return, the allocated GPA cache.
[in]LinesCountThe number of cache lines.
[in]EntriesCountThe number of entries per cache line.
Returns
INT_STATUS_SUCCESS if the cache has been successfully created.
INT_STATUS_INSUFFICIENT_RESOURCES If memory could not be allocated.
INT_STATUS_INVALID_PARAMETER If an invalid parameter has been supplied.

Definition at line 115 of file gpacache.c.

Referenced by IntGuestInit().

◆ IntGpaCacheLookupEntry()

static INTSTATUS IntGpaCacheLookupEntry ( PGPA_CACHE  Cache,
QWORD  Gpa,
PGPA_CACHE_ENTRY Entry 
)
static

Search an entry in the GPA cache.

It will search, inside the provided GPA cache, for an entry associated with the provided Gpa.

Parameters
[in]CacheThe GPA cache.
[in]GpaThe Gpa to be searched.
[out]EntryWill contain, upon successful return, the entry associated with the provided Gpa.
Returns
INT_STATUS_SUCCESS On success (Entry will be valid).
INT_STATUS_NOT_FOUND If no entry associated with Gpa is present inside the cache.

Definition at line 380 of file gpacache.c.

Referenced by IntGpaCacheFetchAndAdd(), IntGpaCacheFindAndAdd(), and IntGpaCachePatchAndAdd().

◆ IntGpaCachePatchAndAdd()

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.

This function will search for the guest physical address Gpa inside the cache. If it is not present, it will be added to the cache. Afterwards, it will copy Size bytes from the provided Buffer into the given Gpa. Gpa doesn't have to be page aligned. This function assumes that Buffer is large enough to accommodate at least the required size.

Parameters
[in]CacheThe GPA cache.
[in]GpaThe Gpa to be accessed.
[in]SizeNumber of bytes to copy from Gpa into Buffer.
[in]BufferContains the data to be copied at Gpa.
Returns
INT_STATUS_SUCCESS On success.
INT_STATUS_INVALID_PARAMETER If an invalid parameter is supplied.
INT_STATUS_NOT_SUPPORTED If a page overrun is encountered (Gpa + Size points outside the page).

Definition at line 593 of file gpacache.c.

Referenced by IntDispatchVeAsEpt().

◆ IntGpaCacheRelease()

INTSTATUS IntGpaCacheRelease ( PGPA_CACHE  Cache,
QWORD  Gpa 
)

Release a previously used cached entry.

Releases a previously mapped Gpa. This function must be called once the pointer returned by IntGpaCacheFindAndAdd is no longer needed. Calling this function for Gpa values that were not previously mapped using IntGpaCacheFindAndAdd will lead to undefined behavior. Note that the Gpa may have been moved inside the victim cache, if space was needed inside that particular cache line for another entry. This, however, is transparent to the caller.

Parameters
[in]CacheThe GPA cache.
[in]GpaThe Gpa previously mapped using IntGpaCacheFindAndAdd.
Returns
INT_STATUS_SUCCESS On success.
INT_STATUS_INVALID_PARAMETER If an invalid parameter is supplied.
INT_STATUS_NOT_FOUND If the provided Gpa is not found inside the cache.

Definition at line 678 of file gpacache.c.

Referenced by IntDecEmulatePTWrite(), IntDispatchVeAsEpt(), IntIntegrityCheckAll(), and IntUnmapGpaForTranslation().

◆ IntGpaCacheUnInit()

INTSTATUS IntGpaCacheUnInit ( PGPA_CACHE Cache)

Uninit a GPA cache.

Frees a previously initialized GPA cache. All entries, including entries inside the victim cache, will be removed. This function should be called only during uninit, as it carries to risk of leaving dangling pointers, if all Gpa entries were not released before calling this function.

Parameters
[in,out]CacheThe previously allocated GPA cache.
Returns
INT_STATUS_SUCCESS On success.
INT_STATUS_NOT_INITIALIZED_HINT If the provided Cache is not allocated (it is NULL).

Definition at line 209 of file gpacache.c.

Referenced by IntGuestUninit().