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