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
KdpPhysMap(ULONG_PTR PhysAddr,LONG Len)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
KdpPhysRead(ULONG_PTR PhysAddr,LONG Len)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
KdpPhysWrite(ULONG_PTR PhysAddr,LONG Len,ULONGLONG Value)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
KdpTranslateAddress(ULONG_PTR Addr,PULONG_PTR ResultAddr)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
KdpSafeReadMemory(ULONG_PTR Addr,LONG Len,PVOID Value)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
KdpSafeWriteMemory(ULONG_PTR Addr,LONG Len,ULONGLONG Value)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
KdpEnableSafeMem(VOID)217 KdpEnableSafeMem(VOID)
218 {
219 KdpPhysAccess = TRUE;
220 }
221
222 /* EOF */
223