rewrite comments into one, unified style
This commit is contained in:
1 parent
6260de0085
commit
467a58c9c6
163 files changed
+3560
-2556
No files matched your search
+81
-46
@@ -1,14 +1,14 @@
|
||||
// mm_virt.c - virtual memory manager
|
||||
//
|
||||
// Kernel virtual-memory manager. This file owns kernel page-table construction, mapping attributes, and direct-map maintenance.
|
||||
|
||||
// Page tables:
|
||||
// One PML4 shared by all processes.
|
||||
// Upper half (bit 47 set) has U/S = 0 - ring-3 access always faults.
|
||||
// Lower half pages are PAGE_USER.
|
||||
//
|
||||
|
||||
// Kernel pool:
|
||||
// A boundary-tag (header + footer) free-list allocator starting at POOL_BASE.
|
||||
// Pages are committed on demand from the PMM.
|
||||
//
|
||||
|
||||
// User heap:
|
||||
// A single best-fit free list in the lower half.
|
||||
// Page-granular lower-half regions owned by PROCESS metadata. Sub-page
|
||||
@@ -24,21 +24,19 @@
|
||||
#include <kernel/ke_irql.h>
|
||||
#include <kernel/hal/hal_apic.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers - physical window access
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers - physical window access.
|
||||
static uint64_t gPhysBase = PHYS_MAP_BASE;
|
||||
|
||||
// Implements the phys To Virt operation.
|
||||
static inline void* KiPhysToVirt(PHYSICAL_ADDRESS p) {
|
||||
return (void *)(p + gPhysBase);
|
||||
}
|
||||
// Implements the pte Ptr operation.
|
||||
static inline uint64_t* KiPtePtr(PHYSICAL_ADDRESS tablePhys, unsigned idx) {
|
||||
return (uint64_t *)KiPhysToVirt(tablePhys) + idx;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// PML4 / page-table helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
// PML4 / page-table helpers.
|
||||
static PHYSICAL_ADDRESS gPml4Phys = 0;
|
||||
static SPINLOCK gPageTableLock = SPINLOCK_INIT;
|
||||
|
||||
@@ -78,13 +76,12 @@ static PHYSICAL_ADDRESS KiEnsureTable(PHYSICAL_ADDRESS parentPhys,
|
||||
return childPhys;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// TLB/cache coherency hooks
|
||||
// ---------------------------------------------------------------------------
|
||||
// TLB/cache coherency hooks.
|
||||
void MmFlushTlbLocal(uintptr_t virt) {
|
||||
__invlpg((void*)virt);
|
||||
}
|
||||
|
||||
// Implements the acquire Tlb Shootdown Lock operation.
|
||||
static void KiAcquireTlbShootdownLock(void) {
|
||||
// Do not use the normal spinlock here: it masks interrupts while spinning.
|
||||
// A CPU spinning with IF=0 on the shootdown lock could not acknowledge a
|
||||
@@ -95,11 +92,13 @@ static void KiAcquireTlbShootdownLock(void) {
|
||||
_ReadWriteBarrier();
|
||||
}
|
||||
|
||||
// Releases tlb Shootdown Lock.
|
||||
static void KiReleaseTlbShootdownLock(void) {
|
||||
_ReadWriteBarrier();
|
||||
_InterlockedExchange(&gTlbShootdownLock, 0);
|
||||
}
|
||||
|
||||
// Flushes tlb For Kernel Mapping.
|
||||
void MmFlushTlbForKernelMapping(uintptr_t virt) {
|
||||
MmFlushTlbLocal(virt);
|
||||
|
||||
@@ -146,6 +145,7 @@ void MmFlushTlbForKernelMapping(uintptr_t virt) {
|
||||
}
|
||||
}
|
||||
|
||||
// Handles tlb Shootdown.
|
||||
static int KiHandleTlbShootdown(void) {
|
||||
if (_InterlockedCompareExchange(&gTlbShootdownActive, 0, 0) == 0)
|
||||
return 0;
|
||||
@@ -158,13 +158,12 @@ static int KiHandleTlbShootdown(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Handles tlb Shootdown Nmi.
|
||||
int MmHandleTlbShootdownNmi(void) {
|
||||
return KiHandleTlbShootdown();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public mapping
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public mapping.
|
||||
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags, MM_MAP_MODE mode) {
|
||||
unsigned userFlag = (flags & PAGE_USER) ? PAGE_USER : 0;
|
||||
|
||||
@@ -199,6 +198,7 @@ __declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, u
|
||||
}
|
||||
|
||||
|
||||
// Releases page.
|
||||
__declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt) {
|
||||
uintptr_t lockFlags = KeAcquireSpinlock(&gPageTableLock);
|
||||
|
||||
@@ -226,6 +226,7 @@ __declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt) {
|
||||
}
|
||||
|
||||
|
||||
// Changes page attributes for 4 KiB mappings and refuses huge-page leaves that cannot be edited in place.
|
||||
__declspec(dllexport) KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags) {
|
||||
if (!size) return STATUS_SUCCESS;
|
||||
|
||||
@@ -282,6 +283,7 @@ __declspec(dllexport) KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint
|
||||
}
|
||||
|
||||
|
||||
// Returns physical Address.
|
||||
__declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) {
|
||||
if (!gPml4Phys) return 0; // Not initialized
|
||||
|
||||
@@ -299,7 +301,7 @@ __declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) {
|
||||
uint64_t* pdpt = KiPhysToVirt(pml4[pml4_idx] & PAGE_FRAME_4K_MASK);
|
||||
if (!(pdpt[pdpt_idx] & PAGE_PRESENT)) goto out;
|
||||
|
||||
// Check for 1GB huge pages (bit 7 - PS)
|
||||
// Check for 1GB huge pages (bit 7 - PS).
|
||||
if (pdpt[pdpt_idx] & PAGE_PS) {
|
||||
result = (pdpt[pdpt_idx] & PAGE_FRAME_1G_MASK) + (virt & 0x3FFFFFFF);
|
||||
goto out;
|
||||
@@ -308,7 +310,7 @@ __declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) {
|
||||
uint64_t* pd = KiPhysToVirt(pdpt[pdpt_idx] & PAGE_FRAME_4K_MASK);
|
||||
if (!(pd[pd_idx] & PAGE_PRESENT)) goto out;
|
||||
|
||||
// Check for 2MB huge pages (bit 7 - PS)
|
||||
// Check for 2MB huge pages (bit 7 - PS).
|
||||
if (pd[pd_idx] & PAGE_PS) {
|
||||
result = (pd[pd_idx] & PAGE_FRAME_2M_MASK) + (virt & 0x1FFFFF);
|
||||
goto out;
|
||||
@@ -317,7 +319,7 @@ __declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) {
|
||||
uint64_t* pt = KiPhysToVirt(pd[pd_idx] & PAGE_FRAME_4K_MASK);
|
||||
if (!(pt[pt_idx] & PAGE_PRESENT)) goto out;
|
||||
|
||||
// Extract the physical frame and add the offset within the page
|
||||
// Extract the physical frame and add the offset within the page.
|
||||
result = (pt[pt_idx] & PAGE_FRAME_4K_MASK) + (virt & 0xFFF);
|
||||
|
||||
out:
|
||||
@@ -327,9 +329,7 @@ out:
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Page query and user/kernel copy boundary helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
// Page query and user/kernel copy boundary helpers.
|
||||
__declspec(dllexport) KSTATUS MmQueryPage(uintptr_t virt,
|
||||
PHYSICAL_ADDRESS* physOut,
|
||||
uint64_t* flagsOut) {
|
||||
@@ -409,6 +409,7 @@ out:
|
||||
}
|
||||
|
||||
|
||||
// Implements the user Range Valid operation.
|
||||
static int KiUserRangeValid(uintptr_t addr, size_t size) {
|
||||
if (size == 0) return 1;
|
||||
if (addr < USER_BASE) return 0;
|
||||
@@ -417,6 +418,7 @@ static int KiUserRangeValid(uintptr_t addr, size_t size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Probes user Range.
|
||||
static KSTATUS KiProbeUserRange(uintptr_t addr, size_t size, uint64_t requiredFlags) {
|
||||
if (!KiUserRangeValid(addr, size))
|
||||
return STATUS_ACCESS_DENIED;
|
||||
@@ -442,14 +444,17 @@ static KSTATUS KiProbeUserRange(uintptr_t addr, size_t size, uint64_t requiredFl
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Probes user Read.
|
||||
__declspec(dllexport) KSTATUS MmProbeUserRead(const void* ptr, size_t size) {
|
||||
return KiProbeUserRange((uintptr_t)ptr, size, PAGE_PRESENT | PAGE_USER);
|
||||
}
|
||||
|
||||
// Probes user Write.
|
||||
__declspec(dllexport) KSTATUS MmProbeUserWrite(void* ptr, size_t size) {
|
||||
return KiProbeUserRange((uintptr_t)ptr, size, PAGE_PRESENT | PAGE_USER | PAGE_WRITE);
|
||||
}
|
||||
|
||||
// Copies from User.
|
||||
__declspec(dllexport) KSTATUS CopyFromUser(void* kernelDst, const void* userSrc, size_t size) {
|
||||
if (!kernelDst && size) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
@@ -460,6 +465,7 @@ __declspec(dllexport) KSTATUS CopyFromUser(void* kernelDst, const void* userSrc,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Copies to User.
|
||||
__declspec(dllexport) KSTATUS CopyToUser(void* userDst, const void* kernelSrc, size_t size) {
|
||||
if (!kernelSrc && size) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
@@ -470,9 +476,7 @@ __declspec(dllexport) KSTATUS CopyToUser(void* userDst, const void* kernelSrc, s
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Boundary-tag allocator (used for both pool and user heap)
|
||||
// ---------------------------------------------------------------------------
|
||||
// Each allocation has a BLOCK_HDR immediately before the user data, and a
|
||||
// BLOCK_FTR immediately after. Both carry the block size and a 'free' flag.
|
||||
// This allows O(1) coalescing of adjacent free blocks.
|
||||
@@ -498,15 +502,19 @@ typedef struct BLOCK_FTR {
|
||||
#define OVERHEAD (HDR_SIZE + FTR_SIZE)
|
||||
#define MIN_BLOCK (OVERHEAD + sizeof(void*))
|
||||
|
||||
// Implements the hdr To Ftr operation.
|
||||
static inline BLOCK_FTR* KiHdrToFtr(BLOCK_HDR* h) {
|
||||
return (BLOCK_FTR *)((char *)h + HDR_SIZE + h->Size);
|
||||
}
|
||||
// Implements the ftr To Hdr operation.
|
||||
static inline BLOCK_HDR* KiFtrToHdr(BLOCK_FTR* f) {
|
||||
return (BLOCK_HDR *)((char *)f - HDR_SIZE - f->Size);
|
||||
}
|
||||
// Implements the next Block operation.
|
||||
static inline BLOCK_HDR* KiNextBlock(BLOCK_HDR* h) {
|
||||
return (BLOCK_HDR *)((char *)h + HDR_SIZE + h->Size + FTR_SIZE);
|
||||
}
|
||||
// Implements the prev Ftr operation.
|
||||
static inline BLOCK_FTR* KiPrevFtr(BLOCK_HDR* h) {
|
||||
return (BLOCK_FTR *)((char *)h - FTR_SIZE);
|
||||
}
|
||||
@@ -520,6 +528,7 @@ typedef struct HEAP {
|
||||
SPINLOCK Lock;
|
||||
} HEAP;
|
||||
|
||||
// Implements the heap Ensure Mapped operation.
|
||||
static int KiHeapEnsureMapped(HEAP* h, uintptr_t start, size_t size) {
|
||||
if (!h || !size) return 1;
|
||||
if (start < h->Start) return 0;
|
||||
@@ -592,6 +601,7 @@ static void KiFreeListRemove(HEAP* h, BLOCK_HDR* blk) {
|
||||
blk->PrevFree = blk->NextFree = (BLOCK_HDR *)0;
|
||||
}
|
||||
|
||||
// Implements the heap Try Decommit Tail operation.
|
||||
static void KiHeapTryDecommitTail(HEAP* h, BLOCK_HDR* blk) {
|
||||
(void)h;
|
||||
if (!blk || blk->Free == 0) return;
|
||||
@@ -607,6 +617,7 @@ static void KiHeapTryDecommitTail(HEAP* h, BLOCK_HDR* blk) {
|
||||
KiHdrToFtr(blk)->Free = 1;
|
||||
}
|
||||
|
||||
// Implements the heap Alloc operation.
|
||||
static void* KiHeapAlloc(HEAP* h, size_t size) {
|
||||
if (!size) return (void *)0;
|
||||
size = (size + 7) & ~7ULL; // 8-byte align
|
||||
@@ -670,6 +681,7 @@ static void* KiHeapAlloc(HEAP* h, size_t size) {
|
||||
return (char *)best + HDR_SIZE;
|
||||
}
|
||||
|
||||
// Implements the heap Free operation.
|
||||
static void KiHeapFree(HEAP* h, void* ptr) {
|
||||
if (!ptr) return;
|
||||
BLOCK_HDR* blk = (BLOCK_HDR *)((char *)ptr - HDR_SIZE);
|
||||
@@ -717,27 +729,28 @@ static void KiHeapFree(HEAP* h, void* ptr) {
|
||||
KeReleaseSpinlock(&h->Lock, flags);
|
||||
}
|
||||
|
||||
// Implements the heap Realloc operation.
|
||||
static void* KiHeapRealloc(HEAP* h, void* ptr, size_t new_size) {
|
||||
// If ptr is NULL, realloc acts like malloc
|
||||
// If ptr is NULL, realloc acts like malloc.
|
||||
if (!ptr) {
|
||||
return KiHeapAlloc(h, new_size);
|
||||
}
|
||||
|
||||
// If size is 0, realloc acts like free
|
||||
// If size is 0, realloc acts like free.
|
||||
if (new_size == 0) {
|
||||
KiHeapFree(h, ptr);
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
// Retrieve the header of the existing block
|
||||
// Retrieve the header of the existing block.
|
||||
BLOCK_HDR* blk = (BLOCK_HDR *)((char *)ptr - HDR_SIZE);
|
||||
|
||||
// Sanity checks to prevent operating on corrupted or already-freed pointers
|
||||
// Sanity checks to prevent operating on corrupted or already-freed pointers.
|
||||
if (blk->Magic != BLOCK_MAGIC || blk->Free) {
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
// Align the requested size (matches KiHeapAlloc 8-byte alignment)
|
||||
// Align the requested size (matches KiHeapAlloc 8-byte alignment).
|
||||
size_t aligned_size = (new_size + 7) & ~7ULL;
|
||||
|
||||
// If the current block is already big enough, we can reuse it in-place.
|
||||
@@ -758,20 +771,16 @@ static void* KiHeapRealloc(HEAP* h, void* ptr, size_t new_size) {
|
||||
// We only copy up to the old block's usable size.
|
||||
memcpy(new_ptr, ptr, blk->Size);
|
||||
|
||||
// Free the old block
|
||||
// Free the old block.
|
||||
KiHeapFree(h, ptr);
|
||||
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Kernel pool
|
||||
// ---------------------------------------------------------------------------
|
||||
// Kernel pool.
|
||||
static HEAP gPoolHeap;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// User virtual region arena
|
||||
// ---------------------------------------------------------------------------
|
||||
// User virtual region arena.
|
||||
typedef struct USER_VA_REGION {
|
||||
LIST_ENTRY ProcessLink;
|
||||
LIST_ENTRY GlobalLink;
|
||||
@@ -794,9 +803,7 @@ static int gUserRegionListReady = 0;
|
||||
|
||||
#define USER_REGION_ARENA_BASE 0x0000100000000000ULL
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Module init
|
||||
// ---------------------------------------------------------------------------
|
||||
// Module init.
|
||||
void MmInitializeVirtual(PHYSICAL_ADDRESS bootPml4Phys, size_t poolSize) {
|
||||
gPml4Phys = bootPml4Phys;
|
||||
gPageTableLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
@@ -822,38 +829,40 @@ void MmInitializeVirtual(PHYSICAL_ADDRESS bootPml4Phys, size_t poolSize) {
|
||||
gUserRegionListReady = 1;
|
||||
}
|
||||
|
||||
// Implements the activate operation.
|
||||
void MmActivate(void) {
|
||||
__writecr3(gPml4Phys);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public pool API
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public pool API.
|
||||
__declspec(dllexport) void* MmAllocatePool(size_t size) { return KiHeapAlloc(&gPoolHeap, size); }
|
||||
// Releases pool.
|
||||
__declspec(dllexport) void MmFreePool(void* ptr) { KiHeapFree(&gPoolHeap, ptr); }
|
||||
// Implements the reallocate Pool operation.
|
||||
__declspec(dllexport) void* MmReallocatePool(void* ptr, size_t newSize) { return KiHeapRealloc(&gPoolHeap, ptr, newSize); }
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// User virtual region API
|
||||
// ---------------------------------------------------------------------------
|
||||
// User virtual region API.
|
||||
static inline uintptr_t KiAlignUpPtr(uintptr_t v, size_t align) {
|
||||
if (align < PAGE_SIZE) align = PAGE_SIZE;
|
||||
if (align & (align - 1)) return 0;
|
||||
return (v + (uintptr_t)align - 1) & ~((uintptr_t)align - 1);
|
||||
}
|
||||
|
||||
// Implements the align Up Size operation.
|
||||
static inline size_t KiAlignUpSize(size_t v, size_t align) {
|
||||
if (align < PAGE_SIZE) align = PAGE_SIZE;
|
||||
if (align & (align - 1)) return 0;
|
||||
return (v + align - 1) & ~(align - 1);
|
||||
}
|
||||
|
||||
// Implements the ranges Overlap operation.
|
||||
static int KiRangesOverlap(uintptr_t aBase, size_t aSize, uintptr_t bBase, size_t bSize) {
|
||||
uintptr_t aEnd = aBase + aSize;
|
||||
uintptr_t bEnd = bBase + bSize;
|
||||
return aBase < bEnd && bBase < aEnd;
|
||||
}
|
||||
|
||||
// Returns user Va Range.
|
||||
static KSTATUS KiFindUserVaRange(size_t reservationSize, size_t alignment, uintptr_t* baseOut) {
|
||||
if (!baseOut || !reservationSize) return STATUS_INVALID_PARAMETER;
|
||||
if (!gUserRegionListReady) return STATUS_FAILURE;
|
||||
@@ -887,6 +896,7 @@ static KSTATUS KiFindUserVaRange(size_t reservationSize, size_t alignment, uintp
|
||||
}
|
||||
}
|
||||
|
||||
// Returns user Region Locked.
|
||||
static USER_VA_REGION* KiFindUserRegionLocked(PROCESS* process, const void* base) {
|
||||
if (!process || !base) return (USER_VA_REGION*)0;
|
||||
uintptr_t b = (uintptr_t)base;
|
||||
@@ -897,6 +907,7 @@ static USER_VA_REGION* KiFindUserRegionLocked(PROCESS* process, const void* base
|
||||
return (USER_VA_REGION*)0;
|
||||
}
|
||||
|
||||
// Returns user Region Containing Locked.
|
||||
static USER_VA_REGION* KiFindUserRegionContainingLocked(PROCESS* process, uintptr_t base, size_t size) {
|
||||
if (!process || !base || !size) return (USER_VA_REGION*)0;
|
||||
if (base > (uintptr_t)-1 - (size - 1)) return (USER_VA_REGION*)0;
|
||||
@@ -910,6 +921,7 @@ static USER_VA_REGION* KiFindUserRegionContainingLocked(PROCESS* process, uintpt
|
||||
return (USER_VA_REGION*)0;
|
||||
}
|
||||
|
||||
// Releases user Region Payload.
|
||||
static void KiUnmapUserRegionPayload(USER_VA_REGION* r) {
|
||||
if (!r) return;
|
||||
uintptr_t end = r->Base + r->CommittedSize;
|
||||
@@ -1007,6 +1019,7 @@ KSTATUS MmCreateUserRegion(PROCESS* process, size_t size, size_t alignment,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the ensure User Region Mapped operation.
|
||||
KSTATUS MmEnsureUserRegionMapped(PROCESS* process, void* base, size_t size, uint64_t pageFlags) {
|
||||
KeAssertIrql(PASSIVE_LEVEL);
|
||||
if (!process || !base || !size) return STATUS_INVALID_PARAMETER;
|
||||
@@ -1061,6 +1074,7 @@ KSTATUS MmEnsureUserRegionMapped(PROCESS* process, void* base, size_t size, uint
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the protect User Region operation.
|
||||
KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t pageFlags) {
|
||||
KeAssertIrql(PASSIVE_LEVEL);
|
||||
if (!process || !base || !size) return STATUS_INVALID_PARAMETER;
|
||||
@@ -1143,6 +1157,7 @@ KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases user Region.
|
||||
KSTATUS MmDestroyUserRegion(PROCESS* process, void* base) {
|
||||
KeAssertIrql(PASSIVE_LEVEL);
|
||||
if (!process || !base) return STATUS_INVALID_PARAMETER;
|
||||
@@ -1165,6 +1180,7 @@ KSTATUS MmDestroyUserRegion(PROCESS* process, void* base) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Releases all User Regions.
|
||||
void MmDestroyAllUserRegions(PROCESS* process) {
|
||||
KeAssertIrql(PASSIVE_LEVEL);
|
||||
if (!process) return;
|
||||
@@ -1213,6 +1229,7 @@ KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut,
|
||||
}
|
||||
|
||||
|
||||
// Returns process User Memory.
|
||||
void MmQueryProcessUserMemory(PROCESS* process, size_t* regionCountOut, size_t* reservedBytesOut, size_t* committedBytesOut) {
|
||||
size_t regions = 0;
|
||||
size_t reserved = 0;
|
||||
@@ -1234,6 +1251,7 @@ void MmQueryProcessUserMemory(PROCESS* process, size_t* regionCountOut, size_t*
|
||||
if (committedBytesOut) *committedBytesOut = committed;
|
||||
}
|
||||
|
||||
// Returns user Region Size.
|
||||
size_t MmGetUserRegionSize(PROCESS* process, const void* base) {
|
||||
if (!process || !base) return 0;
|
||||
uintptr_t procFlags = KeAcquireSpinlock(&process->UserRegionLock);
|
||||
@@ -1243,6 +1261,7 @@ size_t MmGetUserRegionSize(PROCESS* process, const void* base) {
|
||||
return size;
|
||||
}
|
||||
|
||||
// Returns user Region Size By Base.
|
||||
size_t MmGetUserRegionSizeByBase(const void* base) {
|
||||
if (!base) return 0;
|
||||
uintptr_t b = (uintptr_t)base;
|
||||
@@ -1260,6 +1279,7 @@ size_t MmGetUserRegionSizeByBase(const void* base) {
|
||||
}
|
||||
|
||||
|
||||
// Implements the user Region Type Name operation.
|
||||
static const char* KiUserRegionTypeName(USER_REGION_TYPE type) {
|
||||
switch (type) {
|
||||
case UserRegionGeneric: return "generic";
|
||||
@@ -1275,6 +1295,7 @@ static const char* KiUserRegionTypeName(USER_REGION_TYPE type) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the debug Dump User Regions operation.
|
||||
void MmDebugDumpUserRegions(PROCESS* process) {
|
||||
if (!process) {
|
||||
DbgPrint("MM: user regions: <no process>\n");
|
||||
@@ -1302,6 +1323,7 @@ void MmDebugDumpUserRegions(PROCESS* process) {
|
||||
if (!count) DbgPrint(" <none>\n");
|
||||
}
|
||||
|
||||
// Implements the debug Describe Pool Address operation.
|
||||
static void KiDebugDescribePoolAddress(uintptr_t addr) {
|
||||
DbgPrint("MM: kernel pool start=%016llx brk=%016llx limit=%016llx usage=%llu KiB\n",
|
||||
(unsigned long long)gPoolHeap.Start,
|
||||
@@ -1347,6 +1369,7 @@ static void KiDebugDescribePoolAddress(uintptr_t addr) {
|
||||
KeReleaseSpinlock(&gPoolHeap.Lock, flags);
|
||||
}
|
||||
|
||||
// Implements the debug Describe Address operation.
|
||||
void MmDebugDescribeAddress(uintptr_t addr) {
|
||||
PHYSICAL_ADDRESS phys = 0;
|
||||
uint64_t flags = 0;
|
||||
@@ -1385,6 +1408,7 @@ void MmDebugDescribeAddress(uintptr_t addr) {
|
||||
}
|
||||
}
|
||||
|
||||
// Creates user Memory For Process.
|
||||
__declspec(dllexport) void* MmAllocateUserMemoryForProcess(PROCESS* process, size_t size) {
|
||||
void* base = (void*)0;
|
||||
if (!process || !size) return (void*)0;
|
||||
@@ -1396,11 +1420,13 @@ __declspec(dllexport) void* MmAllocateUserMemoryForProcess(PROCESS* process, siz
|
||||
return KSUCCESS(s) ? base : (void*)0;
|
||||
}
|
||||
|
||||
// Releases user Memory For Process.
|
||||
__declspec(dllexport) void MmFreeUserMemoryForProcess(PROCESS* process, void* ptr) {
|
||||
if (!process || !ptr) return;
|
||||
(void)MmDestroyUserRegion(process, ptr);
|
||||
}
|
||||
|
||||
// Implements the reallocate User Memory For Process operation.
|
||||
__declspec(dllexport) void* MmReallocateUserMemoryForProcess(PROCESS* process, void* ptr, size_t newSize) {
|
||||
if (!process) return (void*)0;
|
||||
if (!ptr) return MmAllocateUserMemoryForProcess(process, newSize);
|
||||
@@ -1420,21 +1446,25 @@ __declspec(dllexport) void* MmReallocateUserMemoryForProcess(PROCESS* process, v
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
// Creates user Memory.
|
||||
__declspec(dllexport) void* MmAllocateUserMemory(size_t size) {
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
return MmAllocateUserMemoryForProcess(process, size);
|
||||
}
|
||||
|
||||
// Releases user Memory.
|
||||
__declspec(dllexport) void MmFreeUserMemory(void* ptr) {
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
MmFreeUserMemoryForProcess(process, ptr);
|
||||
}
|
||||
|
||||
// Implements the reallocate User Memory operation.
|
||||
__declspec(dllexport) void* MmReallocateUserMemory(void* ptr, size_t newSize) {
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
return MmReallocateUserMemoryForProcess(process, ptr, newSize);
|
||||
}
|
||||
|
||||
// Creates user Image For Process.
|
||||
__declspec(dllexport) void* MmAllocateUserImageForProcess(PROCESS* process, size_t size) {
|
||||
void* base = (void*)0;
|
||||
if (!process || !size) return (void*)0;
|
||||
@@ -1446,27 +1476,32 @@ __declspec(dllexport) void* MmAllocateUserImageForProcess(PROCESS* process, size
|
||||
return KSUCCESS(s) ? base : (void*)0;
|
||||
}
|
||||
|
||||
// Releases user Image For Process.
|
||||
__declspec(dllexport) void MmFreeUserImageForProcess(PROCESS* process, void* ptr, size_t size) {
|
||||
(void)size;
|
||||
if (!process || !ptr) return;
|
||||
(void)MmDestroyUserRegion(process, ptr);
|
||||
}
|
||||
|
||||
// Creates user Image.
|
||||
__declspec(dllexport) void* MmAllocateUserImage(size_t size) {
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
return MmAllocateUserImageForProcess(process, size);
|
||||
}
|
||||
|
||||
// Releases user Image.
|
||||
__declspec(dllexport) void MmFreeUserImage(void* ptr, size_t size) {
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
MmFreeUserImageForProcess(process, ptr, size);
|
||||
}
|
||||
|
||||
// Returns kernel Pool Usage.
|
||||
size_t MmGetKernelPoolUsage(void) {
|
||||
// Returns bytes committed to the kernel pool
|
||||
// Returns bytes committed to the kernel pool.
|
||||
return (size_t)(gPoolHeap.Brk - gPoolHeap.Start);
|
||||
}
|
||||
|
||||
// Returns user Heap Usage.
|
||||
size_t MmGetUserHeapUsage(void) {
|
||||
size_t total = 0;
|
||||
if (!gUserRegionListReady) return 0;
|
||||
|
||||
Reference in new issue
Block a user