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
MiDbgTranslatePhysicalAddress(IN ULONG64 PhysicalAddress,IN ULONG Flags)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
MiDbgUnTranslatePhysicalAddress(VOID)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
MmDbgCopyMemory(IN ULONG64 Address,IN PVOID Buffer,IN ULONG Size,IN ULONG Flags)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 if (!(Flags & MMDBG_COPY_UNSAFE))
136 {
137 static BOOLEAN Warned = FALSE;
138 if (!Warned)
139 {
140 KdpDprintf("MmDbgCopyMemory: not providing MMDBG_COPY_UNSAFE is UNIMPLEMENTED\n");
141 Warned = TRUE;
142 }
143 }
144
145 /* We only handle 1, 2, 4 and 8 byte requests */
146 if ((Size != 1) &&
147 (Size != 2) &&
148 (Size != 4) &&
149 (Size != 8))
150 {
151 /* Invalid size, fail */
152 KdpDprintf("MmDbgCopyMemory: Received Illegal Size 0x%lx\n",
153 Size);
154 return STATUS_INVALID_PARAMETER_3;
155 }
156
157 /* The copy must be aligned */
158 if ((Address & (Size - 1)) != 0)
159 {
160 /* Not allowing unaligned access */
161 KdpDprintf("MmDbgCopyMemory: Received Unaligned Address 0x%I64x Size %lx\n",
162 Address,
163 Size);
164 return STATUS_INVALID_PARAMETER_3;
165 }
166
167 /* Check for physical or virtual copy */
168 if (Flags & MMDBG_COPY_PHYSICAL)
169 {
170 /* Physical: translate and map it to our mapping space */
171 TargetAddress = MiDbgTranslatePhysicalAddress(Address,
172 Flags);
173
174 /* Check if translation failed */
175 if (!TargetAddress)
176 {
177 /* Fail */
178 KdpDprintf("MmDbgCopyMemory: Failed to Translate Physical Address %I64x\n",
179 Address);
180 return STATUS_UNSUCCESSFUL;
181 }
182
183 /* The address we received must be valid! */
184 ASSERT(MmIsAddressValid(TargetAddress));
185 }
186 else
187 {
188 /* Virtual; truncate it to avoid casts later down */
189 TargetAddress = (PVOID)(ULONG_PTR)Address;
190
191 /* Make sure address is valid */
192 if (!MmIsAddressValid(TargetAddress))
193 {
194 /* Fail */
195 KdpDprintf("MmDbgCopyMemory: Failing %s for invalid Virtual Address 0x%p\n",
196 Flags & MMDBG_COPY_WRITE ? "write" : "read",
197 TargetAddress);
198 return STATUS_UNSUCCESSFUL;
199 }
200
201 /* Not handling session space correctly yet */
202 if (MmIsSessionAddress(TargetAddress))
203 {
204 /* FIXME */
205 }
206
207 /* If we are going to write to the address, then check if its writable */
208 PointerPte = MiAddressToPte(TargetAddress);
209 if ((Flags & MMDBG_COPY_WRITE) &&
210 (!MI_IS_PAGE_WRITEABLE(PointerPte)))
211 {
212 /* Not writable, we need to do a physical copy */
213 Flags |= MMDBG_COPY_PHYSICAL;
214
215 /* Calculate the physical address */
216 PhysicalAddress = PointerPte->u.Hard.PageFrameNumber << PAGE_SHIFT;
217 PhysicalAddress += BYTE_OFFSET(Address);
218
219 /* Translate the physical address */
220 TargetAddress = MiDbgTranslatePhysicalAddress(PhysicalAddress,
221 Flags);
222
223 /* Check if translation failed */
224 if (!TargetAddress)
225 {
226 /* Fail */
227 KdpDprintf("MmDbgCopyMemory: Failed to translate for write %I64x (%I64x)\n",
228 PhysicalAddress,
229 Address);
230 return STATUS_UNSUCCESSFUL;
231 }
232 }
233 }
234
235 /* Check what kind of operation this is */
236 if (Flags & MMDBG_COPY_WRITE)
237 {
238 /* Write */
239 CopyDestination = TargetAddress;
240 CopySource = Buffer;
241 }
242 else
243 {
244 /* Read */
245 CopyDestination = Buffer;
246 CopySource = TargetAddress;
247 }
248
249 /* Do the copy */
250 switch (Size)
251 {
252 case 1:
253
254 /* 1 byte */
255 *(PUCHAR)CopyDestination = *(PUCHAR)CopySource;
256 break;
257
258 case 2:
259
260 /* 2 bytes */
261 *(PUSHORT)CopyDestination = *(PUSHORT)CopySource;
262 break;
263
264 case 4:
265
266 /* 4 bytes */
267 *(PULONG)CopyDestination = *(PULONG)CopySource;
268 break;
269
270 case 8:
271
272 /* 8 bytes */
273 *(PULONGLONG)CopyDestination = *(PULONGLONG)CopySource;
274 break;
275
276 /* Size is sanitized above */
277 DEFAULT_UNREACHABLE;
278 }
279
280 /* Get rid of the mapping if this was a physical copy */
281 if (Flags & MMDBG_COPY_PHYSICAL)
282 {
283 /* Unmap and flush it */
284 MiDbgUnTranslatePhysicalAddress();
285 }
286
287 /* And we are done */
288 return STATUS_SUCCESS;
289 }
290