Author: tkreuzer
Date: Sat Dec 19 04:43:33 2009
New Revision: 44653
URL:
http://svn.reactos.org/svn/reactos?rev=44653&view=rev
Log:
[MM]
- Improve MiGetPteForProcess
Implement MiGetPteProtection, MiSetPteProtection, MmCreateVirtualMappingUnsafe,
MmCreateVirtualMapping
Modified:
branches/ros-amd64-bringup/reactos/ntoskrnl/mm/amd64/page.c
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/mm/amd64/page.c
URL:
http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntosk…
==============================================================================
--- branches/ros-amd64-bringup/reactos/ntoskrnl/mm/amd64/page.c [iso-8859-1] (original)
+++ branches/ros-amd64-bringup/reactos/ntoskrnl/mm/amd64/page.c [iso-8859-1] Sat Dec 19
04:43:33 2009
@@ -18,6 +18,14 @@
#pragma alloc_text(INIT, MiInitPageDirectoryMap)
#endif
+#undef InterlockedExchangePte
+#define InterlockedExchangePte(pte1, pte2) \
+ InterlockedExchange64(&pte1->u.Long, pte2.u.Long)
+
+#define PAGE_EXECUTE_ANY
(PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)
+#define PAGE_WRITE_ANY
(PAGE_EXECUTE_READWRITE|PAGE_READWRITE|PAGE_EXECUTE_WRITECOPY|PAGE_WRITECOPY)
+#define PAGE_WRITECOPY_ANY (PAGE_EXECUTE_WRITECOPY|PAGE_WRITECOPY)
+
extern MMPTE HyperTemplatePte;
/* GLOBALS *****************************************************************/
@@ -53,7 +61,7 @@
PVOID Address,
BOOLEAN Create)
{
- PMMPTE Pte;
+ MMPTE TmplPte, *Pte;
/* Check if we need hypersapce mapping */
if (Address < MmSystemRangeStart &&
@@ -64,25 +72,33 @@
}
else if (Create)
{
+ TmplPte.u.Long = 0;
+ TmplPte.u.Flush.Valid = 1;
+ TmplPte.u.Flush.Write = 1;
+
/* Get the PXE */
Pte = MiAddressToPxe(Address);
if (!Pte->u.Hard.Valid)
- InterlockedBitTestAndSet64(&Pte->u.Long, 0);
+ {
+ TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE);
+ InterlockedExchangePte(Pte, TmplPte);
+ }
/* Get the PPE */
Pte = MiAddressToPpe(Address);
if (!Pte->u.Hard.Valid)
- InterlockedBitTestAndSet64(&Pte->u.Long, 0);
+ {
+ TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE);
+ InterlockedExchangePte(Pte, TmplPte);
+ }
/* Get the PDE */
Pte = MiAddressToPde(Address);
if (!Pte->u.Hard.Valid)
- InterlockedBitTestAndSet64(&Pte->u.Long, 0);
-
- /* Get the PTE */
- Pte = MiAddressToPte(Address);
-
- return Pte;
+ {
+ TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE);
+ InterlockedExchangePte(Pte, TmplPte);
+ }
}
else
{
@@ -100,14 +116,9 @@
Pte = MiAddressToPde(Address);
if (!Pte->u.Hard.Valid)
return NULL;
-
- /* Get the PTE */
- Pte = MiAddressToPte(Address);
-
- return Pte;
- }
-
- return 0;
+ }
+
+ return MiAddressToPte(Address);
}
static
@@ -128,75 +139,11 @@
return PteValue;
}
-
-/* FUNCTIONS ***************************************************************/
-
-PFN_NUMBER
-NTAPI
-MmGetPfnForProcess(PEPROCESS Process,
- PVOID Address)
-{
- MMPTE Pte;
- Pte.u.Long = MiGetPteValueForProcess(Process, Address);
- return Pte.u.Hard.Valid ? Pte.u.Hard.PageFrameNumber : 0;
-}
-
-PHYSICAL_ADDRESS
-NTAPI
-MmGetPhysicalAddress(PVOID Address)
-{
- PHYSICAL_ADDRESS p;
- MMPTE Pte;
-
- Pte.u.Long = MiGetPteValueForProcess(NULL, Address);
- if (Pte.u.Hard.Valid)
- {
- p.QuadPart = Pte.u.Hard.PageFrameNumber * PAGE_SIZE;
- p.u.LowPart |= (ULONG_PTR)Address & (PAGE_SIZE - 1);
- }
- else
- {
- p.QuadPart = 0;
- }
-
- return p;
-}
-
-BOOLEAN
-NTAPI
-MmIsPagePresent(PEPROCESS Process, PVOID Address)
-{
- MMPTE Pte;
- Pte.u.Long = MiGetPteValueForProcess(Process, Address);
- return Pte.u.Hard.Valid;
-}
-
-BOOLEAN
-NTAPI
-MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
-{
- MMPTE Pte;
- Pte.u.Long = MiGetPteValueForProcess(Process, Address);
- return Pte.u.Hard.Valid && Pte.u.Soft.Transition;
-}
-
-BOOLEAN
-NTAPI
-MmIsDirtyPage(PEPROCESS Process, PVOID Address)
-{
- MMPTE Pte;
- Pte.u.Long = MiGetPteValueForProcess(Process, Address);
- return Pte.u.Hard.Valid && Pte.u.Hard.Dirty;
-}
-
ULONG
NTAPI
-MmGetPageProtect(PEPROCESS Process, PVOID Address)
-{
- MMPTE Pte;
+MiGetPteProtection(MMPTE Pte)
+{
ULONG Protect;
-
- Pte.u.Long = MiGetPteValueForProcess(Process, Address);
if (!Pte.u.Flush.Valid)
{
@@ -228,11 +175,93 @@
Protect |= PAGE_WRITETHROUGH;
// PAGE_GUARD ?
-
return Protect;
}
-#define PAGE_EXECUTE_ANY
(PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)
+VOID
+NTAPI
+MiSetPteProtection(PMMPTE Pte, ULONG Protection)
+{
+ Pte->u.Flush.CopyOnWrite = (Protection & PAGE_WRITECOPY_ANY) ? 1 : 0;
+ Pte->u.Flush.Write = (Protection & PAGE_WRITE_ANY) ? 1 : 0;
+ Pte->u.Flush.CacheDisable = (Protection & PAGE_NOCACHE) ? 1 : 0;
+ Pte->u.Flush.WriteThrough = (Protection & PAGE_WRITETHROUGH) ? 1 : 0;
+
+ // FIXME: This doesn't work. Why?
+// Pte->u.Flush.NoExecute = (Protection & PAGE_EXECUTE_ANY) ? 0 : 1;
+}
+
+/* FUNCTIONS ***************************************************************/
+
+PFN_NUMBER
+NTAPI
+MmGetPfnForProcess(PEPROCESS Process,
+ PVOID Address)
+{
+ MMPTE Pte;
+ Pte.u.Long = MiGetPteValueForProcess(Process, Address);
+ return Pte.u.Hard.Valid ? Pte.u.Hard.PageFrameNumber : 0;
+}
+
+PHYSICAL_ADDRESS
+NTAPI
+MmGetPhysicalAddress(PVOID Address)
+{
+ PHYSICAL_ADDRESS p;
+ MMPTE Pte;
+
+ Pte.u.Long = MiGetPteValueForProcess(NULL, Address);
+ if (Pte.u.Hard.Valid)
+ {
+ p.QuadPart = Pte.u.Hard.PageFrameNumber * PAGE_SIZE;
+ p.u.LowPart |= (ULONG_PTR)Address & (PAGE_SIZE - 1);
+ }
+ else
+ {
+ p.QuadPart = 0;
+ }
+
+ return p;
+}
+
+BOOLEAN
+NTAPI
+MmIsPagePresent(PEPROCESS Process, PVOID Address)
+{
+ MMPTE Pte;
+ Pte.u.Long = MiGetPteValueForProcess(Process, Address);
+ return Pte.u.Hard.Valid;
+}
+
+BOOLEAN
+NTAPI
+MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
+{
+ MMPTE Pte;
+ Pte.u.Long = MiGetPteValueForProcess(Process, Address);
+ return Pte.u.Hard.Valid && Pte.u.Soft.Transition;
+}
+
+BOOLEAN
+NTAPI
+MmIsDirtyPage(PEPROCESS Process, PVOID Address)
+{
+ MMPTE Pte;
+ Pte.u.Long = MiGetPteValueForProcess(Process, Address);
+ return Pte.u.Hard.Valid && Pte.u.Hard.Dirty;
+}
+
+ULONG
+NTAPI
+MmGetPageProtect(PEPROCESS Process, PVOID Address)
+{
+ MMPTE Pte;
+ ULONG Protect;
+
+ Pte.u.Long = MiGetPteValueForProcess(Process, Address);
+
+ return MiGetPteProtection(Pte);
+}
VOID
NTAPI
@@ -241,27 +270,14 @@
PMMPTE Pte;
MMPTE NewPte;
- if (!(flProtect & PAGE_EXECUTE_ANY))
- NewPte.u.Flush.NoExecute = 1;
-
- if (flProtect & (PAGE_EXECUTE_WRITECOPY|PAGE_WRITECOPY))
- {
- NewPte.u.Flush.Write = 1;
- NewPte.u.Flush.CopyOnWrite = 1;
- }
-
- if (flProtect & (PAGE_EXECUTE_READWRITE|PAGE_READWRITE))
- NewPte.u.Flush.Write = 1;
-
- if (flProtect & PAGE_NOCACHE)
- NewPte.u.Flush.CacheDisable = 1;
-
- if (flProtect & PAGE_WRITETHROUGH)
- NewPte.u.Flush.WriteThrough = 1;
-
Pte = MiGetPteForProcess(Process, Address, FALSE);
-
- InterlockedExchange64(&Pte->u.Long, NewPte.u.Long);
+ ASSERT(Pte != NULL);
+
+ NewPte = *Pte;
+
+ MiSetPteProtection(&NewPte, flProtect);
+
+ InterlockedExchangePte(Pte, NewPte);
MiFlushTlb(Pte, Address);
}
@@ -409,26 +425,74 @@
NTSTATUS
NTAPI
-MmCreateVirtualMappingUnsafe(PEPROCESS Process,
- PVOID Address,
- ULONG flProtect,
- PPFN_NUMBER Pages,
- ULONG PageCount)
-{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;
+MmCreateVirtualMappingUnsafe(
+ PEPROCESS Process,
+ PVOID Address,
+ ULONG PageProtection,
+ PPFN_NUMBER Pages,
+ ULONG PageCount)
+{
+ ULONG i;
+ MMPTE TmplPte, *Pte;
+
+ /* Check if the range is valid */
+ if ((Process == NULL && Address < MmSystemRangeStart) ||
+ (Process != NULL && Address > MmHighestUserAddress))
+ {
+ DPRINT1("Address 0x%p is invalid for process %p\n", Address, Process);
+ ASSERT(FALSE);
+ }
+
+ TmplPte.u.Long = 0;
+ TmplPte.u.Hard.Valid = 1;
+ MiSetPteProtection(&TmplPte, PageProtection);
+
+//__debugbreak();
+
+ for (i = 0; i < PageCount; i++)
+ {
+ TmplPte.u.Hard.PageFrameNumber = Pages[i];
+
+ Pte = MiGetPteForProcess(Process, Address, TRUE);
+
+DPRINT1("MmCreateVirtualMappingUnsafe, Address=%p, TmplPte=%p, Pte=%p\n",
+ Address, TmplPte.u.Long, Pte);
+
+ if (InterlockedExchangePte(Pte, TmplPte))
+ {
+ KeInvalidateTlbEntry(Address);
+ }
+
+ if (MiIsHyperspaceAddress(Pte))
+ MmDeleteHyperspaceMapping((PVOID)PAGE_ROUND_DOWN(Pte));
+
+ Address = (PVOID)((ULONG64)Address + PAGE_SIZE);
+ }
+
+
+ return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
MmCreateVirtualMapping(PEPROCESS Process,
PVOID Address,
- ULONG flProtect,
+ ULONG Protect,
PPFN_NUMBER Pages,
ULONG PageCount)
{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;
+ ULONG i;
+
+ for (i = 0; i < PageCount; i++)
+ {
+ if (!MmIsPageInUse(Pages[i]))
+ {
+ DPRINT1("Page %x not in use\n", Pages[i]);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ }
+
+ return MmCreateVirtualMappingUnsafe(Process, Address, Protect, Pages, PageCount);
}
NTSTATUS