reactos/ntoskrnl/mm/i386
diff -u -r1.71 -r1.72
--- page.c 19 Aug 2004 21:47:51 -0000 1.71
+++ page.c 7 Sep 2004 11:08:16 -0000 1.72
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: page.c,v 1.71 2004/08/19 21:47:51 hbirr Exp $
+/* $Id: page.c,v 1.72 2004/09/07 11:08:16 hbirr Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/i386/page.c
@@ -57,9 +57,10 @@
ULONG MmGlobalKernelPageDirectory[1024] = {0, };
-#if defined(__GNUC__)
#define PTE_TO_PFN(X) ((X) >> PAGE_SHIFT)
#define PFN_TO_PTE(X) ((X) << PAGE_SHIFT)
+
+#if defined(__GNUC__)
#define PTE_TO_PAGE(X) ((LARGE_INTEGER)(LONGLONG)(PAGE_MASK(X)))
#else
__inline LARGE_INTEGER PTE_TO_PAGE(ULONG npage)
@@ -119,18 +120,22 @@
return(Attributes);
}
-#define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (4 * 1024 * 1024))
+#define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (1024 * PAGE_SIZE))
#define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \
((((ULONG)(v)) / (1024 * 1024))&(~0x3)))
#define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((((ULONG)(v) / 1024))&(~0x3)))
-#define ADDR_TO_PDE_OFFSET(v) ((((ULONG)(v)) / (4 * 1024 * 1024)))
+#define ADDR_TO_PDE_OFFSET(v) ((((ULONG)(v)) / (1024 * PAGE_SIZE)))
+
+#define ADDR_TO_PTE_OFFSET(v) ((((ULONG)(v)) % (1024 * PAGE_SIZE)) / PAGE_SIZE)
NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process)
{
PUSHORT LdtDescriptor;
ULONG LdtBase;
+ PULONG PageDir, Pde;
+ ULONG i, j;
DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process);
@@ -145,6 +150,38 @@
{
ExFreePool((PVOID) LdtBase);
}
+ PageDir = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT);
+ for (i = 0; i < ADDR_TO_PDE_OFFSET(KERNEL_BASE); i++)
+ {
+ if (PageDir[i] != 0)
+ {
+ DPRINT1("Pde for %08x - %08x is not freed, RefCount %d\n",
+ i * 4 * 1024 * 1024, (i + 1) * 4 * 1024 * 1024 - 1,
+ Process->AddressSpace.PageTableRefCountTable[i]);
+ Pde = ExAllocatePageWithPhysPage(PageDir[i] >> PAGE_SHIFT);
+ for (j = 0; j < 1024; j++)
+ {
+ if(Pde[j] != 0)
+ {
+ if (Pde[j] & PA_PRESENT)
+ {
+ DPRINT1("Page at %08x is not freed\n",
+ i * 4 * 1024 * 1024 + j * PAGE_SIZE);
+ }
+ else
+ {
+ DPRINT1("Swapentry %x at %x is not freed\n",
+ Pde[j], i * 4 * 1024 * 1024 + j * PAGE_SIZE);
+ }
+
+ }
+ }
+ ExUnmapPage(Pde);
+ MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[i]));
+ }
+ }
+ ExUnmapPage(PageDir);
+
MmReleasePageMemoryConsumer(MC_NPPOOL, Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT);
#if defined(__GNUC__)
@@ -229,7 +266,7 @@
if (PageTable[i] != 0)
{
DbgPrint("Page table entry not clear at %x/%x (is %x)\n",
- ((ULONG)Address / 4*1024*1024), i, PageTable[i]);
+ ((ULONG)Address / (4*1024*1024)), i, PageTable[i]);
KEBUGCHECK(0);
}
}
@@ -252,102 +289,133 @@
}
}
-static PULONG MmGetPageEntry(PVOID PAddress, BOOL CreatePde)
-/*
- * FUNCTION: Get a pointer to the page table entry for a virtual address
- */
+static PULONG
+MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
{
- PULONG Pde, kePde;
- PFN_TYPE Pfn;
- ULONG Attributes;
+ ULONG PdeOffset = ADDR_TO_PDE_OFFSET(Address);
NTSTATUS Status;
-
- DPRINT("MmGetPageEntry(Address %x)\n", PAddress);
-
- Pde = ADDR_TO_PDE(PAGE_ROUND_DOWN(PAddress));
- if (*Pde == 0)
+ PFN_TYPE Pfn;
+ ULONG Entry;
+ PULONG Pt, PageDir;
+
+ if (Address < (PVOID)KERNEL_BASE && Process && Process != PsGetCurrentProcess())
+ {
+ PageDir = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT);
+ if (PageDir == NULL)
+ {
+ KEBUGCHECK(0);
+ }
+ if (PageDir[PdeOffset] == 0)
+ {
+ if (Create == FALSE)
+ {
+ ExUnmapPage(PageDir);
+ return NULL;
+ }
+ Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
+ if (!NT_SUCCESS(Status) || Pfn == 0)
+ {
+ KEBUGCHECK(0);
+ }
+ Entry = InterlockedCompareExchange(&PageDir[PdeOffset], PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
+ if (Entry != 0)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
+ Pfn = PTE_TO_PFN(Entry);
+ }
+ }
+ else
+ {
+ Pfn = PTE_TO_PFN(PageDir[PdeOffset]);
+ }
+ ExUnmapPage(PageDir);
+ DPRINT("%d\n", Pfn);
+ Pt = ExAllocatePageWithPhysPage(Pfn);
+ if (Pt == NULL)
+ {
+ KEBUGCHECK(0);
+ }
+ return Pt + ADDR_TO_PTE_OFFSET(Address);
+ }
+ PageDir = ADDR_TO_PDE(Address);
+ if (*PageDir == 0)
{
- if (PAddress >= (PVOID)KERNEL_BASE)
+ if (Address >= (PVOID)KERNEL_BASE)
{
- kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress);
- if (*kePde == 0)
+ if (MmGlobalKernelPageDirectory[PdeOffset] == 0)
{
- if (CreatePde == FALSE)
- {
+ if (Create == FALSE)
+ {
return NULL;
- }
+ }
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
- if (!NT_SUCCESS(Status) || Pfn == 0)
- {
- KEBUGCHECK(0);
- }
- Attributes = PA_PRESENT | PA_READWRITE;
+ if (!NT_SUCCESS(Status) || Pfn == 0)
+ {
+ KEBUGCHECK(0);
+ }
+ Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE;
if (Ke386CpuidFlags & X86_FEATURE_PGE)
{
- Attributes |= PA_GLOBAL;
+ Entry |= PA_GLOBAL;
}
- if (0 == InterlockedCompareExchange(kePde, PFN_TO_PTE(Pfn) | Attributes, 0))
+ if(0 != InterlockedCompareExchange(&MmGlobalKernelPageDirectory[PdeOffset], Entry, 0))
{
- Pfn = 0;
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
}
- else
- {
- Pfn = 0;
- }
- *Pde = *kePde;
-#if 0
- /* Non existing mappings are not cached within the tlb. We must not invalidate this entry */
- FLUSH_TLB_ONE(ADDR_TO_PTE(PAddress));
-#endif
+ *PageDir =MmGlobalKernelPageDirectory[PdeOffset];
}
else
{
- if (CreatePde == FALSE)
- {
+ if (Create == FALSE)
+ {
return NULL;
- }
+ }
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
- if (!NT_SUCCESS(Status) || Pfn == 0)
- {
- KEBUGCHECK(0);
- }
- if (0 == InterlockedCompareExchange(Pde, PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0))
+ if (!NT_SUCCESS(Status) || Pfn == 0)
{
- Pfn = 0;
+ KEBUGCHECK(0);
+ }
+ Entry = InterlockedCompareExchange(PageDir, PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
+ if (Entry != 0)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
-#if 0
- /* Non existing mappings are not cached within the tlb. We must not invalidate this entry */
- FLUSH_TLB_ONE(ADDR_TO_PTE(PAddress));
-#endif
- }
- if (Pfn != 0)
- {
- MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
}
- return (PULONG)ADDR_TO_PTE(PAddress);
+ return (PULONG)ADDR_TO_PTE(Address);
}
-static ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
+BOOLEAN MmUnmapPageTable(PULONG Pt)
{
- PULONG Pte;
- ULONG oldPte;
- PEPROCESS CurrentProcess = PsGetCurrentProcess();
-
- if (Process != NULL && Process != CurrentProcess)
+ if (Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024)
{
- KeAttachProcess(Process);
+ return TRUE;
}
- Pte = MmGetPageEntry(Address, FALSE);
- oldPte = Pte != NULL ? *Pte : 0;
- if (Process != NULL && Process != CurrentProcess)
+ if (Pt)
{
- KeDetachProcess();
+ ExUnmapPage((PVOID)PAGE_ROUND_DOWN(Pt));
}
- return oldPte;
+ return FALSE;
+
}
+static ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
+{
+ ULONG Pte;
+ PULONG Pt;
+
+ Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+ if (Pt)
+ {
+ Pte = *Pt;
+
+ MmUnmapPageTable(Pt);
+ return Pte;
+ }
+ return 0;
+}
+
PFN_TYPE
MmGetPfnForProcess(PEPROCESS Process,
PVOID Address)
@@ -369,44 +437,33 @@
* FUNCTION: Delete a virtual mapping
*/
{
- PULONG Pte;
- ULONG oldPte;
- PEPROCESS CurrentProcess = PsGetCurrentProcess();
+ ULONG Pte;
+ PULONG Pt;
BOOLEAN WasValid;
- /*
- * If we are setting a page in another process we need to be in its
- * context.
- */
- if (Process != NULL && Process != CurrentProcess)
- {
- KeAttachProcess(Process);
- }
-
- Pte = MmGetPageEntry(Address, FALSE);
- if (Pte == NULL)
+ Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+ if (Pt == NULL)
{
KEBUGCHECK(0);
}
+
/*
* Atomically set the entry to zero and get the old value.
*/
- oldPte = *Pte;
- *Pte = oldPte & (~PA_PRESENT);
- FLUSH_TLB_ONE(Address);
- WasValid = (PAGE_MASK(oldPte) != 0);
- if (!WasValid)
+ do
{
- KEBUGCHECK(0);
- }
+ Pte = *Pt;
+ } while (Pte != InterlockedCompareExchange(Pt, Pte & ~PA_PRESENT, Pte));
- /*
- * If necessary go back to the original context
- */
- if (Process != NULL && Process != CurrentProcess)
+ if (MmUnmapPageTable(Pt) || Address >= (PVOID)KERNEL_BASE)
{
- KeDetachProcess();
+ FLUSH_TLB_ONE(Address);
+ }
+ WasValid = (PAGE_MASK(Pte) != 0);
+ if (!WasValid)
+ {
+ KEBUGCHECK(0);
}
/*
@@ -414,31 +471,26 @@
*/
if (WasDirty != NULL)
{
- *WasDirty = oldPte & PA_DIRTY;
+ *WasDirty = Pte & PA_DIRTY;
}
if (Page != NULL)
{
- *Page = PTE_TO_PFN(oldPte);
+ *Page = PTE_TO_PFN(Pte);
}
}
VOID
MmRawDeleteVirtualMapping(PVOID Address)
{
- PULONG Pte;
+ PULONG Pt;
- /*
- * Set the page directory entry, we may have to copy the entry from
- * the global page directory.
- */
-
- Pte = MmGetPageEntry(Address, FALSE);
- if (Pte)
+ Pt = MmGetPageTableForProcess(NULL, Address, FALSE);
+ if (Pt && *Pt)
{
/*
* Set the entry to zero
*/
- *Pte = 0;
+ *Pt = 0;
FLUSH_TLB_ONE(Address);
}
}
@@ -450,27 +502,17 @@
* FUNCTION: Delete a virtual mapping
*/
{
- ULONG oldPte;
- PULONG Pte;
- PEPROCESS CurrentProcess = PsGetCurrentProcess();
+ ULONG Pte;
+ PULONG Pt;
BOOLEAN WasValid;
- /*
- * If we are setting a page in another process we need to be in its
- * context.
- */
- if (Process != NULL && Process != CurrentProcess)
- {
- KeAttachProcess(Process);
- }
+ DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n",
+ Process, Address, FreePage, WasDirty, Page);
+
+ Pt = MmGetPageTableForProcess(Process, Address, FALSE);
- Pte = MmGetPageEntry(Address, FALSE);
- if (Pte == NULL)
+ if (Pt == NULL)
{
- if (Process != NULL && Process != CurrentProcess)
- {
- KeDetachProcess();
- }
if (WasDirty != NULL)
{
*WasDirty = FALSE;
@@ -485,19 +527,22 @@
/*
* Atomically set the entry to zero and get the old value.
*/
- oldPte = InterlockedExchange(Pte, 0);
- if (oldPte)
+ Pte = InterlockedExchange(Pt, 0);
+
+ if ((MmUnmapPageTable(Pt) || Address >=(PVOID)KERNEL_BASE) && Pte)
{
- FLUSH_TLB_ONE(Address);
+ FLUSH_TLB_ONE(Address);
}
- WasValid = (PAGE_MASK(oldPte) != 0);
+
+ WasValid = (PAGE_MASK(Pte) != 0);
if (WasValid)
{
- MmMarkPageUnmapped(PTE_TO_PFN(oldPte));
+ MmMarkPageUnmapped(PTE_TO_PFN(Pte));
}
+
if (FreePage && WasValid)
{
- MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(oldPte));
+ MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(Pte));
}
/*
@@ -519,23 +564,15 @@
}
/*
- * If necessary go back to the original context
- */
- if (Process != NULL && Process != CurrentProcess)
- {
- KeDetachProcess();
- }
-
- /*
* Return some information to the caller
*/
if (WasDirty != NULL)
{
- *WasDirty = oldPte & PA_DIRTY ? TRUE : FALSE;
+ *WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
}
if (Page != NULL)
{
- *Page = PTE_TO_PFN(oldPte);
+ *Page = PTE_TO_PFN(Pte);
}
}
@@ -546,28 +583,13 @@
* FUNCTION: Delete a virtual mapping
*/
{
- ULONG oldPte;
- PULONG Pte;
- PEPROCESS CurrentProcess = PsGetCurrentProcess();
- BOOLEAN WasValid = FALSE;
-
- /*
- * If we are setting a page in another process we need to be in its
- * context.
- */
- if (Process != NULL && Process != CurrentProcess)
- {
- KeAttachProcess(Process);
- }
+ ULONG Pte;
+ PULONG Pt;
- Pte = MmGetPageEntry(Address, FALSE);
+ Pt = MmGetPageTableForProcess(Process, Address, FALSE);
- if (Pte == NULL)
+ if (Pt == NULL)
{
- if (Process != NULL && Process != CurrentProcess)
- {
- KeDetachProcess();
- }
*SwapEntry = 0;
return;
}
@@ -575,17 +597,19 @@
/*
* Atomically set the entry to zero and get the old value.
*/
- oldPte = InterlockedExchange(Pte, 0);
- FLUSH_TLB_ONE(Address);
+ Pte = InterlockedExchange(Pt, 0);
- WasValid = PAGE_MASK(oldPte) == 0 ? FALSE : TRUE;
+ if (MmUnmapPageTable(Pt) || Address >= (PVOID)KERNEL_BASE)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
/*
* Decrement the reference count for this page table.
*/
- if (Process != NULL && WasValid &&
- Process->AddressSpace.PageTableRefCountTable != NULL &&
- Address < (PVOID)KERNEL_BASE)
+ if (Process != NULL && Pte &&
+ Process->AddressSpace.PageTableRefCountTable != NULL &&
+ Address < (PVOID)KERNEL_BASE)
{
PUSHORT Ptrc;
@@ -598,34 +622,28 @@
}
}
- /*
- * If necessary go back to the original context
- */
- if (Process != NULL && Process != CurrentProcess)
- {
- KeDetachProcess();
- }
/*
* Return some information to the caller
*/
- *SwapEntry = oldPte >> 1;
+ *SwapEntry = Pte >> 1;
}
BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
{
- PULONG Pte, Pde;
+ PULONG Pt, Pde;
+
Pde = ADDR_TO_PDE(PAddress);
if (*Pde == 0)
{
- Pte = MmGetPageEntry(PAddress, FALSE);
+ Pt = MmGetPageTableForProcess(NULL, PAddress, FALSE);
#if 0
/* Non existing mappings are not cached within the tlb. We must not invalidate this entry */
FLASH_TLB_ONE(PAddress);
#endif
- if (Pte != NULL)
+ if (Pt != NULL)
{
return TRUE;
}
@@ -641,145 +659,136 @@
BOOLEAN
MmIsAccessedAndResetAccessPage(PEPROCESS Process, PVOID Address)
{
- ULONG oldPte;
- PULONG Pte;
- PEPROCESS CurrentProcess;
+ PULONG Pt;
+ ULONG Pte;
- if (Process)
+ if (Address < (PVOID)KERNEL_BASE && Process == NULL)
{
- CurrentProcess = PsGetCurrentProcess();
- if (Process != CurrentProcess)
- {
- KeAttachProcess(Process);
- }
- }
- else
- {
- if (((ULONG)Address & ~0xFFF) < KERNEL_BASE)
- {
- DPRINT1("MmIsAccessedAndResetAccessPage is called for user space without a process.\n");
- KEBUGCHECK(0);
- }
- CurrentProcess = NULL;
+ DPRINT1("MmIsAccessedAndResetAccessPage is called for user space without a process.\n");
+ KEBUGCHECK(0);
}
- Pte = MmGetPageEntry(Address, FALSE);
- if (Pte == NULL)
+ Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+ if (Pt == NULL)
{
KEBUGCHECK(0);
}
- oldPte = *Pte;
- if (oldPte & PA_ACCESSED)
+
+ do
{
- *Pte = *Pte & (~PA_ACCESSED);
- FLUSH_TLB_ONE(Address);
+ Pte = *Pt;
+ } while (Pte != InterlockedCompareExchange(Pt, Pte & ~PA_ACCESSED, Pte));
+
+ if (Pte & PA_ACCESSED)
+ {
+ if (MmUnmapPageTable(Pt) || Address >= (PVOID)KERNEL_BASE)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
+ return TRUE;
}
- if (Process != CurrentProcess)
+ else
{
- KeDetachProcess();
+ MmUnmapPageTable(Pt);
+ return FALSE;
}
-
- return oldPte & PA_ACCESSED ? TRUE : FALSE;
}
VOID MmSetCleanPage(PEPROCESS Process, PVOID Address)
{
- PULONG Pte;
- PEPROCESS CurrentProcess;
+ PULONG Pt;
+ ULONG Pte;
- if (Process)
+ if (Address < (PVOID)KERNEL_BASE && Process == NULL)
{
- CurrentProcess = PsGetCurrentProcess();
- if (Process != CurrentProcess)
- {
- KeAttachProcess(Process);
- }
- }
- else
- {
- if (Address < (PVOID)KERNEL_BASE)
- {
- DPRINT1("MmSetCleanPage is called for user space without a process.\n");
- KEBUGCHECK(0);
- }
- CurrentProcess = NULL;
+ DPRINT1("MmSetCleanPage is called for user space without a process.\n");
+ KEBUGCHECK(0);
}
- Pte = MmGetPageEntry(Address, FALSE);
- if (Pte == NULL)
+
+ Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+
+ if (Pt == NULL)
{
KEBUGCHECK(0);
}
- if (*Pte & PA_DIRTY)
+
+ do
{
- *Pte = *Pte & (~PA_DIRTY);
- FLUSH_TLB_ONE(Address);
+ Pte = *Pt;
+ } while (Pte != InterlockedCompareExchange(Pt, Pte & ~PA_DIRTY, Pte));
+
+ if (Pte & PA_DIRTY)
+ {
+ if (MmUnmapPageTable(Pt) || Address > (PVOID)KERNEL_BASE)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
}
- if (Process != CurrentProcess)
+ else
{
- KeDetachProcess();
+ MmUnmapPageTable(Pt);
}
}
VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address)
{
- PULONG Pte;
- PEPROCESS CurrentProcess = NULL;
+ PULONG Pt;
+ ULONG Pte;
- if (Process)
- {
- CurrentProcess = PsGetCurrentProcess();
- if (Process != CurrentProcess)
- {
- KeAttachProcess(Process);
- }
- }
- else
+ if (Address < (PVOID)KERNEL_BASE && Process == NULL)
{
- if (Address < (PVOID)KERNEL_BASE)
- {
- DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
- KEBUGCHECK(0);
- }
- CurrentProcess = NULL;
+ DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
+ KEBUGCHECK(0);
}
- Pte = MmGetPageEntry(Address, FALSE);
- if (Pte == NULL)
+
+ Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+ if (Pt == NULL)
{
KEBUGCHECK(0);
}
- if (!(*Pte & PA_DIRTY))
+
+ do
{
- *Pte = *Pte | PA_DIRTY;
- FLUSH_TLB_ONE(Address);
+ Pte = *Pt;
+ } while (Pte != InterlockedCompareExchange(Pt, Pte | PA_DIRTY, Pte));
+ if (!(Pte & PA_DIRTY))
+ {
+ if (MmUnmapPageTable(Pt) || Address > (PVOID)KERNEL_BASE)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
}
- if (Process != CurrentProcess)
+ else
{
- KeDetachProcess();
+ MmUnmapPageTable(Pt);
}
}
VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
{
- PULONG Pte;
- PEPROCESS CurrentProcess = PsGetCurrentProcess();
+ PULONG Pt;
+ ULONG Pte;
- if (Process != CurrentProcess)
- {
- KeAttachProcess(Process);
- }
- Pte = MmGetPageEntry(Address, FALSE);
- if (Pte == NULL)
+ Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+ if (Pt == NULL)
{
KEBUGCHECK(0);
}
- if (!(*Pte & PA_PRESENT))
+
+ do
{
- *Pte = *Pte | PA_PRESENT;
- FLUSH_TLB_ONE(Address);
+ Pte = *Pt;
+ } while (Pte != InterlockedCompareExchange(Pt, Pte | PA_PRESENT, Pte));
+ if (!(Pte & PA_PRESENT))
+ {
+ if (MmUnmapPageTable(Pt) || Address > (PVOID)KERNEL_BASE)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
}
- if (Process != CurrentProcess)
+ else
{
- KeDetachProcess();
+ MmUnmapPageTable(Pt);
}
}
@@ -801,10 +810,14 @@
PPFN_TYPE Pages,
ULONG PageCount)
{
- ULONG Attributes, oldPte;
- PULONG Pte;
+ ULONG Attributes, Pte;
+ PULONG Pt;
ULONG i;
PVOID Addr;
+ ULONG PdeOffset, oldPdeOffset;
+
+ DPRINT("MmCreateVirtualMappingForKernel(%x, %x, %x, %d)\n",
+ Address, flProtect, Pages, PageCount);
if (Address < (PVOID)KERNEL_BASE)
{
@@ -817,7 +830,16 @@
{
Attributes |= PA_GLOBAL;
}
+
Addr = Address;
+ oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr);
+ Pt = MmGetPageTableForProcess(NULL, Addr, TRUE);
+ if (Pt == NULL)
+ {
+ KEBUGCHECK(0);
+ }
+ Pt--;
+
for (i = 0; i < PageCount; i++, Addr += PAGE_SIZE)
{
if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
@@ -828,21 +850,28 @@
KEBUGCHECK(0);
}
- Pte = MmGetPageEntry(Addr, TRUE);
- if (Pte == NULL)
+ PdeOffset = ADDR_TO_PDE_OFFSET(Addr);
+ if (oldPdeOffset != PdeOffset)
{
- KEBUGCHECK(0);
+ Pt = MmGetPageTableForProcess(NULL, Addr, TRUE);
+ if (Pt == NULL)
+ {
+ KEBUGCHECK(0);
+ }
}
- oldPte = *Pte;
- if (PAGE_MASK((oldPte)) != 0)
+ else
{
- KEBUGCHECK(0);
+ Pt++;
}
- *Pte = PFN_TO_PTE(Pages[i]) | Attributes;
- if (oldPte != 0)
+ oldPdeOffset = PdeOffset;
+
+ Pte = *Pt;
+ if (Pte != 0)
{
- FLUSH_TLB_ONE(Addr);
+ DPRINT1("%x %x %x\n", Address, Pt, Pte << PAGE_SHIFT);
+ KEBUGCHECK(0);
}
+ *Pt = PFN_TO_PTE(Pages[i]) | Attributes;
}
return(STATUS_SUCCESS);
@@ -853,18 +882,9 @@
PVOID Address,
SWAPENTRY SwapEntry)
{
- PEPROCESS CurrentProcess;
- PULONG Pte;
- ULONG oldPte;
+ PULONG Pt;
+ ULONG Pte;
- if (Process != NULL)
- {
- CurrentProcess = PsGetCurrentProcess();
- }
- else
- {
- CurrentProcess = NULL;
- }
if (Process == NULL && Address < (PVOID)KERNEL_BASE)
{
@@ -881,24 +901,32 @@
KEBUGCHECK(0);
}
- if (Process != NULL && Process != CurrentProcess)
+ Pt = MmGetPageTableForProcess(Process, Address, TRUE);
+ if (Pt == NULL)
{
- KeAttachProcess(Process);
+ KEBUGCHECK(0);
}
- Pte = MmGetPageEntry(Address, TRUE);
- if (Pte == NULL)
+ Pte = *Pt;
+ if (PAGE_MASK((Pte)) != 0)
{
- KEBUGCHECK(0);
+ MmMarkPageUnmapped(PTE_TO_PFN((Pte)));
}
- oldPte = *Pte;
- if (PAGE_MASK((oldPte)) != 0)
+ *Pt = SwapEntry << 1;
+ if (Pte != 0)
{
- MmMarkPageUnmapped(PTE_TO_PFN((oldPte)));
+ if (MmUnmapPageTable(Pt) || Address > (PVOID)KERNEL_BASE)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
}
- *Pte = SwapEntry << 1;
+ else
+ {
+ MmUnmapPageTable(Pt);
+ }
+
if (Process != NULL &&
- Process->AddressSpace.PageTableRefCountTable != NULL &&
- Address < (PVOID)KERNEL_BASE)
+ Process->AddressSpace.PageTableRefCountTable != NULL &&
+ Address < (PVOID)KERNEL_BASE)
{
PUSHORT Ptrc;
@@ -906,14 +934,6 @@
Ptrc[ADDR_TO_PAGE_TABLE(Address)]++;
}
- if (oldPte != 0)
- {
- FLUSH_TLB_ONE(Address);
- }
- if (Process != NULL && Process != CurrentProcess)
- {
- KeDetachProcess();
- }
return(STATUS_SUCCESS);
}
@@ -925,31 +945,43 @@
PPFN_TYPE Pages,
ULONG PageCount)
{
- PEPROCESS CurrentProcess;
ULONG Attributes;
- PVOID Addr = Address;
+ PVOID Addr;
ULONG i;
- PULONG Pte;
- ULONG oldPte;
+ PULONG Pt = NULL;
+ ULONG Pte;
+ ULONG oldPdeOffset, PdeOffset;
- if (Process != NULL)
+ DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x, %d)\n",
+ Process, Address, flProtect, Pages, PageCount);
+
+ if (Process == NULL)
{
- CurrentProcess = PsGetCurrentProcess();
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ DPRINT1("No process\n");
+ KEBUGCHECK(0);
+ }
+ if (PageCount > 0x10000 ||
+ (ULONG_PTR) Address / PAGE_SIZE + PageCount > 0x100000)
+ {
+ DPRINT1("Page count to large\n");
+ KEBUGCHECK(0);
+ }
}
else
{
- CurrentProcess = NULL;
- }
-
[truncated at 1000 lines; 161 more skipped]