1 /*****************************************************************************\ 2 * * 3 * This file is current kept ONLY for DOCUMENTATION purposes, until * 4 * we are sure that all the functionality (e.g. regarding the "big pages") * 5 * are fully present in Mm and in mm/ARM3/mmdbg.c that supersedes this file. * 6 * * 7 \*****************************************************************************/ 8 9 /* 10 * COPYRIGHT: See COPYING in the top level directory 11 * PROJECT: ReactOS Kernel 12 * PURPOSE: Kernel Debugger Safe Memory Support 13 * 14 * PROGRAMMERS: arty 15 */ 16 17 #include <ntoskrnl.h> 18 19 #define HIGH_PHYS_MASK 0x80000000 20 #define PAGE_TABLE_MASK 0x3ff 21 #define BIG_PAGE_SIZE (1<<22) 22 #define CR4_PAGE_SIZE_BIT 0x10 23 #define PDE_PRESENT_BIT 0x01 24 #define PDE_W_BIT 0x02 25 #define PDE_PWT_BIT 0x08 26 #define PDE_PCD_BIT 0x10 27 #define PDE_ACCESSED_BIT 0x20 28 #define PDE_DIRTY_BIT 0x40 29 #define PDE_PS_BIT 0x80 30 31 #define MI_KDBG_TMP_PAGE_1 (HYPER_SPACE + 0x400000 - PAGE_SIZE) 32 #define MI_KDBG_TMP_PAGE_0 (MI_KDBG_TMP_PAGE_1 - PAGE_SIZE) 33 34 /* VARIABLES ***************************************************************/ 35 36 static BOOLEAN KdpPhysAccess = FALSE; 37 38 static 39 ULONG_PTR 40 KdpPhysMap(ULONG_PTR PhysAddr, LONG Len) 41 { 42 MMPTE TempPte; 43 PMMPTE PointerPte; 44 ULONG_PTR VirtAddr; 45 46 TempPte.u.Long = PDE_PRESENT_BIT | PDE_W_BIT | PDE_PWT_BIT | 47 PDE_PCD_BIT | PDE_ACCESSED_BIT | PDE_DIRTY_BIT; 48 49 if ((PhysAddr & (PAGE_SIZE - 1)) + Len > PAGE_SIZE) 50 { 51 TempPte.u.Hard.PageFrameNumber = (PhysAddr >> PAGE_SHIFT) + 1; 52 PointerPte = MiAddressToPte((PVOID)MI_KDBG_TMP_PAGE_1); 53 *PointerPte = TempPte; 54 VirtAddr = (ULONG_PTR)PointerPte << 10; 55 KeInvalidateTlbEntry((PVOID)VirtAddr); 56 } 57 58 TempPte.u.Hard.PageFrameNumber = PhysAddr >> PAGE_SHIFT; 59 PointerPte = MiAddressToPte((PVOID)MI_KDBG_TMP_PAGE_0); 60 *PointerPte = TempPte; 61 VirtAddr = (ULONG_PTR)PointerPte << 10; 62 KeInvalidateTlbEntry((PVOID)VirtAddr); 63 64 return VirtAddr + (PhysAddr & (PAGE_SIZE - 1)); 65 } 66 67 static 68 ULONGLONG 69 KdpPhysRead(ULONG_PTR PhysAddr, LONG Len) 70 { 71 ULONG_PTR Addr; 72 ULONGLONG Result = 0; 73 74 Addr = KdpPhysMap(PhysAddr, Len); 75 76 switch (Len) 77 { 78 case 8: 79 Result = *((PULONGLONG)Addr); 80 break; 81 case 4: 82 Result = *((PULONG)Addr); 83 break; 84 case 2: 85 Result = *((PUSHORT)Addr); 86 break; 87 case 1: 88 Result = *((PUCHAR)Addr); 89 break; 90 } 91 92 return Result; 93 } 94 95 static 96 VOID 97 KdpPhysWrite(ULONG_PTR PhysAddr, LONG Len, ULONGLONG Value) 98 { 99 ULONG_PTR Addr; 100 101 Addr = KdpPhysMap(PhysAddr, Len); 102 103 switch (Len) 104 { 105 case 8: 106 *((PULONGLONG)Addr) = Value; 107 break; 108 case 4: 109 *((PULONG)Addr) = Value; 110 break; 111 case 2: 112 *((PUSHORT)Addr) = Value; 113 break; 114 case 1: 115 *((PUCHAR)Addr) = Value; 116 break; 117 } 118 } 119 120 static 121 BOOLEAN 122 KdpTranslateAddress(ULONG_PTR Addr, PULONG_PTR ResultAddr) 123 { 124 ULONG_PTR CR3Value = __readcr3(); 125 ULONG_PTR CR4Value = __readcr4(); 126 ULONG_PTR PageDirectory = (CR3Value & ~(PAGE_SIZE-1)) + 127 ((Addr >> 22) * sizeof(ULONG)); 128 ULONG_PTR PageDirectoryEntry = KdpPhysRead(PageDirectory, sizeof(ULONG)); 129 130 /* Not present -> fail */ 131 if (!(PageDirectoryEntry & PDE_PRESENT_BIT)) 132 { 133 return FALSE; 134 } 135 136 /* Big Page? */ 137 if ((PageDirectoryEntry & PDE_PS_BIT) && (CR4Value & CR4_PAGE_SIZE_BIT)) 138 { 139 *ResultAddr = (PageDirectoryEntry & ~(BIG_PAGE_SIZE-1)) + 140 (Addr & (BIG_PAGE_SIZE-1)); 141 return TRUE; 142 } 143 else 144 { 145 ULONG_PTR PageTableAddr = 146 (PageDirectoryEntry & ~(PAGE_SIZE-1)) + 147 ((Addr >> PAGE_SHIFT) & PAGE_TABLE_MASK) * sizeof(ULONG); 148 ULONG_PTR PageTableEntry = KdpPhysRead(PageTableAddr, sizeof(ULONG)); 149 if (PageTableEntry & PDE_PRESENT_BIT) 150 { 151 *ResultAddr = (PageTableEntry & ~(PAGE_SIZE-1)) + 152 (Addr & (PAGE_SIZE-1)); 153 return TRUE; 154 } 155 } 156 157 return FALSE; 158 } 159 160 BOOLEAN 161 NTAPI 162 KdpSafeReadMemory(ULONG_PTR Addr, LONG Len, PVOID Value) 163 { 164 ULONG_PTR ResultPhysAddr; 165 166 if (!KdpPhysAccess) 167 { 168 memcpy(Value, (PVOID)Addr, Len); 169 return TRUE; 170 } 171 172 memset(Value, 0, Len); 173 174 if (!KdpTranslateAddress(Addr, &ResultPhysAddr)) 175 return FALSE; 176 177 switch (Len) 178 { 179 case 8: 180 *((PULONGLONG)Value) = KdpPhysRead(ResultPhysAddr, Len); 181 break; 182 case 4: 183 *((PULONG)Value) = KdpPhysRead(ResultPhysAddr, Len); 184 break; 185 case 2: 186 *((PUSHORT)Value) = KdpPhysRead(ResultPhysAddr, Len); 187 break; 188 case 1: 189 *((PUCHAR)Value) = KdpPhysRead(ResultPhysAddr, Len); 190 break; 191 } 192 193 return TRUE; 194 } 195 196 BOOLEAN 197 NTAPI 198 KdpSafeWriteMemory(ULONG_PTR Addr, LONG Len, ULONGLONG Value) 199 { 200 ULONG_PTR ResultPhysAddr; 201 202 if (!KdpPhysAccess) 203 { 204 memcpy((PVOID)Addr, &Value, Len); 205 return TRUE; 206 } 207 208 if (!KdpTranslateAddress(Addr, &ResultPhysAddr)) 209 return FALSE; 210 211 KdpPhysWrite(ResultPhysAddr, Len, Value); 212 return TRUE; 213 } 214 215 VOID 216 NTAPI 217 KdpEnableSafeMem(VOID) 218 { 219 KdpPhysAccess = TRUE; 220 } 221 222 /* EOF */ 223