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