xref: /reactos/ntoskrnl/mm/ARM3/mmdbg.c (revision c2946ced)
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