xref: /reactos/ntoskrnl/kdbg/i386/kdmemsup.c (revision 6fafe54f)
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