My Project
Loading...
Searching...
No Matches
vad.c
Go to the documentation of this file.
1/*++
2
3Module Name:
4
5 vad.c
6
7Purpose:
8
9 This translation unit contains the implementation of Virtual Address Descriptors (VADs) of the memory manager.
10
11Author:
12
13 slep (Matanel) 2025.
14
15Revision History:
16
17--*/
18
19// Dev notes: BST's left child are smaller than the node, and the right child is larger than the node (heavier)
20// So: LeftChild < Node < RightChild
21
22#include "../../includes/mm.h"
23#include "../../includes/ps.h"
24#include "../../assert.h"
25
27int
29 IN PMMVAD Node
30)
31
32/*++
33
34 Routine description:
35
36 This routine returns the current height of the VAD node (or -1)
37
38 Arguments:
39
40 Pointer to MMVAD Node.
41
42 Return Values:
43
44 Height of node, or -1 if invalid pointer. (0)
45
46--*/
47
48{
49 if (!Node) return -1;
50 return Node->Height;
51}
52
54void
56 IN PMMVAD Node
57)
58
59/*++
60
61 Routine description:
62
63 Updates the node's height based on its children.
64
65 Arguments:
66
67 Pointer to MMVAD Node.
68
69 Return Values:
70
71 None.
72
73--*/
74
75{
76 if (!Node) return;
77 Node->Height = 1 + MAX(MiGetNodeHeight(Node->LeftChild), MiGetNodeHeight(Node->RightChild));
78}
79
81int
83 IN PMMVAD Node
84)
85
86/*++
87
88 Routine description:
89
90 Calculates balance factor of node in the tree.
91
92 Arguments:
93
94 Pointer to MMVAD Node.
95
96 Return Values:
97
98 Return's the nodes balance factor.
99
100--*/
101
102{
103 if (!Node) return 0;
104 // balance factor is the (height of the right - height of the left)
105 return MiGetNodeHeight(Node->RightChild) - MiGetNodeHeight(Node->LeftChild);
106}
107
108static
109PMMVAD
110MiAllocateVad(
111 void
112)
113
114/*++
115
116 Routine description:
117
118 This routine allocates a VAD from the nonpaged pool and sets it up.
119
120 Arguments:
121
122 None.
123
124 Return Values:
125
126 Pointer to allocated VAD. NULL On failure.
127
128--*/
129
130{
131 // Allocate the VAD.
132 PMMVAD vad = (PMMVAD)MmAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD), ' daV'); // Little endian tag.
133 if (!vad) return NULL;
134
135 // Initialize to zero. (including height)
136 kmemset(vad, 0, sizeof(MMVAD));
137
138 return vad;
139}
140
141
142static
143void
144MiFreeVad(
145 IN PMMVAD Vad
146)
147
148/*++
149
150 Routine description:
151
152 Frees a VAD structure back to the non-paged pool.
153
154 Arguments:
155
156 Pointer to MMVAD Node.
157
158 Return Values:
159
160 None.
161
162--*/
163
164{
165 return MmFreePool((void*)Vad);
166}
167
168static
169PMMVAD
170MiRotateRight(
171 IN PMMVAD y
172)
173
174/*++
175 Routine description:
176 Performs a single right rotation on node y.
177
178 Before:
179 y
180 / \
181 x T3
182 / \
183 T1 T2
184
185 After:
186 x
187 / \
188 T1 y
189 / \
190 T2 T3
191
192 Return Values:
193
194 New root of subtree.
195--*/
196
197{
198 PMMVAD x = y->LeftChild;
199 PMMVAD T2 = x->RightChild;
200
201 // Perform rotation
202 x->RightChild = y;
203 y->LeftChild = T2;
204
205 // Update parent pointers
206 x->Parent = y->Parent;
207 y->Parent = x;
208 if (T2) T2->Parent = y;
209
210 // Update heights (update Y before X, since the function uses X)
213
214 // Return new root of subtree.
215 return x;
216}
217
218static
219PMMVAD
220MiRotateLeft(
221 IN PMMVAD x
222)
223
224/*++
225 Routine description:
226 Performs a single left rotation on node x.
227
228 Before:
229 x
230 / \
231 T1 y
232 / \
233 T2 T3
234
235 After:
236 y
237 / \
238 x T3
239 / \
240 T1 T2
241
242 Return Values:
243
244 New root of subtree.
245--*/
246
247{
248 PMMVAD y = x->RightChild;
249 PMMVAD T2 = y->LeftChild;
250
251 // Perform rotation
252 y->LeftChild = x;
253 x->RightChild = T2;
254
255 // Update parent pointers
256 y->Parent = x->Parent;
257 x->Parent = y;
258 if (T2) T2->Parent = x;
259
260 // Update heights (update X before Y, since the function uses Y)
263
264 // Return new root of subtree.
265 return y;
266}
267
268static
269PMMVAD
270MiFindMinimumVad(
271 IN PMMVAD Node
272)
273
274/*++
275
276 Routine description:
277
278 Finds the node with the minimum value (StartVa) in a given sub-tree.
279
280 Arguments:
281
282 Pointer to MMVAD Node.
283
284 Return Values:
285
286 None.
287
288--*/
289
290{
291 PMMVAD current = Node;
292 while (current && current->LeftChild != NULL) {
293 current = current->LeftChild;
294 }
295 return current;
296}
297
298static
299bool
300MiCheckVadOverlap(
301 IN PMMVAD Root,
302 IN uintptr_t StartVa,
303 IN uintptr_t EndVa
304)
305
306/*++
307
308 Routine description:
309
310 Checks if a proposed new VAD (defined by StartVA and EndVA) overlaps with any existing VADs in the tree.
311
312 Arguments:
313
314 Pointer to MMVAD Node.
315 Start Virtual Address.
316 Ending Virtual Address.
317
318 Return Values:
319
320 True if there is an overlap, false otherwise.
321
322--*/
323
324{
325 PMMVAD Node = Root;
326 while (Node) {
327 // Check for overlap
328 // A overlaps B if A.start < B.End AND > B.start
329 if (StartVa <= Node->EndVa && EndVa >= Node->StartVa) {
330 return true;
331 }
332
333 // If the new VAD is entirely before the current one
334 if (EndVa < Node->StartVa) {
335 Node = Node->LeftChild; // Only need to check left
336 }
337
338 // If the new VAD is entirely after the current one
339 else if (StartVa > Node->EndVa) {
340 Node = Node->RightChild; // Only need to check right
341 }
342
343 // Overlaps.
344 else {
345 return true;
346 }
347 }
348
349 // No overlap found.
350 return false;
351}
352
353PMMVAD
355 IN PMMVAD Root,
356 IN uintptr_t VirtualAddress
357)
358
359/*++
360
361 Routine description:
362
363 Finds a VAD that contains the given virtual address in it.
364
365 Arguments:
366
367 [IN] PMMVAD Root - Root of the VAD Tree of the process.
368 [IN] uintptr_t VirtualAddress - Virtual address to check for.
369
370 Return Values:
371
372 Returns the VAD if found, NULL otherwise.
373
374--*/
375
376{
377 PMMVAD current = Root;
378
379 while (current) {
380 // Is the virtual address BEFORE this VAD
381 if (VirtualAddress < current->StartVa) {
382 current = current->LeftChild;
383 }
384
385 // Is the virtual address AFTER this VAD
386 else if (VirtualAddress > current->EndVa) {
387 current = current->RightChild;
388 }
389
390 // Then, it must be inside of this VAD.
391 else return current;
392 }
393
394 // Not found.
395 return NULL;
396}
397
398static
399PMMVAD
400MiInsertVadNode(
401 IN PMMVAD Node,
402 IN PMMVAD NewVad
403)
404
405/*++
406
407 Routine description:
408
409 Inserts the NewVad into Node using AVL insert.
410
411 Arguments:
412
413 Node to insert to.
414 Vad to insert.
415
416 Return Values:
417
418 New root of subtree.
419
420--*/
421
422{
423 // Found the best spot to insert
424 if (!Node) return NewVad;
425
426 // Recursive step
427 if (NewVad->StartVa < Node->StartVa) {
428 PMMVAD newLeft = MiInsertVadNode(Node->LeftChild, NewVad);
429 Node->LeftChild = newLeft;
430 if (newLeft) newLeft->Parent = Node;
431 }
432 else {
433 // No duplicates or overlaps, the caller should handle that before calling.
434 PMMVAD newRight = MiInsertVadNode(Node->RightChild, NewVad);
435 Node->RightChild = newRight;
436 if (newRight) newRight->Parent = Node;
437 }
438
439 // Update height
440 MiUpdateNodeHeight(Node);
441
442 // Get balance, and rebalance the tree if needed.
443 int balance = MiGetBalanceFactor(Node);
444
445 // Left heavy tree
446 if (balance < -1) {
447 // Left left
448 if (NewVad->StartVa < Node->LeftChild->StartVa) {
449 return MiRotateRight(Node);
450 }
451 // Left right
452 else {
453 Node->LeftChild = MiRotateLeft(Node->LeftChild);
454 return MiRotateRight(Node);
455 }
456 }
457
458 // Right heavy tree
459 if (balance > 1) {
460 // Right right
461 if (NewVad->StartVa > Node->RightChild->StartVa) {
462 return MiRotateLeft(Node);
463 }
464 // Right left
465 else {
466 Node->RightChild = MiRotateRight(Node->RightChild);
467 return MiRotateLeft(Node);
468 }
469 }
470
471 // Return the (probably new) root of the this subtree.
472 return Node;
473}
474
475static
476PMMVAD
477MiDeleteVadNode(
478 IN PMMVAD Root,
479 IN PMMVAD VadToDelete
480)
481
482/*++
483
484 Routine description:
485
486 Delets VadToDelete from Root.
487
488 Arguments:
489
490 Root to delete from
491 Vad to delete.
492
493 Return Values:
494
495 New root of subtree.
496
497--*/
498
499{
500 if (Root == NULL) {
501 // Shouldn't happen if logic is correct.
502 return NULL;
503 }
504
505 // Find the node
506 if (VadToDelete->StartVa < Root->StartVa) {
507 Root->LeftChild = MiDeleteVadNode(Root->LeftChild, VadToDelete);
508 }
509 else if (VadToDelete->StartVa > Root->StartVa) {
510 Root->RightChild = MiDeleteVadNode(Root->RightChild, VadToDelete);
511 }
512 else {
513 // Node with 0 or 1 child.
514 if (Root->LeftChild == NULL || Root->RightChild == NULL) {
515 PMMVAD temp = Root->LeftChild ? Root->LeftChild : Root->RightChild;
516
517 // No childs.
518 if (!temp) {
519 // This node (root) is what we want to delete.
520 // We return NULL to our parent, who will set its child ptr to null. (and free it from memory)
521 return NULL;
522 }
523 // One child
524 else {
525 // The child takes our place.
526 temp->Parent = Root->Parent;
527 return temp; // Return the child to our parent.
528 }
529 }
530 // Node with 2 children
531 else {
532 PMMVAD successor = MiFindMinimumVad(Root->RightChild);
533
534 // Save Root's tree links
535 PMMVAD oldLeft = Root->LeftChild;
536 PMMVAD oldParent = Root->Parent;
537
538 // Copy all of successor's data (data + tree links)
539 kmemcpy(Root, successor, sizeof(MMVAD));
540
541 // Restore Root's original tree links
542 Root->LeftChild = oldLeft;
543 Root->Parent = oldParent;
544
545 // Update parent pointers for Root's children
546 if (Root->LeftChild) Root->LeftChild->Parent = Root;
547 if (Root->RightChild) Root->RightChild->Parent = Root; // successor's right
548
549 // Now delete the original successor
550 Root->RightChild = MiDeleteVadNode(Root->RightChild, successor);
551 }
552 }
553
554 // Update height.
555 MiUpdateNodeHeight(Root);
556
557 // Get balance and rebalance if needed.
558 int balance = MiGetBalanceFactor(Root);
559
560 // Left Heavy
561 if (balance < -1) {
562 // Left-Left
563 if (MiGetBalanceFactor(Root->LeftChild) <= 0) {
564 return MiRotateRight(Root);
565 }
566 // Left-Right
567 else {
568 Root->LeftChild = MiRotateLeft(Root->LeftChild);
569 return MiRotateRight(Root);
570 }
571 }
572
573 // Right Heavy
574 if (balance > 1) {
575 // Right-Right
576 if (MiGetBalanceFactor(Root->RightChild) >= 0) {
577 return MiRotateLeft(Root);
578 }
579 // Right-Left
580 else {
581 Root->RightChild = MiRotateRight(Root->RightChild);
582 return MiRotateLeft(Root);
583 }
584 }
585
586 return Root;
587}
588
589#define MAX_VAD_DEPTH 64 // Usually enough for a 64-bit tree
591int stackTop = -1;
592
593static
594uintptr_t
595MiFindGap(
596 IN PMMVAD Root,
597 IN size_t NumberOfBytes,
598 IN uintptr_t SearchStart,
599 IN uintptr_t SearchEnd // exclusive
600)
601
602/*++
603
604 Routine description:
605
606 Finds a VA gap in the VAD Tree using an iterative in-order traversal. (does NOT claim the gap)
607
608 Arguments:
609
610 [IN] PMMVAD Root - The ROOT of the VAD Tree.
611 [IN] size_t NumberOfBytes - The size of the gap needed.
612 [IN] uintptr_t SearchStart - Inclusive start of the search range.
613 [IN] uintptr_t SearchEnd - Exclusive end of the search range.
614
615 Return Values:
616
617 Start of VA that has enough bytes for 'size'. 0 If gap isn't found.
618
619--*/
620{
621 if (SearchStart >= SearchEnd) return 0; // invalid range
622 if (NumberOfBytes == 0) return 0; // no zero-sized allocations
623 if (SearchStart == 0) return 0; // defensive: we don't expect VA 0
624
625 PMMVAD current = Root;
626 size_t size_needed = ALIGN_UP(NumberOfBytes, VirtualPageSize);
627
628 // Start from one byte before SearchStart so ALIGN_UP(lastEndVa + 1, page) == aligned SearchStart
629 uintptr_t lastEndVa = SearchStart - 1;
630
631 stackTop = -1; // Reset stack (you already use this global stack)
632
633 while (current != NULL || stackTop != -1) {
634 // Go all the way left, pushing nodes onto the stack
635 while (current != NULL) {
636 if (stackTop + 1 >= MAX_VAD_DEPTH) {
637 // Tree is too deep (shouldn't happen if we balanced it though)
638 return 0;
639 }
640 vadStack[++stackTop] = current;
641 current = current->LeftChild;
642 }
643
644 // Pop the next in-order node
645 current = vadStack[stackTop--];
646
647 // If this VAD is entirely before our search range, skip it.
648 if (current->EndVa < SearchStart) {
649 // Still update lastEndVa so gaps before SearchStart are ignored
650 if (current->EndVa > lastEndVa) lastEndVa = current->EndVa;
651 current = current->RightChild;
652 continue;
653 }
654
655 // If this VAD starts at/after the search end, we can check the final gap and exit.
656 if (current->StartVa >= SearchEnd) {
657 uintptr_t gapStart = ALIGN_UP(lastEndVa + 1, VirtualPageSize);
658
659 // Overflow check: gapStart + size_needed must not wrap
660 if (gapStart <= (uintptr_t)-1 - (size_needed - 1)) {
661 if (gapStart + size_needed <= SearchEnd) return gapStart;
662 }
663 return 0;
664 }
665
666 // Normal case: VAD intersects our search range in some way.
667 // We compute gapStart relative to lastEndVa, but it must also be >= SearchStart.
668 uintptr_t gapStart = ALIGN_UP(lastEndVa + 1, VirtualPageSize);
669 if (gapStart < SearchStart) gapStart = ALIGN_UP(SearchStart, VirtualPageSize);
670
671 // If gapStart is strictly before this VAD's StartVa, we have candidate gap.
672 if (gapStart < current->StartVa) {
673 // check overflow and fit into both current VAD and SearchEnd
674 if (gapStart <= (uintptr_t)-1 - (size_needed - 1)) {
675 uintptr_t gapEndExclusive = gapStart + size_needed;
676 // must fit before current VAD and before SearchEnd (SearchEnd is exclusive)
677 if (gapEndExclusive <= current->StartVa && gapEndExclusive <= SearchEnd) {
678 return gapStart;
679 }
680 }
681 }
682
683 // Update lastEndVa to cover this VAD. ensure monotonicity.
684 if (current->EndVa > lastEndVa) lastEndVa = current->EndVa;
685
686 // Move to right subtree
687 current = current->RightChild;
688 }
689
690 // After traversing entire tree, check the gap between lastEndVa and SearchEnd (exclusive)
691 uintptr_t finalGapStart = ALIGN_UP(lastEndVa + 1, VirtualPageSize);
692 if (finalGapStart < SearchStart) finalGapStart = ALIGN_UP(SearchStart, VirtualPageSize);
693
694 if (finalGapStart <= (uintptr_t)-1 - (size_needed - 1)) {
695 if (finalGapStart + size_needed <= SearchEnd) {
696 return finalGapStart;
697 }
698 }
699
700 // No gap found anywhere
701 return 0;
702}
703
704// PUBLIC API
705
706// Wrapper
707uintptr_t
709 IN PEPROCESS Process,
710 IN size_t NumberOfBytes,
711 IN uintptr_t SearchStart,
712 IN uintptr_t SearchEnd // exclusive
713)
714
715{
716 if (Process && NumberOfBytes) {
717 return MiFindGap(Process->VadRoot, NumberOfBytes, SearchStart, SearchEnd);
718 }
719 return 0;
720}
721
724 IN PEPROCESS Process,
725 _In_Opt _Out_Opt void** BaseAddress,
726 IN size_t NumberOfBytes,
727 IN VAD_FLAGS VadFlags
728)
729
730/*++
731
732 Routine description:
733
734 Allocates virtual memory (paged) for the process.
735
736 Arguments:
737
738 [IN] PEPROCESS Process - Process to allocate memory for
739 [IN OPTIONAL | OUT OPTIONAL] [PTR_TO_PTR] void** BaseAddress - The base address to allocate memory starting from if supplied. If NULL, a free gap is chosen and used by NumberOfBytes, and *baseAddress is set to the found start of gap.
740 [IN] size_t NumberOfBytes - The amount in virtual memory to allocate.
741 [IN] uint32_t VadFlags - The VAD Flags to supply for the allocation (file backed?)
742
743 Return Values:
744
745 Various MTSTATUS Status codes.
746
747--*/
748
749{
750 // Calculate pages needed
751 uintptr_t StartVa = (uintptr_t)*BaseAddress;
752 size_t Pages = BYTES_TO_PAGES(NumberOfBytes);
753 uintptr_t EndVa = StartVa + PAGES_TO_BYTES(Pages) - 1;
754 MTSTATUS status = MT_GENERAL_FAILURE; // Default to failure
755 bool checkForOverlap = true;
756
757 if (!StartVa) {
758 // We need to determine if the allocation is for a system process or a user process.
759 bool KernelProcess = (Process->PID == 4) ? true : false;
760 if (unlikely(KernelProcess)) {
761 assert(false);
762 MeBugCheckEx(MANUALLY_INITIATED_CRASH, RETADDR(0), NULL, NULL, NULL);
763 }
764 else {
765 // User mode
766 StartVa = MiFindGap(Process->VadRoot, NumberOfBytes, USER_VA_START, (uintptr_t)USER_VA_END + 1);
767 }
768 if (!StartVa) return MT_NOT_FOUND;
769 // No need to check for an overlap as if we found a sufficient gap, there is guranteed to be no overlap.
770 checkForOverlap = false;
771
772 // Calculate the end VA.
773 EndVa = StartVa + PAGES_TO_BYTES(Pages) - 1;
774 }
775
776 // Acquire rundown protection for process
777 if (!MsAcquireRundownProtection(&Process->ProcessRundown)) {
778 return MT_INVALID_STATE;
779 }
780
781 // Acquire lock for this process VAD tree.
782 IRQL oldIrql;
783 MsAcquireSpinlock(&Process->VadLock, &oldIrql);
784
785 // Check for overlap
786 if (checkForOverlap && MiCheckVadOverlap(Process->VadRoot, StartVa, EndVa)) {
788 goto cleanup;
789 }
790
791 // Allocate and initialize new VAD.
792 PMMVAD newVad = MiAllocateVad();
793 if (!newVad) {
794 status = MT_NO_RESOURCES;
795 goto cleanup;
796 }
797
798 newVad->StartVa = StartVa;
799 newVad->EndVa = EndVa;
800 newVad->Flags = VadFlags;
801 newVad->OwningProcess = Process;
802
803 // TODO init file info if VAD_FLAG_MAPPED_FILE is set. (TODO FILE PAGING)
804
805 // Insert the VAD into the the process's tree.
806 Process->VadRoot = MiInsertVadNode(Process->VadRoot, newVad);
807 status = MT_SUCCESS;
808 goto cleanup;
809
810cleanup:
811 MsReleaseRundownProtection(&Process->ProcessRundown);
812 MsReleaseSpinlock(&Process->VadLock, oldIrql);
813 return status;
814}
815
818 IN PEPROCESS Process,
819 IN void* BaseAddress
820)
821
822/*++
823
824 Routine description:
825
826 Releases virtual memory allocated by MmAllocateVirtualMemory.
827
828 Arguments:
829
830 [IN] PEPROCESS Process - Process to allocate memory for
831 [IN] void* BaseAddress - The base address to release memory, supplied from/to MmAllocateVirtualMemory.
832
833 Return Values:
834
835 Various MTSTATUS Status code.
836
837--*/
838
839{
841 uintptr_t va = (uintptr_t)BaseAddress;
842
843 // Acquire rundown protection
844 if (!MsAcquireRundownProtection(&Process->ProcessRundown)) {
845 return MT_INVALID_STATE;
846 }
847
848 // Acquire VAD lock
849 IRQL oldIrql;
850 MsAcquireSpinlock(&Process->VadLock, &oldIrql);
851
852 PMMVAD VadToFree = MiFindVad(Process->VadRoot, va);
853
854 // Check if its the valid VAD and if the base address is the start of the VAD region.
855 if (VadToFree == NULL || VadToFree->StartVa != va) {
856 status = MT_INVALID_PARAM;
857 goto cleanup;
858 }
859
860 // Unmap all PTEs and physical pages from VAD.
861 for (uintptr_t virtualaddr = VadToFree->StartVa; virtualaddr <= VadToFree->EndVa; virtualaddr += VirtualPageSize) {
862 // Get the PTE pointer for the current VA.
863 PMMPTE pte = MiGetPtePointer(virtualaddr);
864 // Atomically unmap the PTE.
865 MiUnmapPte(pte);
866 // Grab the PFN Number from the (now replaced) PTE. (in PresentSet, PageFrameNumber is the physical address, not the PFN index, our MiUnmapPte function replaced that)
868 // Release the PFN back to MM.
870 }
871
872 // Delete the VAD from the tree.
873 Process->VadRoot = MiDeleteVadNode(Process->VadRoot, VadToFree);
874 // Free the VAD struct itself (from kernel's nonpagedpool memory, its not a double free)
875 MiFreeVad(VadToFree);
876
877 // Set status.
878 status = MT_SUCCESS;
879 goto cleanup;
880
881cleanup:
882 MsReleaseRundownProtection(&Process->ProcessRundown);
883 MsReleaseSpinlock(&Process->VadLock, oldIrql);
884 return status;
885}
#define _In_Opt
Definition annotations.h:9
#define FORCEINLINE
Definition annotations.h:22
#define _Out_Opt
Definition annotations.h:10
#define IN
Definition annotations.h:7
#define assert(...)
Definition assert.h:57
NORETURN void MeBugCheckEx(IN enum _BUGCHECK_CODES BugCheckCode, IN void *BugCheckParameter1, IN void *BugCheckParameter2, IN void *BugCheckParameter3, IN void *BugCheckParameter4)
Definition bugcheck.c:305
enum _IRQL IRQL
EPROCESS * PEPROCESS
Definition core.h:50
#define RETADDR(level)
Definition macros.h:38
#define unlikely(x)
Definition macros.h:47
#define MAX(a, b)
Definition macros.h:33
PMMPTE MiGetPtePointer(IN uintptr_t va)
Definition map.c:76
void MiUnmapPte(IN PMMPTE pte)
Definition map.c:385
@ MANUALLY_INITIATED_CRASH
Definition me.h:90
@ NonPagedPool
Definition mm.h:316
#define PAGES_TO_BYTES(Pages)
Definition mm.h:149
struct _MMPTE * PMMPTE
FORCEINLINE void * kmemcpy(void *dest, const void *src, size_t len)
Definition mm.h:554
struct _MMVAD MMVAD
uint64_t PAGE_INDEX
Definition mm.h:232
FORCEINLINE void * kmemset(void *dest, int64_t val, uint64_t len)
Definition mm.h:540
#define USER_VA_END
Definition mm.h:160
enum _VAD_FLAGS VAD_FLAGS
#define BYTES_TO_PAGES(Bytes)
Definition mm.h:147
#define USER_VA_START
Definition mm.h:161
struct _MMVAD * PMMVAD
#define VirtualPageSize
Definition mm.h:53
#define ALIGN_UP(x, align)
Definition mm.h:181
#define MT_SUCCESS
Definition mtstatus.h:22
#define MT_GENERAL_FAILURE
Definition mtstatus.h:31
#define MT_INVALID_STATE
Definition mtstatus.h:25
#define MT_INVALID_PARAM
Definition mtstatus.h:24
int32_t MTSTATUS
Definition mtstatus.h:12
#define MT_NOT_FOUND
Definition mtstatus.h:30
#define MT_NO_RESOURCES
Definition mtstatus.h:32
#define MT_CONFLICTING_ADDRESSES
Definition mtstatus.h:47
void MiReleasePhysicalPage(IN PAGE_INDEX PfnIndex)
Definition pfn.c:421
void MmFreePool(IN void *buf)
Definition pool.c:586
void * MmAllocatePoolWithTag(IN enum _POOL_TYPE PoolType, IN size_t NumberOfBytes, IN uint32_t Tag)
Definition pool.c:427
bool MsAcquireRundownProtection(IN PRUNDOWN_REF rundown)
Definition rundown.c:7
void MsReleaseRundownProtection(IN PRUNDOWN_REF rundown)
Definition rundown.c:40
void MsAcquireSpinlock(IN PSPINLOCK lock, IN PIRQL OldIrql)
Definition spinlock.c:13
void MsReleaseSpinlock(IN PSPINLOCK lock, IN IRQL OldIrql)
Definition spinlock.c:45
struct _MMVAD * VadRoot
Definition ps.h:117
uint64_t PageFrameNumber
Definition mm.h:404
struct _MMPTE::@172372265215056352375070220246156106027174106113::@277354034164206104264133322054061025100052052376 Soft
VAD_FLAGS Flags
Definition mm.h:476
uintptr_t EndVa
Definition mm.h:475
struct _MMVAD * Parent
Definition mm.h:481
uintptr_t StartVa
Definition mm.h:474
struct _EPROCESS * OwningProcess
Definition mm.h:491
struct _MMVAD * LeftChild
Definition mm.h:479
struct _MMVAD * RightChild
Definition mm.h:480
#define MAX_VAD_DEPTH
Definition vad.c:589
int stackTop
Definition vad.c:591
PMMVAD vadStack[MAX_VAD_DEPTH]
Definition vad.c:590
FORCEINLINE int MiGetBalanceFactor(IN PMMVAD Node)
Definition vad.c:82
FORCEINLINE int MiGetNodeHeight(IN PMMVAD Node)
Definition vad.c:28
MTSTATUS MmFreeVirtualMemory(IN PEPROCESS Process, IN void *BaseAddress)
Definition vad.c:817
PMMVAD MiFindVad(IN PMMVAD Root, IN uintptr_t VirtualAddress)
Definition vad.c:354
MTSTATUS MmAllocateVirtualMemory(IN PEPROCESS Process, _In_Opt _Out_Opt void **BaseAddress, IN size_t NumberOfBytes, IN VAD_FLAGS VadFlags)
Definition vad.c:723
uintptr_t MmFindFreeAddressSpace(IN PEPROCESS Process, IN size_t NumberOfBytes, IN uintptr_t SearchStart, IN uintptr_t SearchEnd)
Definition vad.c:708
FORCEINLINE void MiUpdateNodeHeight(IN PMMVAD Node)
Definition vad.c:55