[NTOS]: Another one bites the dust, another one bites the dust. And another one gone...
[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 extern MMPTE ValidKernelPte;
46 PFN_NUMBER Pfn;
47 MMPTE TempPte;
48 PVOID MappingBaseAddress;
49
50 //
51 // Check if we are called too early
52 //
53 if (MiDbgReadyForPhysical == FALSE)
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 //
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
154 //
155 // No local kernel debugging support yet, so don't worry about locking
156 //
157 ASSERT(Flags & MMDBG_COPY_UNSAFE);
158
159 //
160 // We only handle 1, 2, 4 and 8 byte requests
161 //
162 if ((Size != 1) &&
163 (Size != 2) &&
164 (Size != 4) &&
165 (Size != MMDBG_COPY_MAX_SIZE))
166 {
167 //
168 // Invalid size, fail
169 //
170 KdpDprintf("MmDbgCopyMemory: Received Illegal Size 0x%lx\n", Size);
171 return STATUS_INVALID_PARAMETER_3;
172 }
173
174 //
175 // The copy must be aligned
176 //
177 if ((Address & (Size - 1)) != 0)
178 {
179 //
180 // Fail
181 //
182 KdpDprintf("MmDbgCopyMemory: Received Unaligned Address 0x%I64x Size %lx\n",
183 Address, Size);
184 return STATUS_INVALID_PARAMETER_3;
185 }
186
187 //
188 // Check if this is physical or virtual copy
189 //
190 if (Flags & MMDBG_COPY_PHYSICAL)
191 {
192 //
193 // Physical: translate and map it to our mapping space
194 //
195 TargetAddress = MiDbgTranslatePhysicalAddress(Address, Flags);
196
197 //
198 // Check if translation failed
199 //
200 if (!TargetAddress)
201 {
202 //
203 // Fail
204 //
205 KdpDprintf("MmDbgCopyMemory: Failed to Translate Physical Address "
206 "%I64x\n", Address);
207 return STATUS_UNSUCCESSFUL;
208 }
209
210 //
211 // The address we received must be valid!
212 //
213 ASSERT(MmIsAddressValid(TargetAddress));
214 }
215 else
216 {
217 //
218 // Virtual; truncate it to avoid casts later down
219 //
220 TargetAddress = (PVOID)(ULONG_PTR)Address;
221
222 //
223 // Check if the address is invalid
224 //
225 if (!MmIsAddressValid(TargetAddress))
226 {
227 //
228 // Fail
229 //
230 KdpDprintf("MmDbgCopyMemory: Failing %s for invalid "
231 "Virtual Address 0x%p\n",
232 Flags & MMDBG_COPY_WRITE ? "write" : "read",
233 TargetAddress);
234 return STATUS_UNSUCCESSFUL;
235 }
236
237 //
238 // No session space support yet
239 //
240 ASSERT(MmIsSessionAddress(TargetAddress) == FALSE);
241 }
242
243 //
244 // If we are going to write to the address then make sure it is writeable too
245 //
246 if ((Flags & MMDBG_COPY_WRITE) &&
247 (!MI_IS_PAGE_WRITEABLE(MiAddressToPte(TargetAddress))))
248 {
249 //
250 // Check if we mapped anything
251 //
252 if (Flags & MMDBG_COPY_PHYSICAL)
253 {
254 //
255 // Get rid of the mapping
256 //
257 MiDbgUnTranslatePhysicalAddress();
258 }
259
260 //
261 // Fail
262 //
263 // FIXME: We should attempt to override the write protection instead of
264 // failing here
265 //
266 KdpDprintf("MmDbgCopyMemory: Failing Write for Protected Address 0x%p\n",
267 TargetAddress);
268 return STATUS_UNSUCCESSFUL;
269 }
270
271 //
272 // Use SEH to try to catch anything else somewhat cleanly
273 //
274 _SEH2_TRY
275 {
276 //
277 // Check if this is read or write
278 //
279 if (Flags & MMDBG_COPY_WRITE)
280 {
281 //
282 // Do the write
283 //
284 RtlCopyMemory(TargetAddress,
285 Buffer,
286 Size);
287 }
288 else
289 {
290 //
291 // Do the read
292 //
293 RtlCopyMemory(Buffer,
294 TargetAddress,
295 Size);
296 }
297
298 //
299 // Copy succeeded
300 //
301 Status = STATUS_SUCCESS;
302 }
303 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
304 {
305 //
306 // Get the exception code
307 //
308 Status = _SEH2_GetExceptionCode();
309 }
310 _SEH2_END;
311
312 //
313 // Get rid of the mapping if this was a physical copy
314 //
315 if (Flags & MMDBG_COPY_PHYSICAL)
316 {
317 //
318 // Unmap and flush it
319 //
320 MiDbgUnTranslatePhysicalAddress();
321 }
322
323 //
324 // Return status to caller
325 //
326 return Status;
327 }