Bitdefender Hypervisor Memory Introspection
icache.c File Reference
#include "icache.h"
#include "hook.h"

Go to the source code of this file.

Macros

#define INV_MASK   (~0x60ULL)
 

Functions

static __inline DWORD IntIcHashInv (PINS_CACHE Cache, QWORD Gva)
 Compute the invalidation entry index. More...
 
static __inline DWORD IntIcHashLine (PINS_CACHE Cache, QWORD Gva)
 Compute an instruction line index. More...
 
void IntIcDumpIcache (void)
 Dumps the entire contents of the implicit, per guest, instruction cache. More...
 
static INTSTATUS IntIcFreeInvdEntry (PINS_CACHE_INV_ENTRY Invd)
 Free an invalidation entry. More...
 
static INTSTATUS IntIcRemoveAllInvdEntries (PINS_CACHE Cache)
 Removes all the invalidation entries contained in this cache. This should be used only during uninit. More...
 
static INTSTATUS IntIcInvdEntry (PINS_CACHE Cache, PINS_CACHE_INV_ENTRY Invd)
 Decrements the reference count of the provided invalidation entry, and, if it reaches 0, it completely frees it. More...
 
static INTSTATUS IntIcInvdCacheEntry (PINS_CACHE Cache, PINS_CACHE_ENTRY Entry)
 Invalidate an instruction cache entry. More...
 
static INTSTATUS IntIcWriteHandler (INS_CACHE_INV_ENTRY const *Context, void const *Hook, QWORD Address, INTRO_ACTION *Action)
 Cached instruction page write handler. More...
 
static INTSTATUS IntIcSwapHandler (void *Context, QWORD VirtualAddress, QWORD OldEntry, QWORD NewEntry, QWORD OldPageSize, QWORD NewPageSize)
 Cache instruction page swap handler. More...
 
static INTSTATUS IntIcLookupInstructionInternal (PINS_CACHE Cache, PINSTRUX Instrux, QWORD Gva, QWORD Cr3, DWORD Lru)
 Lookup an instruction inside the cache. More...
 
INTSTATUS IntIcLookupInstruction (PINS_CACHE Cache, PINSTRUX Instrux, QWORD Gva, QWORD Cr3)
 Lookup an instruction inside the cache. More...
 
INTSTATUS IntIcFlush (PINS_CACHE Cache)
 Flush the entire instruction cache. More...
 
INTSTATUS IntIcFlushAddress (PINS_CACHE Cache, QWORD Gva, QWORD Cr3)
 Flush entries cached from a given address. More...
 
INTSTATUS IntIcFlushGvaPage (PINS_CACHE Cache, QWORD Gva, QWORD Cr3, BOOLEAN Spill)
 Flush all entries cached from a given guest virtual page. More...
 
INTSTATUS IntIcFlushGpaPage (PINS_CACHE Cache, QWORD Gpa)
 Flush all entries cached from a given guest physical page. More...
 
INTSTATUS IntIcFlushVaSpace (PINS_CACHE Cache, QWORD Cr3)
 Flush an entire virtual address space. More...
 
static INTSTATUS IntIcAddInvdForInstruction (PINS_CACHE Cache, QWORD Gva, QWORD Cr3, PINS_CACHE_INV_ENTRY *Invd)
 Add invalidation entries for a newly cached instruction. More...
 
INTSTATUS IntIcAddInstruction (PINS_CACHE Cache, PINSTRUX Instruction, QWORD Gva, QWORD Cr3, BOOLEAN Global)
 Adds an instruction to the cache. More...
 
INTSTATUS IntIcCreate (INS_CACHE **Cache, DWORD LinesCount, DWORD EntriesCount, DWORD InvCount)
 Create anew instruction cache. More...
 
INTSTATUS IntIcDestroy (PINS_CACHE *Cache)
 Destroy an instruction cache. More...
 

Macro Definition Documentation

◆ INV_MASK

#define INV_MASK   (~0x60ULL)

Referenced by IntIcSwapHandler().

Function Documentation

◆ IntIcAddInstruction()

INTSTATUS IntIcAddInstruction ( PINS_CACHE  Cache,
PINSTRUX  Instruction,
QWORD  Gva,
QWORD  Cr3,
BOOLEAN  Global 
)

Adds an instruction to the cache.

Will add the given instruction to the decoded instruction cache. If an invalid entry is found, the instruction will be added there. If not, a random entry will be selected for eviction. The instruction address Gva is used as a tag, and the address space Cr3 is used to indicate the process the instruction belongs to. If the instruction is in kernel, Cr3 must be IC_ANY_VAS and Global must be true, otherwise the instruction may be evicted from the cache even if the page it lies in is still valid. This function will automatically create the invalidation entries for this instruction, or reference an already existing invalidation entry, if instructions from this page have already been cached.

Parameters
[in]CacheThe instruction cache.
[in]InstructionThe decoded instruction to be added inside the cache.
[in]GvaInstruction address.
[in]Cr3Address space. Must be IC_ANY_VAS for kernel instructions.
[in]GlobalTrue if the instruction is global (shared among multiple address spaces).
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 952 of file icache.c.

Referenced by IntDecDecodeInstructionAtRipWithCache().

◆ IntIcAddInvdForInstruction()

static INTSTATUS IntIcAddInvdForInstruction ( PINS_CACHE  Cache,
QWORD  Gva,
QWORD  Cr3,
PINS_CACHE_INV_ENTRY Invd 
)
static

Add invalidation entries for a newly cached instruction.

Provided the virtual address Gva inside address space Cr3, this function will create & return an invalidation entry. Invalidation entries are used to keep track of all the instructions that must be invalidated inside a give page of memory.

Parameters
[in]CacheThe instruction cache.
[in]GvaThe instruction virtual address.
[in]Cr3The virtual address space. Can be IC_ANY_VAS for instructions which are inside kernel space.
[out]InvdWill contain upon successful return the invalidation entry created for the given address.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf a memory allocation failed.

Definition at line 852 of file icache.c.

Referenced by IntIcAddInstruction().

◆ IntIcCreate()

INTSTATUS IntIcCreate ( INS_CACHE **  Cache,
DWORD  LinesCount,
DWORD  EntriesCount,
DWORD  InvCount 
)

Create anew instruction cache.

Will create a new instruction cache. The layout will be given by LinesCount and EntriesCount, thus creating LinesCount x EntriesCount total entries inside the cache. InvCount give the number of entries for the invalidation structures, which are used to invalidate all instruction belonging to the same page.

Parameters
[in,out]CacheAn address to a pointer that will contain the instruction cache address.
[in]LinesCountNumber of lines.
[in]EntriesCountNumber of entries per line.
[in]InvCountNumber of lines for invalidation entries.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf a memory allocation fails.

Definition at line 1086 of file icache.c.

Referenced by IntGuestInit().

◆ IntIcDestroy()

INTSTATUS IntIcDestroy ( PINS_CACHE Cache)

Destroy an instruction cache.

Frees an instruction cache previously created using IntIcCreate.

Parameters
[in,out]CacheThe previously created instruction cache.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZED_HINTIf the provided cache was not allocated.

Definition at line 1211 of file icache.c.

Referenced by IntGuestUninit().

◆ IntIcDumpIcache()

void IntIcDumpIcache ( void  )

Dumps the entire contents of the implicit, per guest, instruction cache.

Definition at line 55 of file icache.c.

◆ IntIcFlush()

INTSTATUS IntIcFlush ( PINS_CACHE  Cache)

Flush the entire instruction cache.

Will invalidate the contents of the given instruction cache. This is done by marking every cached entry as invalid.

Parameters
[in]CacheThe instruction cache.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.

Definition at line 537 of file icache.c.

Referenced by IntIcCreate(), and IntVirtMemSafeWrite().

◆ IntIcFlushAddress()

INTSTATUS IntIcFlushAddress ( PINS_CACHE  Cache,
QWORD  Gva,
QWORD  Cr3 
)

Flush entries cached from a given address.

Will invalidate the entry tagged with Gva. If no entry with the given tag exists, it will return INT_STATUS_NOT_FOUND. This function will invalidate cached entries for a single address, not for an entire page. The function will invalidate only entries inside the provided address space given by Cr3, but it will always invalidate Global entries. If Cr3 == IC_ANY_VAS, entries in all address spaces will be invalidated. NOTE: After an entry is invalidated, it will no longer be used in any ways. It may be replaced by other entries that must be cached, if no other slots are available.

Parameters
[in]CacheThe instruction cache.
[in]GvaThe address to be invalidated.
[in]Cr3The target virtual address space. If Cr3 == IC_ANY_VAS, entries in all address spaces will be invalidated.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf no instruction is cached with the tag Gva.

Definition at line 597 of file icache.c.

Referenced by IntLixAgentActivatePendingAgent(), IntMtblDisable(), IntMtblPatchInstruction(), IntMtblRemoveEntry(), IntPtiDeleteInstruction(), IntPtiMonitorAllPtWriteCandidates(), IntSwapgsDisable(), IntSwapgsStartMitigation(), and IntWinAgentActivatePendingAgent().

◆ IntIcFlushGpaPage()

INTSTATUS IntIcFlushGpaPage ( PINS_CACHE  Cache,
QWORD  Gpa 
)

Flush all entries cached from a given guest physical page.

Will invalidate all entries cached inside the provided physical page. Low 12 bits inside Gpa are ignored. NOTE: After an entry is invalidated, it will no longer be used in any ways. It may be replaced by other entries that must be cached, if no other slots are available.

Parameters
[in]CacheThe instruction cache.
[in]GpaThe physical page to be invalidated.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf no instruction is cached with the tag Gva.

Definition at line 734 of file icache.c.

◆ IntIcFlushGvaPage()

INTSTATUS IntIcFlushGvaPage ( PINS_CACHE  Cache,
QWORD  Gva,
QWORD  Cr3,
BOOLEAN  Spill 
)

Flush all entries cached from a given guest virtual page.

Will invalidate all the instructions cached inside the provided virtual page. Low 12 bits inside Gva are ignored. If Spill is TRUE, it will only invalidate the last instruction in the page, if it spills inside the next page. NOTE: After an entry is invalidated, it will no longer be used in any ways. It may be replaced by other entries that must be cached, if no other slots are available.

Parameters
[in]CacheThe instruction cache.
[in]GvaThe page that must be invalidated.
[in]Cr3The target virtual address space. If Cr3 == IC_ANY_VAS, all address spaces will be flushed.
[in]SpillIf true, only the last instruction in the page will be invalidated, if it spills in the next page.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf no instruction is cached with the tag Gva.

Definition at line 664 of file icache.c.

Referenced by IntIcSwapHandler(), and IntIcWriteHandler().

◆ IntIcFlushVaSpace()

INTSTATUS IntIcFlushVaSpace ( PINS_CACHE  Cache,
QWORD  Cr3 
)

Flush an entire virtual address space.

Flushes all the instruction cached inside the provided virtual address space Cr3. If Cr3 == IC_ANY_VAS, instructions in every virtual address space will be flushed.

Parameters
[in]CacheThe instruction cache.
[in]Cr3The target virtual address space. If Cr3 == IC_ANY_VAS, all address spaces will be flushed.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 797 of file icache.c.

Referenced by IntLixTaskDeactivateExploitProtection(), IntLixTaskDestroy(), and IntWinProcChangeProtectionFlags().

◆ IntIcFreeInvdEntry()

static INTSTATUS IntIcFreeInvdEntry ( PINS_CACHE_INV_ENTRY  Invd)
static

Free an invalidation entry.

Frees the provided invalidation entry, by removing the swap hook and the write hook from the memory page that contains cached instructions.

Parameters
[in]InvdThe invalidation entry.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 136 of file icache.c.

Referenced by IntIcAddInvdForInstruction(), IntIcInvdEntry(), and IntIcRemoveAllInvdEntries().

◆ IntIcHashInv()

static __inline DWORD IntIcHashInv ( PINS_CACHE  Cache,
QWORD  Gva 
)
static

Compute the invalidation entry index.

Computes the index for the invalidation entry of a given instruction cache entry. The lowest log2(InvCount) bits from the Gva page number are used.

Parameters
[in]CacheThe instruction cache.
[in]GvaThe Gva for which the invalidation index is computed.
Returns
The invalidation entry index for the given Gva.

Definition at line 10 of file icache.c.

Referenced by IntIcAddInvdForInstruction().

◆ IntIcHashLine()

static __inline DWORD IntIcHashLine ( PINS_CACHE  Cache,
QWORD  Gva 
)
static

Compute an instruction line index.

Computes the line index for a given guest virtual address. The line index depends on the cache layout, as the lowest log2(LinesCount) bits from the Gva page number are used.

Parameters
[in]CacheThe instruction cache.
[in]GvaThe Gva for which the line index is computed.
Returns
The line index for the given Gva.

Definition at line 32 of file icache.c.

Referenced by IntIcAddInstruction(), IntIcFlushAddress(), IntIcFlushGvaPage(), and IntIcLookupInstructionInternal().

◆ IntIcInvdCacheEntry()

static INTSTATUS IntIcInvdCacheEntry ( PINS_CACHE  Cache,
PINS_CACHE_ENTRY  Entry 
)
static

Invalidate an instruction cache entry.

Provided an instruction cache entry, it will invalidate it. Note that for each entry, there are potentially two invalidation entries, if the instruction spans in two pages (one invalidation entry for each page).

Parameters
[in]CacheThe instruction cache.
[in]EntryThe instruction cache entry to be invalidated.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 261 of file icache.c.

Referenced by IntIcAddInstruction(), IntIcFlushAddress(), IntIcFlushGpaPage(), IntIcFlushGvaPage(), and IntIcFlushVaSpace().

◆ IntIcInvdEntry()

static INTSTATUS IntIcInvdEntry ( PINS_CACHE  Cache,
PINS_CACHE_INV_ENTRY  Invd 
)
static

Decrements the reference count of the provided invalidation entry, and, if it reaches 0, it completely frees it.

Parameters
[in]CacheThe instruction cache.
[in,out]InvdThe invalidation entry.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 219 of file icache.c.

Referenced by IntIcAddInstruction(), and IntIcInvdCacheEntry().

◆ IntIcLookupInstruction()

INTSTATUS IntIcLookupInstruction ( PINS_CACHE  Cache,
PINSTRUX  Instrux,
QWORD  Gva,
QWORD  Cr3 
)

Lookup an instruction inside the cache.

Will check the instruction cache to see if it contains a decoded instruction which is tagged with Gva. If so, it will copy the decoded instruction inside the buffer pointed by Instrux. Otherwise, it will return INT_STATUS_NOT_FOUND. Note that this is a wrapper over IntIcLookupInstructionInternal, and this function is publicly exposed to the callers.

Parameters
[in]CacheThe instruction cache.
[out]InstruxWill contain, upon successful return, the decoded instruction.
[in]GvaThe Gva that contains the instruction.
[in]Cr3The virtual address space that contains the instruction.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf no instruction is cached with the given Gva.

Definition at line 495 of file icache.c.

Referenced by IntDecDecodeInstructionAtRipWithCache().

◆ IntIcLookupInstructionInternal()

static INTSTATUS IntIcLookupInstructionInternal ( PINS_CACHE  Cache,
PINSTRUX  Instrux,
QWORD  Gva,
QWORD  Cr3,
DWORD  Lru 
)
static

Lookup an instruction inside the cache.

Will check the instruction cache to see if it contains a decoded instruction which is tagged with Gva. If so, it will copy the decoded instruction inside the buffer pointed by Instrux. Otherwise, it will return INT_STATUS_NOT_FOUND.

Parameters
[in]CacheThe instruction cache.
[out]InstruxWill contain, upon successful return, the decoded instruction.
[in]GvaThe Gva which contains the instruction.
[in]Cr3The virtual address space which contains the instruction.
[in]LruThe instruction ref count will be updated using this value.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf no instruction is cached with the given Gva.

Definition at line 427 of file icache.c.

Referenced by IntIcLookupInstruction().

◆ IntIcRemoveAllInvdEntries()

static INTSTATUS IntIcRemoveAllInvdEntries ( PINS_CACHE  Cache)
static

Removes all the invalidation entries contained in this cache. This should be used only during uninit.

Parameters
[in]CacheThe instruction cache.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 179 of file icache.c.

Referenced by IntIcDestroy(), and IntIcFlush().

◆ IntIcSwapHandler()

static INTSTATUS IntIcSwapHandler ( void *  Context,
QWORD  VirtualAddress,
QWORD  OldEntry,
QWORD  NewEntry,
QWORD  OldPageSize,
QWORD  NewPageSize 
)
static

Cache instruction page swap handler.

This callback will be called whenever a remapping takes place on a guest virtual page which has instructions cached. Whenever the page-table entry that maps a cache page is modified (except for A/D bits), the entire page will be invalidated, thus removing the instructions from the cache.

Parameters
[in]ContextThe invalidation entry associated with the remapped page.
[in]VirtualAddressThe guest virtual address that is being remapped.
[in]OldEntryOld page table entry associated with VirtualAddress.
[in]NewEntryNew page table entry associated with VirtualAddress.
[in]OldPageSizeOld page size (4K, 2M, 1G).
[in]NewPageSizeNew page size (4K, 2M, 1G).
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 364 of file icache.c.

Referenced by IntIcAddInvdForInstruction().

◆ IntIcWriteHandler()

static INTSTATUS IntIcWriteHandler ( INS_CACHE_INV_ENTRY const *  Context,
void const *  Hook,
QWORD  Address,
INTRO_ACTION Action 
)
static

Cached instruction page write handler.

This callback is called whenever writes take place inside a page that contains cached instruction. Upon writing such a page, all the instructions cached from this page will be removed from the cache. Note that we are OK with regard to 2M/4M pages, because inside the HV, only 4K pages are considered. Therefore, for a 2M page, there would be separate entries & hooks for each 4K HPA page.

Parameters
[in]ContextThe optional hook context, which in this case, represents the invalidation entry.
[in]HookThe hook handle.
[in]AddressThe written guest physical address.
[out]ActionWill always be set on introGuestAllowed, in order to allow the write.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 306 of file icache.c.

Referenced by IntIcAddInvdForInstruction().