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