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