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