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