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 "../ARM3/miarm.h"
18 /* GLOBALS ********************************************************************/
20 PMMPTE MmFirstReservedMappingPte
, MmLastReservedMappingPte
;
21 PMMPTE MiFirstReservedZeroingPte
;
22 MMPTE HyperTemplatePte
;
23 PEPROCESS HyperProcess
;
26 /* PRIVATE FUNCTIONS **********************************************************/
30 MiMapPageInHyperSpace(IN PEPROCESS Process
,
39 // Never accept page 0 or non-physical pages
42 ASSERT(MiGetPfnEntry(Page
) != NULL
);
47 TempPte
= ValidKernelPte
;
48 TempPte
.u
.Hard
.PageFrameNumber
= Page
;
49 MI_MAKE_LOCAL_PAGE(&TempPte
); // Hyperspace is local!
52 // Pick the first hyperspace PTE
54 PointerPte
= MmFirstReservedMappingPte
;
57 // Acquire the hyperlock
59 ASSERT(Process
== PsGetCurrentProcess());
60 KeAcquireSpinLock(&Process
->HyperSpaceLock
, OldIrql
);
63 // Now get the first free PTE
65 Offset
= PFN_FROM_PTE(PointerPte
);
71 Offset
= MI_HYPERSPACE_PTES
;
76 // Prepare the next PTE
78 PointerPte
->u
.Hard
.PageFrameNumber
= Offset
- 1;
81 // Write the current PTE
84 MI_WRITE_VALID_PTE(PointerPte
, TempPte
);
89 return MiPteToAddress(PointerPte
);
94 MiUnmapPageInHyperSpace(IN PEPROCESS Process
,
98 ASSERT(Process
== PsGetCurrentProcess());
101 // Blow away the mapping
103 MiAddressToPte(Address
)->u
.Long
= 0;
106 // Release the hyperlock
108 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
109 KeReleaseSpinLock(&Process
->HyperSpaceLock
, OldIrql
);
114 MiMapPagesToZeroInHyperSpace(IN PMMPFN Pfn1
,
115 IN PFN_NUMBER NumberOfPages
)
119 PFN_NUMBER Offset
, PageFrameIndex
;
124 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
125 ASSERT(NumberOfPages
!= 0);
126 ASSERT(NumberOfPages
<= (MI_ZERO_PTES
- 1));
129 // Pick the first zeroing PTE
131 PointerPte
= MiFirstReservedZeroingPte
;
134 // Now get the first free PTE
136 Offset
= PFN_FROM_PTE(PointerPte
);
137 if (NumberOfPages
> Offset
)
142 Offset
= MI_ZERO_PTES
- 1;
143 PointerPte
->u
.Hard
.PageFrameNumber
= Offset
;
148 // Prepare the next PTE
150 PointerPte
->u
.Hard
.PageFrameNumber
= Offset
- NumberOfPages
;
152 /* Choose the correct PTE to use, and which template */
153 PointerPte
+= (Offset
+ 1);
154 TempPte
= ValidKernelPte
;
155 MI_MAKE_LOCAL_PAGE(&TempPte
); // Hyperspace is local!
157 /* Make sure the list isn't empty and loop it */
158 ASSERT(Pfn1
!= (PVOID
)LIST_HEAD
);
159 while (Pfn1
!= (PVOID
)LIST_HEAD
)
161 /* Get the page index for this PFN */
162 PageFrameIndex
= MiGetPfnEntryIndex(Pfn1
);
167 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
170 // Set the correct PTE to write to, and set its new value
173 MI_WRITE_VALID_PTE(PointerPte
, TempPte
);
175 /* Move to the next PFN */
176 Pfn1
= (PMMPFN
)Pfn1
->u1
.Flink
;
180 // Return the address
182 return MiPteToAddress(PointerPte
);
187 MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress
,
188 IN PFN_NUMBER NumberOfPages
)
195 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
196 ASSERT (NumberOfPages
!= 0);
197 ASSERT (NumberOfPages
<= (MI_ZERO_PTES
- 1));
200 // Get the first PTE for the mapped zero VA
202 PointerPte
= MiAddressToPte(VirtualAddress
);
205 // Blow away the mapped zero PTEs
207 RtlZeroMemory(PointerPte
, NumberOfPages
* sizeof(MMPTE
));