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