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