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 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