2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/mm/mmdbg.c
5 * PURPOSE: Memory Manager support routines for the Kernel Debugger
6 * PROGRAMMERS: Stefan Ginsberg (stefan.ginsberg@reactos.org)
9 /* INCLUDES *******************************************************************/
12 #include "ARM3/miarm.h"
16 /* GLOBALS ********************************************************************/
18 PMMPTE MmDebugPte
= MiAddressToPte(MI_DEBUG_MAPPING
);
19 BOOLEAN MiDbgReadyForPhysical
= FALSE
;
21 /* FUNCTIONS ******************************************************************/
25 MmIsSessionAddress(IN PVOID Address
)
28 // No session space support yet
35 MiDbgTranslatePhysicalAddress(IN ULONG64 PhysicalAddress
,
38 extern MMPTE ValidKernelPte
;
41 PVOID MappingBaseAddress
;
44 // Check if we are called too early
46 if (MiDbgReadyForPhysical
== FALSE
)
49 // The structures we require aren't initialized yet, fail
51 KdpDprintf("MiDbgTranslatePhysicalAddress called too early! "
52 "Address: 0x%I64x\n", PhysicalAddress
);
57 // FIXME: No support for cache flags yet
59 if ((Flags
& (MMDBG_COPY_CACHED
|
61 MMDBG_COPY_WRITE_COMBINED
)) != 0)
66 KdpDprintf("MiDbgTranslatePhysicalAddress: Cache Flags not yet supported. "
67 "Flags: 0x%lx\n", Flags
& (MMDBG_COPY_CACHED
|
69 MMDBG_COPY_WRITE_COMBINED
));
74 // Save the base address of our mapping page
76 MappingBaseAddress
= MiPteToAddress(MmDebugPte
);
81 TempPte
= ValidKernelPte
;
84 // Convert physical address to PFN
86 Pfn
= (PFN_NUMBER
)(PhysicalAddress
>> PAGE_SHIFT
);
89 // Check if this could be an I/O mapping
91 if (Pfn
> MmHighestPhysicalPage
)
94 // FIXME: We don't support this yet
96 KdpDprintf("MiDbgTranslatePhysicalAddress: I/O Space not yet supported. "
97 "PFN: 0x%I64x\n", (ULONG64
)Pfn
);
103 // Set the PFN in the PTE
105 TempPte
.u
.Hard
.PageFrameNumber
= Pfn
;
109 // Map the PTE and invalidate its TLB entry
111 *MmDebugPte
= TempPte
;
112 KeInvalidateTlbEntry(MappingBaseAddress
);
115 // Calculate and return the virtual offset into our mapping page
117 return (PVOID
)((ULONG_PTR
)MappingBaseAddress
+
118 BYTE_OFFSET(PhysicalAddress
));
123 MiDbgUnTranslatePhysicalAddress(VOID
)
125 PVOID MappingBaseAddress
= MiPteToAddress(MmDebugPte
);
128 // The address must still be valid at this point
130 ASSERT(MmIsAddressValid(MappingBaseAddress
));
133 // Clear the mapping PTE and invalidate its TLB entry
135 MmDebugPte
->u
.Long
= 0;
136 KeInvalidateTlbEntry(MappingBaseAddress
);
141 MmDbgCopyMemory(IN ULONG64 Address
,
150 // No local kernel debugging support yet, so don't worry about locking
152 ASSERT(Flags
& MMDBG_COPY_UNSAFE
);
155 // We only handle 1, 2, 4 and 8 byte requests
160 (Size
!= MMDBG_COPY_MAX_SIZE
))
163 // Invalid size, fail
165 KdpDprintf("MmDbgCopyMemory: Received Illegal Size 0x%lx\n", Size
);
166 return STATUS_INVALID_PARAMETER_3
;
170 // The copy must be aligned
172 if ((Address
& (Size
- 1)) != 0)
177 KdpDprintf("MmDbgCopyMemory: Received Unaligned Address 0x%I64x Size %lx\n",
179 return STATUS_INVALID_PARAMETER_3
;
183 // Check if this is physical or virtual copy
185 if (Flags
& MMDBG_COPY_PHYSICAL
)
188 // Physical: translate and map it to our mapping space
190 TargetAddress
= MiDbgTranslatePhysicalAddress(Address
, Flags
);
193 // Check if translation failed
200 KdpDprintf("MmDbgCopyMemory: Failed to Translate Physical Address "
202 return STATUS_UNSUCCESSFUL
;
206 // The address we received must be valid!
208 ASSERT(MmIsAddressValid(TargetAddress
));
213 // Virtual; truncate it to avoid casts later down
215 TargetAddress
= (PVOID
)(ULONG_PTR
)Address
;
218 // Check if the address is invalid
220 if (!MmIsAddressValid(TargetAddress
))
225 KdpDprintf("MmDbgCopyMemory: Failing %s for invalid "
226 "Virtual Address 0x%p\n",
227 Flags
& MMDBG_COPY_WRITE
? "write" : "read",
229 return STATUS_UNSUCCESSFUL
;
233 // No session space support yet
235 ASSERT(MmIsSessionAddress(TargetAddress
) == FALSE
);
239 // If we are going to write to the address then make sure it is writeable too
241 if ((Flags
& MMDBG_COPY_WRITE
) &&
242 (!MI_IS_PAGE_WRITEABLE(MiAddressToPte(TargetAddress
))))
245 // Check if we mapped anything
247 if (Flags
& MMDBG_COPY_PHYSICAL
)
250 // Get rid of the mapping
252 MiDbgUnTranslatePhysicalAddress();
258 // FIXME: We should attempt to override the write protection instead of
261 KdpDprintf("MmDbgCopyMemory: Failing Write for Protected Address 0x%p\n",
263 return STATUS_UNSUCCESSFUL
;
267 // Use SEH to try to catch anything else somewhat cleanly
272 // Check if this is read or write
274 if (Flags
& MMDBG_COPY_WRITE
)
279 RtlCopyMemory(TargetAddress
,
288 RtlCopyMemory(Buffer
,
296 Status
= STATUS_SUCCESS
;
298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
301 // Get the exception code
303 Status
= _SEH2_GetExceptionCode();
308 // Get rid of the mapping if this was a physical copy
310 if (Flags
& MMDBG_COPY_PHYSICAL
)
313 // Unmap and flush it
315 MiDbgUnTranslatePhysicalAddress();
319 // Return status to caller