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