[RSHELL]
[reactos.git] / ntoskrnl / mm / ARM3 / mmdbg.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/mmdbg.c
5 * PURPOSE: Memory Manager support routines for the Kernel Debugger
6 * PROGRAMMERS: Stefan Ginsberg (stefan.ginsberg@reactos.org)
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 #ifndef _WINKD_
19 #define KdpDprintf DPRINT
20 #elif defined(NDEBUG)
21 #define KdpDprintf(...)
22 #endif
23
24 /* GLOBALS ********************************************************************/
25
26 PVOID MiDebugMapping = MI_DEBUG_MAPPING;
27 PMMPTE MmDebugPte = NULL;
28
29 /* FUNCTIONS ******************************************************************/
30
31 BOOLEAN
32 NTAPI
33 MmIsSessionAddress(IN PVOID Address)
34 {
35 //
36 // No session space support yet
37 //
38 return FALSE;
39 }
40
41 PVOID
42 NTAPI
43 MiDbgTranslatePhysicalAddress(IN ULONG64 PhysicalAddress,
44 IN ULONG Flags)
45 {
46 PFN_NUMBER Pfn;
47 MMPTE TempPte;
48 PVOID MappingBaseAddress;
49
50 //
51 // Check if we are called too early
52 //
53 if (MmDebugPte == NULL)
54 {
55 //
56 // The structures we require aren't initialized yet, fail
57 //
58 KdpDprintf("MiDbgTranslatePhysicalAddress called too early! "
59 "Address: 0x%I64x\n", PhysicalAddress);
60 return NULL;
61 }
62
63 //
64 // FIXME: No support for cache flags yet
65 //
66 if ((Flags & (MMDBG_COPY_CACHED |
67 MMDBG_COPY_UNCACHED |
68 MMDBG_COPY_WRITE_COMBINED)) != 0)
69 {
70 //
71 // Fail
72 //
73 KdpDprintf("MiDbgTranslatePhysicalAddress: Cache Flags not yet supported. "
74 "Flags: 0x%lx\n", Flags & (MMDBG_COPY_CACHED |
75 MMDBG_COPY_UNCACHED |
76 MMDBG_COPY_WRITE_COMBINED));
77 return NULL;
78 }
79
80 //
81 // Save the base address of our mapping page
82 //
83 MappingBaseAddress = MiPteToAddress(MmDebugPte);
84
85 //
86 // Get the template
87 //
88 TempPte = ValidKernelPte;
89
90 //
91 // Convert physical address to PFN
92 //
93 Pfn = (PFN_NUMBER)(PhysicalAddress >> PAGE_SHIFT);
94
95 /* Check if this could be an I/O mapping */
96 if (!MiGetPfnEntry(Pfn))
97 {
98 //
99 // FIXME: We don't support this yet
100 //
101 KdpDprintf("MiDbgTranslatePhysicalAddress: I/O Space not yet supported. "
102 "PFN: 0x%I64x\n", (ULONG64)Pfn);
103 return NULL;
104 }
105 else
106 {
107 //
108 // Set the PFN in the PTE
109 //
110 TempPte.u.Hard.PageFrameNumber = Pfn;
111 }
112
113 //
114 // Map the PTE and invalidate its TLB entry
115 //
116 *MmDebugPte = TempPte;
117 KeInvalidateTlbEntry(MappingBaseAddress);
118
119 //
120 // Calculate and return the virtual offset into our mapping page
121 //
122 return (PVOID)((ULONG_PTR)MappingBaseAddress +
123 BYTE_OFFSET(PhysicalAddress));
124 }
125
126 VOID
127 NTAPI
128 MiDbgUnTranslatePhysicalAddress(VOID)
129 {
130 PVOID MappingBaseAddress = MiPteToAddress(MmDebugPte);
131
132 //
133 // The address must still be valid at this point
134 //
135 ASSERT(MmIsAddressValid(MappingBaseAddress));
136
137 //
138 // Clear the mapping PTE and invalidate its TLB entry
139 //
140 MmDebugPte->u.Long = 0;
141 KeInvalidateTlbEntry(MappingBaseAddress);
142 }
143
144 NTSTATUS
145 NTAPI
146 MmDbgCopyMemory(IN ULONG64 Address,
147 IN PVOID Buffer,
148 IN ULONG Size,
149 IN ULONG Flags)
150 {
151 NTSTATUS Status;
152 PVOID TargetAddress;
153 ULONG64 PhysicalAddress;
154 PMMPTE PointerPte;
155
156 //
157 // No local kernel debugging support yet, so don't worry about locking
158 //
159 ASSERT(Flags & MMDBG_COPY_UNSAFE);
160
161 //
162 // We only handle 1, 2, 4 and 8 byte requests
163 //
164 if ((Size != 1) &&
165 (Size != 2) &&
166 (Size != 4) &&
167 (Size != MMDBG_COPY_MAX_SIZE))
168 {
169 //
170 // Invalid size, fail
171 //
172 KdpDprintf("MmDbgCopyMemory: Received Illegal Size 0x%lx\n", Size);
173 return STATUS_INVALID_PARAMETER_3;
174 }
175
176 //
177 // The copy must be aligned
178 //
179 if ((Address & (Size - 1)) != 0)
180 {
181 //
182 // Fail
183 //
184 KdpDprintf("MmDbgCopyMemory: Received Unaligned Address 0x%I64x Size %lx\n",
185 Address, Size);
186 return STATUS_INVALID_PARAMETER_3;
187 }
188
189 //
190 // Check if this is physical or virtual copy
191 //
192 if (Flags & MMDBG_COPY_PHYSICAL)
193 {
194 //
195 // Physical: translate and map it to our mapping space
196 //
197 TargetAddress = MiDbgTranslatePhysicalAddress(Address, Flags);
198
199 //
200 // Check if translation failed
201 //
202 if (!TargetAddress)
203 {
204 //
205 // Fail
206 //
207 KdpDprintf("MmDbgCopyMemory: Failed to Translate Physical Address "
208 "%I64x\n", Address);
209 return STATUS_UNSUCCESSFUL;
210 }
211
212 //
213 // The address we received must be valid!
214 //
215 ASSERT(MmIsAddressValid(TargetAddress));
216 }
217 else
218 {
219 //
220 // Virtual; truncate it to avoid casts later down
221 //
222 TargetAddress = (PVOID)(ULONG_PTR)Address;
223
224 //
225 // Check if the address is invalid
226 //
227 if (!MmIsAddressValid(TargetAddress))
228 {
229 //
230 // Fail
231 //
232 KdpDprintf("MmDbgCopyMemory: Failing %s for invalid "
233 "Virtual Address 0x%p\n",
234 Flags & MMDBG_COPY_WRITE ? "write" : "read",
235 TargetAddress);
236 return STATUS_UNSUCCESSFUL;
237 }
238
239 //
240 // No session space support yet
241 //
242 ASSERT(MmIsSessionAddress(TargetAddress) == FALSE);
243
244 /* If we are going to write to the address, then check if its writable */
245 PointerPte = MiAddressToPte(TargetAddress);
246 if ((Flags & MMDBG_COPY_WRITE) && !MI_IS_PAGE_WRITEABLE(PointerPte))
247 {
248 /* Not writable, we need to do a physical copy */
249 Flags |= MMDBG_COPY_PHYSICAL;
250
251 /* Calculate the physical address */
252 PhysicalAddress = PointerPte->u.Hard.PageFrameNumber << PAGE_SHIFT;
253 PhysicalAddress += BYTE_OFFSET(Address);
254
255 /* Translate the physical address */
256 TargetAddress = MiDbgTranslatePhysicalAddress(PhysicalAddress, Flags);
257
258 /* Check if translation failed */
259 if (!TargetAddress)
260 {
261 /* Fail */
262 KdpDprintf("MmDbgCopyMemory: Failed to translate for write "
263 "%I64x (%I64x)\n", PhysicalAddress, Address);
264 return STATUS_UNSUCCESSFUL;
265 }
266 }
267 }
268
269 //
270 // Use SEH to try to catch anything else somewhat cleanly
271 //
272 _SEH2_TRY
273 {
274 //
275 // Check if this is read or write
276 //
277 if (Flags & MMDBG_COPY_WRITE)
278 {
279 //
280 // Do the write
281 //
282 RtlCopyMemory(TargetAddress,
283 Buffer,
284 Size);
285 }
286 else
287 {
288 //
289 // Do the read
290 //
291 RtlCopyMemory(Buffer,
292 TargetAddress,
293 Size);
294 }
295
296 //
297 // Copy succeeded
298 //
299 Status = STATUS_SUCCESS;
300 }
301 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
302 {
303 //
304 // Get the exception code
305 //
306 Status = _SEH2_GetExceptionCode();
307 }
308 _SEH2_END;
309
310 //
311 // Get rid of the mapping if this was a physical copy
312 //
313 if (Flags & MMDBG_COPY_PHYSICAL)
314 {
315 //
316 // Unmap and flush it
317 //
318 MiDbgUnTranslatePhysicalAddress();
319 }
320
321 //
322 // Return status to caller
323 //
324 return Status;
325 }