[NTOS]
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / hypermap.c
1 /*
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
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 #define MODULE_INVOLVED_IN_ARM3
16 #include "../ARM3/miarm.h"
17
18 /* GLOBALS ********************************************************************/
19
20 PMMPTE MmFirstReservedMappingPte, MmLastReservedMappingPte;
21 PMMPTE MiFirstReservedZeroingPte;
22 MMPTE HyperTemplatePte;
23 PEPROCESS HyperProcess;
24 KIRQL HyperIrql;
25
26 /* PRIVATE FUNCTIONS **********************************************************/
27
28 PVOID
29 NTAPI
30 MiMapPageInHyperSpace(IN PEPROCESS Process,
31 IN PFN_NUMBER Page,
32 IN PKIRQL OldIrql)
33 {
34 MMPTE TempPte;
35 PMMPTE PointerPte;
36 PFN_NUMBER Offset;
37
38 //
39 // Never accept page 0 or non-physical pages
40 //
41 ASSERT(Page != 0);
42 ASSERT(MiGetPfnEntry(Page) != NULL);
43
44 //
45 // Build the PTE
46 //
47 TempPte = ValidKernelPte;
48 TempPte.u.Hard.PageFrameNumber = Page;
49 MI_MAKE_LOCAL_PAGE(&TempPte); // Hyperspace is local!
50
51 //
52 // Pick the first hyperspace PTE
53 //
54 PointerPte = MmFirstReservedMappingPte;
55
56 //
57 // Acquire the hyperlock
58 //
59 ASSERT(Process == PsGetCurrentProcess());
60 KeAcquireSpinLock(&Process->HyperSpaceLock, OldIrql);
61
62 //
63 // Now get the first free PTE
64 //
65 Offset = PFN_FROM_PTE(PointerPte);
66 if (!Offset)
67 {
68 //
69 // Reset the PTEs
70 //
71 Offset = MI_HYPERSPACE_PTES;
72 KeFlushProcessTb();
73 }
74
75 //
76 // Prepare the next PTE
77 //
78 PointerPte->u.Hard.PageFrameNumber = Offset - 1;
79
80 //
81 // Write the current PTE
82 //
83 PointerPte += Offset;
84 MI_WRITE_VALID_PTE(PointerPte, TempPte);
85
86 //
87 // Return the address
88 //
89 return MiPteToAddress(PointerPte);
90 }
91
92 VOID
93 NTAPI
94 MiUnmapPageInHyperSpace(IN PEPROCESS Process,
95 IN PVOID Address,
96 IN KIRQL OldIrql)
97 {
98 ASSERT(Process == PsGetCurrentProcess());
99
100 //
101 // Blow away the mapping
102 //
103 MiAddressToPte(Address)->u.Long = 0;
104
105 //
106 // Release the hyperlock
107 //
108 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
109 KeReleaseSpinLock(&Process->HyperSpaceLock, OldIrql);
110 }
111
112 PVOID
113 NTAPI
114 MiMapPagesInZeroSpace(IN PMMPFN Pfn1,
115 IN PFN_NUMBER NumberOfPages)
116 {
117 MMPTE TempPte;
118 PMMPTE PointerPte;
119 PFN_NUMBER Offset, PageFrameIndex;
120
121 //
122 // Sanity checks
123 //
124 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
125 ASSERT(NumberOfPages != 0);
126 ASSERT(NumberOfPages <= (MI_ZERO_PTES - 1));
127
128 //
129 // Pick the first zeroing PTE
130 //
131 PointerPte = MiFirstReservedZeroingPte;
132
133 //
134 // Now get the first free PTE
135 //
136 Offset = PFN_FROM_PTE(PointerPte);
137 if (NumberOfPages > Offset)
138 {
139 //
140 // Reset the PTEs
141 //
142 Offset = MI_ZERO_PTES - 1;
143 PointerPte->u.Hard.PageFrameNumber = Offset;
144 KeFlushProcessTb();
145 }
146
147 //
148 // Prepare the next PTE
149 //
150 PointerPte->u.Hard.PageFrameNumber = Offset - NumberOfPages;
151
152 /* Choose the correct PTE to use, and which template */
153 PointerPte += (Offset + 1);
154 TempPte = ValidKernelPte;
155
156 /* Make sure the list isn't empty and loop it */
157 ASSERT(Pfn1 != (PVOID)LIST_HEAD);
158 while (Pfn1 != (PVOID)LIST_HEAD)
159 {
160 /* Get the page index for this PFN */
161 PageFrameIndex = MiGetPfnEntryIndex(Pfn1);
162
163 //
164 // Write the PFN
165 //
166 TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
167
168 //
169 // Set the correct PTE to write to, and set its new value
170 //
171 PointerPte--;
172 MI_WRITE_VALID_PTE(PointerPte, TempPte);
173
174 /* Move to the next PFN */
175 Pfn1 = (PMMPFN)Pfn1->u1.Flink;
176 }
177
178 //
179 // Return the address
180 //
181 return MiPteToAddress(PointerPte);
182 }
183
184 VOID
185 NTAPI
186 MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress,
187 IN PFN_NUMBER NumberOfPages)
188 {
189 PMMPTE PointerPte;
190
191 //
192 // Sanity checks
193 //
194 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
195 ASSERT (NumberOfPages != 0);
196 ASSERT (NumberOfPages <= (MI_ZERO_PTES - 1));
197
198 //
199 // Get the first PTE for the mapped zero VA
200 //
201 PointerPte = MiAddressToPte(VirtualAddress);
202
203 //
204 // Blow away the mapped zero PTEs
205 //
206 RtlZeroMemory(PointerPte, NumberOfPages * sizeof(MMPTE));
207 }
208