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)
9 /* INCLUDES *******************************************************************/
15 #define MODULE_INVOLVED_IN_ARM3
16 #include "../ARM3/miarm.h"
19 #define KdpDprintf DPRINT
21 #define KdpDprintf(...)
24 /* GLOBALS ********************************************************************/
26 PVOID MiDebugMapping
= MI_DEBUG_MAPPING
;
27 PMMPTE MmDebugPte
= NULL
;
29 /* FUNCTIONS ******************************************************************/
33 MmIsSessionAddress(IN PVOID Address
)
36 // No session space support yet
43 MiDbgTranslatePhysicalAddress(IN ULONG64 PhysicalAddress
,
48 PVOID MappingBaseAddress
;
51 // Check if we are called too early
53 if (MmDebugPte
== NULL
)
56 // The structures we require aren't initialized yet, fail
58 KdpDprintf("MiDbgTranslatePhysicalAddress called too early! "
59 "Address: 0x%I64x\n", PhysicalAddress
);
64 // FIXME: No support for cache flags yet
66 if ((Flags
& (MMDBG_COPY_CACHED
|
68 MMDBG_COPY_WRITE_COMBINED
)) != 0)
73 KdpDprintf("MiDbgTranslatePhysicalAddress: Cache Flags not yet supported. "
74 "Flags: 0x%lx\n", Flags
& (MMDBG_COPY_CACHED
|
76 MMDBG_COPY_WRITE_COMBINED
));
81 // Save the base address of our mapping page
83 MappingBaseAddress
= MiPteToAddress(MmDebugPte
);
88 TempPte
= ValidKernelPte
;
91 // Convert physical address to PFN
93 Pfn
= (PFN_NUMBER
)(PhysicalAddress
>> PAGE_SHIFT
);
95 /* Check if this could be an I/O mapping */
96 if (!MiGetPfnEntry(Pfn
))
99 // FIXME: We don't support this yet
101 KdpDprintf("MiDbgTranslatePhysicalAddress: I/O Space not yet supported. "
102 "PFN: 0x%I64x\n", (ULONG64
)Pfn
);
108 // Set the PFN in the PTE
110 TempPte
.u
.Hard
.PageFrameNumber
= Pfn
;
114 // Map the PTE and invalidate its TLB entry
116 *MmDebugPte
= TempPte
;
117 KeInvalidateTlbEntry(MappingBaseAddress
);
120 // Calculate and return the virtual offset into our mapping page
122 return (PVOID
)((ULONG_PTR
)MappingBaseAddress
+
123 BYTE_OFFSET(PhysicalAddress
));
128 MiDbgUnTranslatePhysicalAddress(VOID
)
130 PVOID MappingBaseAddress
= MiPteToAddress(MmDebugPte
);
133 // The address must still be valid at this point
135 ASSERT(MmIsAddressValid(MappingBaseAddress
));
138 // Clear the mapping PTE and invalidate its TLB entry
140 MmDebugPte
->u
.Long
= 0;
141 KeInvalidateTlbEntry(MappingBaseAddress
);
146 MmDbgCopyMemory(IN ULONG64 Address
,
153 ULONG64 PhysicalAddress
;
157 // No local kernel debugging support yet, so don't worry about locking
159 ASSERT(Flags
& MMDBG_COPY_UNSAFE
);
162 // We only handle 1, 2, 4 and 8 byte requests
167 (Size
!= MMDBG_COPY_MAX_SIZE
))
170 // Invalid size, fail
172 KdpDprintf("MmDbgCopyMemory: Received Illegal Size 0x%lx\n", Size
);
173 return STATUS_INVALID_PARAMETER_3
;
177 // The copy must be aligned
179 if ((Address
& (Size
- 1)) != 0)
184 KdpDprintf("MmDbgCopyMemory: Received Unaligned Address 0x%I64x Size %lx\n",
186 return STATUS_INVALID_PARAMETER_3
;
190 // Check if this is physical or virtual copy
192 if (Flags
& MMDBG_COPY_PHYSICAL
)
195 // Physical: translate and map it to our mapping space
197 TargetAddress
= MiDbgTranslatePhysicalAddress(Address
, Flags
);
200 // Check if translation failed
207 KdpDprintf("MmDbgCopyMemory: Failed to Translate Physical Address "
209 return STATUS_UNSUCCESSFUL
;
213 // The address we received must be valid!
215 ASSERT(MmIsAddressValid(TargetAddress
));
220 // Virtual; truncate it to avoid casts later down
222 TargetAddress
= (PVOID
)(ULONG_PTR
)Address
;
225 // Check if the address is invalid
227 if (!MmIsAddressValid(TargetAddress
))
232 KdpDprintf("MmDbgCopyMemory: Failing %s for invalid "
233 "Virtual Address 0x%p\n",
234 Flags
& MMDBG_COPY_WRITE
? "write" : "read",
236 return STATUS_UNSUCCESSFUL
;
240 // No session space support yet
242 ASSERT(MmIsSessionAddress(TargetAddress
) == FALSE
);
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
))
248 /* Not writable, we need to do a physical copy */
249 Flags
|= MMDBG_COPY_PHYSICAL
;
251 /* Calculate the physical address */
252 PhysicalAddress
= PointerPte
->u
.Hard
.PageFrameNumber
<< PAGE_SHIFT
;
253 PhysicalAddress
+= BYTE_OFFSET(Address
);
255 /* Translate the physical address */
256 TargetAddress
= MiDbgTranslatePhysicalAddress(PhysicalAddress
, Flags
);
258 /* Check if translation failed */
262 KdpDprintf("MmDbgCopyMemory: Failed to translate for write "
263 "%I64x (%I64x)\n", PhysicalAddress
, Address
);
264 return STATUS_UNSUCCESSFUL
;
270 // Use SEH to try to catch anything else somewhat cleanly
275 // Check if this is read or write
277 if (Flags
& MMDBG_COPY_WRITE
)
282 RtlCopyMemory(TargetAddress
,
291 RtlCopyMemory(Buffer
,
299 Status
= STATUS_SUCCESS
;
301 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
304 // Get the exception code
306 Status
= _SEH2_GetExceptionCode();
311 // Get rid of the mapping if this was a physical copy
313 if (Flags
& MMDBG_COPY_PHYSICAL
)
316 // Unmap and flush it
318 MiDbgUnTranslatePhysicalAddress();
322 // Return status to caller