2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/hypermap.c
5 * PURPOSE: ARM Memory Manager Hyperspace Mapping Functionality
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 #define MODULE_INVOLVED_IN_ARM3
16 #include <mm/ARM3/miarm.h>
18 /* GLOBALS ********************************************************************/
20 PMMPTE MmFirstReservedMappingPte
, MmLastReservedMappingPte
;
21 PMMPTE MiFirstReservedZeroingPte
;
22 MMPTE HyperTemplatePte
;
24 /* PRIVATE FUNCTIONS **********************************************************/
26 _Acquires_lock_(Process
->HyperSpaceLock
)
27 _When_(OldIrql
== 0, _IRQL_requires_(DISPATCH_LEVEL
))
28 _When_(OldIrql
!= 0, _IRQL_requires_(PASSIVE_LEVEL
))
29 _When_(OldIrql
!= 0, _At_(*OldIrql
, _IRQL_saves_
))
30 _When_(OldIrql
!= 0, _IRQL_raises_(DISPATCH_LEVEL
))
33 MiMapPageInHyperSpace(_In_ PEPROCESS Process
,
35 _Out_opt_ PKIRQL OldIrql
)
41 ASSERT(((OldIrql
!= NULL
) && (KeGetCurrentIrql() == PASSIVE_LEVEL
))
42 || ((OldIrql
== NULL
) && (KeGetCurrentIrql() == DISPATCH_LEVEL
)));
45 // Never accept page 0 or non-physical pages
48 ASSERT(MiGetPfnEntry(Page
) != NULL
);
53 TempPte
= ValidKernelPteLocal
;
54 TempPte
.u
.Hard
.PageFrameNumber
= Page
;
57 // Pick the first hyperspace PTE
59 PointerPte
= MmFirstReservedMappingPte
;
62 // Acquire the hyperlock
64 ASSERT(Process
== PsGetCurrentProcess());
66 KeAcquireSpinLock(&Process
->HyperSpaceLock
, OldIrql
);
68 KeAcquireSpinLockAtDpcLevel(&Process
->HyperSpaceLock
);
71 // Now get the first free PTE
73 Offset
= PFN_FROM_PTE(PointerPte
);
79 Offset
= MI_HYPERSPACE_PTES
;
84 // Prepare the next PTE
86 PointerPte
->u
.Hard
.PageFrameNumber
= Offset
- 1;
89 // Write the current PTE
92 MI_WRITE_VALID_PTE(PointerPte
, TempPte
);
97 return MiPteToAddress(PointerPte
);
100 _Requires_lock_held_(Process
->HyperSpaceLock
)
101 _Releases_lock_(Process
->HyperSpaceLock
)
102 _IRQL_requires_(DISPATCH_LEVEL
)
103 _When_(OldIrql
!= MM_NOIRQL
, _At_(OldIrql
, _IRQL_restores_
))
106 MiUnmapPageInHyperSpace(_In_ PEPROCESS Process
,
110 ASSERT(Process
== PsGetCurrentProcess());
113 // Blow away the mapping
115 MiAddressToPte(Address
)->u
.Long
= 0;
118 // Release the hyperlock
120 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
121 if (OldIrql
== MM_NOIRQL
)
122 KeReleaseSpinLockFromDpcLevel(&Process
->HyperSpaceLock
);
124 KeReleaseSpinLock(&Process
->HyperSpaceLock
, OldIrql
);
129 MiMapPagesInZeroSpace(IN PMMPFN Pfn1
,
130 IN PFN_NUMBER NumberOfPages
)
134 PFN_NUMBER Offset
, PageFrameIndex
;
139 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
140 ASSERT(NumberOfPages
!= 0);
141 ASSERT(NumberOfPages
<= MI_ZERO_PTES
);
144 // Pick the first zeroing PTE
146 PointerPte
= MiFirstReservedZeroingPte
;
149 // Now get the first free PTE
151 Offset
= PFN_FROM_PTE(PointerPte
);
152 if (NumberOfPages
> Offset
)
157 Offset
= MI_ZERO_PTES
;
158 PointerPte
->u
.Hard
.PageFrameNumber
= Offset
;
163 // Prepare the next PTE
165 PointerPte
->u
.Hard
.PageFrameNumber
= Offset
- NumberOfPages
;
167 /* Choose the correct PTE to use, and which template */
168 PointerPte
+= (Offset
+ 1);
169 TempPte
= ValidKernelPte
;
171 /* Make sure the list isn't empty and loop it */
172 ASSERT(Pfn1
!= (PVOID
)LIST_HEAD
);
173 while (Pfn1
!= (PVOID
)LIST_HEAD
)
175 /* Get the page index for this PFN */
176 PageFrameIndex
= MiGetPfnEntryIndex(Pfn1
);
181 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
184 // Set the correct PTE to write to, and set its new value
187 MI_WRITE_VALID_PTE(PointerPte
, TempPte
);
189 /* Move to the next PFN */
190 Pfn1
= (PMMPFN
)Pfn1
->u1
.Flink
;
194 // Return the address
196 return MiPteToAddress(PointerPte
);
201 MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress
,
202 IN PFN_NUMBER NumberOfPages
)
209 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
210 ASSERT (NumberOfPages
!= 0);
211 ASSERT(NumberOfPages
<= MI_ZERO_PTES
);
214 // Get the first PTE for the mapped zero VA
216 PointerPte
= MiAddressToPte(VirtualAddress
);
219 // Blow away the mapped zero PTEs
221 RtlZeroMemory(PointerPte
, NumberOfPages
* sizeof(MMPTE
));