vmread-sys 0.1.5

Raw FFI bindings to vmread
Documentation
#ifndef MEM_H
#define MEM_H

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @file mem.h
 * @brief Defines memory operations
 *
 * Provides all necessary methods to read and write memory in a VM
 */

#include "definitions.h"

#define PAGE_OFFSET_SIZE 12

#define MAX_BATCHED_RW 1024

typedef struct RWInfo
{
	uint64_t local;
	uint64_t remote;
	size_t size;
} RWInfo;

typedef struct {
	size_t tlbHits;
	size_t tlbMisses;
} tlb_t;

/**
 * @brief Read a piece of data in physical VM address space
 *
 * @param data VM process data
 * @param local local data address
 * @param remote remote data address
 * @param size size of data
 *
 * @return
 * Data moved on success;
 * -1 otherwise
 */
ssize_t MemRead(const ProcessData* data, uint64_t local, uint64_t remote, size_t size);

/**
 * @brief Write a piece of data in physical VM address space
 *
 * @param data VM process data
 * @param local local data address
 * @param remote remote data address
 * @param size size of data
 *
 * @return
 * Data moved on success;
 * -1 otherwise
 */
ssize_t MemWrite(const ProcessData* data, uint64_t local, uint64_t remote, size_t size);

/**
 * @brief Read multiple pieces of data in physical VM address space
 *
 * @param data VM process data
 * @param info list of information for RW operations
 * @param num number of info atoms
 *
 * @return
 * Data moved on success;
 * -1 otherwise
 */
ssize_t MemReadMul(const ProcessData* data, RWInfo* info, size_t num);

/**
 * @brief Write multiple pieces of data in physical VM address space
 *
 * @param data VM process data
 * @param info list of information for RW operations
 * @param num number of info atoms
 *
 * @return
 * Data moved on success;
 * -1 otherwise
 */
ssize_t MemWriteMul(const ProcessData* data, RWInfo* info, size_t num);

/**
 * @brief Read a unsigned 64-bit integer in virtual VM address space
 *
 * @param data VM process data
 * @param dirBase page table directory base of a process
 * @param remote remote data address
 *
 * @return
 * Read value, undefined on failure
 */
uint64_t VMemReadU64(const ProcessData* data, uint64_t dirBase, uint64_t remote);

/**
 * @brief Write a unsigned 64-bit integer in virtual VM address space
 *
 * @param data VM process data
 * @param dirBase page table directory base of a process
 * @param remote remote data address
 * @param value value to be written
 *
 * @return
 * 8 on success;
 * -1 on failure
 */
ssize_t VMemWriteU64(const ProcessData* data, uint64_t dirBase, uint64_t remote, uint64_t value);

/**
 * @brief Read a unsigned 64-bit integer in physical VM address space
 *
 * @param data VM process data
 * @param remote remote data address
 *
 * @return
 * Read value, undefined on failure
 */
uint64_t MemReadU64(const ProcessData* data, uint64_t remote);

/**
 * @brief Write a unsigned 64-bit integer in physical VM address space
 *
 * @param data VM process data
 * @param remote remote data address
 * @param value value to be written
 *
 * @return
 * 8 on success;
 * -1 on failure
 */
ssize_t MemWriteU64(const ProcessData* data, uint64_t remote, uint64_t value);

/**
 * @brief Read data in virtual VM address space
 *
 * @param data VM process data
 * @param dirBase page table directory base of a process
 * @param local local data address
 * @param remote remote data address
 * @param size size of data
 *
 * @return
 * Data moved on success;
 * -1 otherwise
 */
ssize_t VMemRead(const ProcessData* data, uint64_t dirBase, uint64_t local, uint64_t remote, size_t size);

/**
 * @brief Write data in virtual addresss space
 *
 * @param data VM process data
 * @param dirBase page table directory base of a process
 * @param local local data address
 * @param remote remote data address
 * @param size size of data
 *
 * @return
 * Data moved on success;
 * -1 otherwise
 */
ssize_t VMemWrite(const ProcessData* data, uint64_t dirBase, uint64_t local, uint64_t remote, size_t size);

/**
 * @brief Read multiple pieces of data in virtual VM address space
 *
 * @param data VM process data
 * @param dirBase page table directory base of a process
 * @param info list of information for RW operations
 * @param num number of info atoms
 *
 * @return
 * Data moved on success;
 * -1 otherwise
 */
ssize_t VMemReadMul(const ProcessData* data, uint64_t dirBase, RWInfo* info, size_t num);

/**
 * @brief Write multiple pieces of data in virtual VM address space
 *
 * @param data VM process data
 * @param dirBase page table directory base of a process
 * @param info list of information for RW operations
 * @param num number of info atoms
 *
 * @return
 * Data moved on success;
 * -1 otherwise
 */
ssize_t VMemWriteMul(const ProcessData* data, uint64_t dirBase, RWInfo* info, size_t num);

/**
 * @brief Translate a virtual VM address into a physical one
 *
 * @param data VM process data
 * @param dirBase page table directory base of a process
 * @param address virtual address to translate
 *
 * @return
 * Translated linear address;
 * 0 otherwise
 */
uint64_t VTranslate(const ProcessData* data, uint64_t dirBase, uint64_t address);

/**
 * @brief Set translation cache validity time in msecs
 *
 * @param newTime new validity length for a cache entry
 *
 * Defines for how long translation caches (TLB and page buffer) should be valid. Higher values lead to higher
 * performance, but could potentially lead to incorrect translation if the page tables update in that period.
 * Especially dangerous if write operations are to be performed.
 */
void SetMemCacheTime(size_t newTime);

/**
 * @brief Get the default cache validity
 *
 * @return
 * Default cache validity time
 */
size_t GetDefaultMemCacheTime(void);

/**
 * @brief Retrieve current thread's TLB
 *
 * Memory TLB utilizes thread local storage to make the code concurrant. However, it might be beneficial to
 * access the TLB structure to verify its entries asynchronously during idle. This allows to access the
 * said TLB to do just that.
 *
 * @return
 * TLB of the running thread
 */
tlb_t* GetTlb(void);

/**
 * @brief Verify the TLB entries
 *
 * @param data VM process data
 * @param tlb TLB structure to verify
 * @param splitCount how many splits there are
 * @param splitID which slice to verify
 *
 * This allows to verify the TLB structure before initializing a round of memory operations. Useful when the
 * same memory addresses are being accessed in a loop with some delay. During the said delay we could verify
 * the TLB structure in (optionally) multithreaded way to make the memory operations fast.
 *
 * splitCount allows us to split the TLB entries to verify to separate threads. Passing 1 to splitCount makes
 * the function verify the entirety of TLB (single-threaded scenario)
 */
void VerifyTlb(const ProcessData* data, tlb_t* tlb, size_t splitCount, size_t splitID);

/**
 * @brief Flush all TLB entries
 *
 * @param tlb TLB structure to flush
 *
 */
void FlushTlb(tlb_t* tlb);

#ifdef __cplusplus
}
#endif

#endif