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
12 #include <internal/debug.h>
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 1
20 #define PDE_PS_BIT 0x80
22 /* VARIABLES ***************************************************************/
24 extern ULONG MmGlobalKernelPageDirectory
[1024];
25 static BOOLEAN KdpPhysAccess
= FALSE
;
26 ULONG_PTR IdentityMapAddrHigh
, IdentityMapAddrLow
;
27 extern PFN_TYPE NTAPI
MmAllocEarlyPage();
31 KdpPhysRead(ULONG_PTR Addr
, LONG Len
)
34 ULONG_PTR OldCR3
= __readcr3(), OldCR4
= __readcr4();
36 if (Addr
& HIGH_PHYS_MASK
)
38 Addr
&= ~HIGH_PHYS_MASK
;
39 __writecr3(IdentityMapAddrHigh
);
42 __writecr3(IdentityMapAddrLow
);
44 __writecr4(OldCR4
|CR4_PAGE_SIZE_BIT
); // Turn on large page translation
45 __invlpg((PVOID
)Addr
);
50 Result
= *((PULONGLONG
)Addr
);
53 Result
= *((PULONG
)Addr
);
56 Result
= *((PUSHORT
)Addr
);
59 Result
= *((PUCHAR
)Addr
);
62 __writecr4(OldCR4
); // Turn off large page translation
64 __invlpg((PVOID
)Addr
);
72 KdpPhysWrite(ULONG_PTR Addr
, LONG Len
, ULONGLONG Value
)
74 ULONG_PTR OldCR3
= __readcr3(), OldCR4
= __readcr4();
76 if (Addr
& HIGH_PHYS_MASK
)
78 Addr
&= ~HIGH_PHYS_MASK
;
79 __writecr3(IdentityMapAddrHigh
);
82 __writecr3(IdentityMapAddrLow
);
84 __writecr4(OldCR4
|CR4_PAGE_SIZE_BIT
); // Turn on large page translation
85 __invlpg((PVOID
)Addr
);
90 *((PULONGLONG
)Addr
) = Value
;
93 *((PULONG
)Addr
) = Value
;
96 *((PUSHORT
)Addr
) = Value
;
99 *((PUCHAR
)Addr
) = Value
;
102 __writecr4(OldCR4
); // Turn off large page translation
104 __invlpg((PVOID
)Addr
);
109 KdpTranslateAddress(ULONG_PTR Addr
, PULONG_PTR ResultAddr
)
111 ULONG_PTR CR3Value
= __readcr3();
112 ULONG_PTR CR4Value
= __readcr4();
113 ULONG_PTR PageDirectory
= (CR3Value
& ~(PAGE_SIZE
-1)) +
114 ((Addr
>> 22) * sizeof(ULONG
));
115 ULONG_PTR PageDirectoryEntry
= KdpPhysRead(PageDirectory
, sizeof(ULONG
));
117 /* Not present -> fail */
118 if (!(PageDirectoryEntry
& PDE_PRESENT_BIT
))
124 if ((PageDirectoryEntry
& PDE_PS_BIT
) && (CR4Value
& CR4_PAGE_SIZE_BIT
))
126 *ResultAddr
= (PageDirectoryEntry
& ~(BIG_PAGE_SIZE
-1)) +
127 (Addr
& (BIG_PAGE_SIZE
-1));
132 ULONG_PTR PageTableAddr
=
133 (PageDirectoryEntry
& ~(PAGE_SIZE
-1)) +
134 ((Addr
>> PAGE_SHIFT
) & PAGE_TABLE_MASK
) * sizeof(ULONG
);
135 ULONG_PTR PageTableEntry
= KdpPhysRead(PageTableAddr
, sizeof(ULONG
));
136 if (PageTableEntry
& PDE_PRESENT_BIT
)
138 *ResultAddr
= (PageTableEntry
& ~(PAGE_SIZE
-1)) +
139 (Addr
& (PAGE_SIZE
-1));
149 KdpSafeReadMemory(ULONG_PTR Addr
, LONG Len
, PVOID Value
)
151 ULONG_PTR ResultPhysAddr
;
155 memcpy(Value
, (PVOID
)Addr
, Len
);
159 memset(Value
, 0, Len
);
161 if (!KdpTranslateAddress(Addr
, &ResultPhysAddr
))
167 *((PULONGLONG
)Value
) = KdpPhysRead(ResultPhysAddr
, Len
);
170 *((PULONG
)Value
) = KdpPhysRead(ResultPhysAddr
, Len
);
173 *((PUSHORT
)Value
) = KdpPhysRead(ResultPhysAddr
, Len
);
176 *((PUCHAR
)Value
) = KdpPhysRead(ResultPhysAddr
, Len
);
185 KdpSafeWriteMemory(ULONG_PTR Addr
, LONG Len
, ULONGLONG Value
)
187 ULONG_PTR ResultPhysAddr
;
191 memcpy((PVOID
)Addr
, &Value
, Len
);
195 if (!KdpTranslateAddress(Addr
, &ResultPhysAddr
))
198 KdpPhysWrite(ResultPhysAddr
, Len
, Value
);
207 PULONG IdentityMapVirt
;
208 PHYSICAL_ADDRESS IdentityMapPhys
, Highest
= { };
213 Highest
.LowPart
= (ULONG
)-1;
214 /* Allocate a physical page and map it to copy the phys copy code onto */
215 IdentityMapVirt
= (PULONG
)MmAllocateContiguousMemory(2 * PAGE_SIZE
, Highest
);
216 IdentityMapPhys
= MmGetPhysicalAddress(IdentityMapVirt
);
217 IdentityMapAddrHigh
= IdentityMapPhys
.LowPart
;
219 /* Copy the kernel space */
220 memcpy(IdentityMapVirt
,
221 MmGlobalKernelPageDirectory
,
224 /* Set up 512 4Mb pages (high 2Gig identity mapped) */
225 for (i
= 0; i
< 512; i
++)
228 HIGH_PHYS_MASK
| (i
<< 22) | PDE_PS_BIT
| PDE_W_BIT
| PDE_PRESENT_BIT
;
231 /* Allocate a physical page and map it to copy the phys copy code onto */
232 IdentityMapAddrLow
= IdentityMapAddrHigh
+ PAGE_SIZE
;
233 IdentityMapVirt
+= PAGE_SIZE
/ sizeof(ULONG
);
235 /* Copy the kernel space */
236 memcpy(IdentityMapVirt
,
237 MmGlobalKernelPageDirectory
,
240 /* Set up 512 4Mb pages (low 2Gig identity mapped) */
241 for (i
= 0; i
< 512; i
++)
243 IdentityMapVirt
[i
] = (i
<< 22) | PDE_PS_BIT
| PDE_W_BIT
| PDE_PRESENT_BIT
;
246 KdpPhysAccess
= TRUE
;