[NTOSKRNL] Implement ObSetDirectoryDeviceMap
[reactos.git] / ntoskrnl / mm / ARM3 / mmdbg.c
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 }