reactos/ntoskrnl/mm/i386
diff -u -r1.72 -r1.73
--- page.c 7 Sep 2004 11:08:16 -0000 1.72
+++ page.c 9 Sep 2004 20:42:33 -0000 1.73
@@ -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.72 2004/09/07 11:08:16 hbirr Exp $
+/* $Id: page.c,v 1.73 2004/09/09 20:42:33 hbirr Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/i386/page.c
@@ -55,11 +55,17 @@
#define PAGETABLE_MAP (0xf0000000)
#define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024)))
-ULONG MmGlobalKernelPageDirectory[1024] = {0, };
+#define PAE_PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (512)))
+
+ULONG MmGlobalKernelPageDirectory[1024];
+ULONGLONG MmGlobalKernelPageDirectoryForPAE[512];
#define PTE_TO_PFN(X) ((X) >> PAGE_SHIFT)
#define PFN_TO_PTE(X) ((X) << PAGE_SHIFT)
+#define PAE_PTE_TO_PFN(X) (PAE_PAGE_MASK(X) >> PAGE_SHIFT)
+#define PAE_PFN_TO_PTE(X) ((X) << PAGE_SHIFT)
+
#if defined(__GNUC__)
#define PTE_TO_PAGE(X) ((LARGE_INTEGER)(LONGLONG)(PAGE_MASK(X)))
#else
@@ -72,6 +78,7 @@
#endif
extern ULONG Ke386CpuidFlags;
+static BOOLEAN PAE = FALSE;
/* FUNCTIONS ***************************************************************/
@@ -130,11 +137,25 @@
#define ADDR_TO_PTE_OFFSET(v) ((((ULONG)(v)) % (1024 * PAGE_SIZE)) / PAGE_SIZE)
+
+#define PAE_ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (512 * PAGE_SIZE))
+
+#define PAE_ADDR_TO_PDE(v) (PULONGLONG) (PAE_PAGEDIRECTORY_MAP + \
+ ((((ULONG_PTR)(v)) / (512 * 512))&(~0x7)))
+#define PAE_ADDR_TO_PTE(v) (PULONGLONG) (PAGETABLE_MAP + ((((ULONG_PTR)(v) / 512))&(~0x7)))
+
+
+#define PAE_ADDR_TO_PDTE_OFFSET(v) (((ULONG_PTR)(v)) / (512 * 512 * PAGE_SIZE))
+
+#define PAE_ADDR_TO_PDE_OFFSET(v) ((((ULONG_PTR)(v)) % (512 * 512 * PAGE_SIZE)) / (512 * PAGE_SIZE))
+
+#define PAE_ADDR_TO_PTE_OFFSET(v) ((((ULONG_PTR)(v)) % (512 * PAGE_SIZE)) / PAGE_SIZE)
+
+
NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process)
{
PUSHORT LdtDescriptor;
ULONG LdtBase;
- PULONG PageDir, Pde;
ULONG i, j;
DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process);
@@ -150,38 +171,90 @@
{
ExFreePool((PVOID) LdtBase);
}
- PageDir = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT);
- for (i = 0; i < ADDR_TO_PDE_OFFSET(KERNEL_BASE); i++)
+
+ if (PAE)
{
- if (PageDir[i] != 0)
+ PULONGLONG PageDirTable;
+ PULONGLONG PageDir;
+ PULONGLONG Pde;
+ ULONG k;
+
+ PageDirTable = (PULONGLONG)ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT);
+ for (i = 0; i < 4; i++)
{
- 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 (i < 3)
{
- if(Pde[j] != 0)
+ PageDir = (PULONGLONG)ExAllocatePageWithPhysPage(PageDirTable[i] >> PAGE_SHIFT);
+ for (j = 0; j < 512; j++)
{
- if (Pde[j] & PA_PRESENT)
+ if (PageDir[j] != 0LL)
{
- DPRINT1("Page at %08x is not freed\n",
- i * 4 * 1024 * 1024 + j * PAGE_SIZE);
+ DPRINT1("ProcessId %d, Pde for %08x - %08x is not freed, RefCount %d\n",
+ Process->UniqueProcessId,
+ (i * 512 + j) * 512 * PAGE_SIZE, (i * 512 + j + 1) * 512 * PAGE_SIZE - 1,
+ Process->AddressSpace.PageTableRefCountTable[i*512 + j]);
+ Pde = ExAllocatePageWithPhysPage(PageDir[j] >> PAGE_SHIFT);
+ for (k = 0; k < 512; k++)
+ {
+ if(Pde[k] != 0)
+ {
+ if (Pde[k] & PA_PRESENT)
+ {
+ DPRINT1("Page at %08x is not freed\n",
+ (i * 512 + j) * 512 * PAGE_SIZE + k * PAGE_SIZE);
+ }
+ else
+ {
+ DPRINT1("Swapentry %x at %x is not freed\n",
+ (i * 512 + j) * 512 * PAGE_SIZE + k * PAGE_SIZE);
+ }
+ }
+ }
+ ExUnmapPage(Pde);
+ MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDir[j]));
}
- else
+ }
+ ExUnmapPage(PageDir);
+ }
+ MmReleasePageMemoryConsumer(MC_NPPOOL, PageDirTable[i] >> PAGE_SHIFT);
+ }
+ ExUnmapPage((PVOID)PageDirTable);
+ }
+ else
+ {
+ PULONG Pde;
+ PULONG PageDir;
+ 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)
{
- DPRINT1("Swapentry %x at %x is not freed\n",
- Pde[j], i * 4 * 1024 * 1024 + j * PAGE_SIZE);
+ 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(Pde);
- MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[i]));
}
+ ExUnmapPage(PageDir);
}
- ExUnmapPage(PageDir);
-
MmReleasePageMemoryConsumer(MC_NPPOOL, Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT);
#if defined(__GNUC__)
@@ -199,30 +272,80 @@
NTSTATUS MmCopyMmInfo(PEPROCESS Src, PEPROCESS Dest)
{
PHYSICAL_ADDRESS PhysPageDirectory;
- PULONG PageDirectory;
PKPROCESS KProcess = &Dest->Pcb;
DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest);
- PageDirectory = ExAllocatePage();
- if (PageDirectory == NULL)
+ if (PAE)
{
- return(STATUS_UNSUCCESSFUL);
+ PULONGLONG PageDirTable;
+ PULONGLONG PageDir;
+ PFN_TYPE Pfn[4];
+ ULONG i, j;
+ NTSTATUS Status;
+
+ PageDirTable = ExAllocatePage();
+ if (PageDirTable == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ PhysPageDirectory = MmGetPhysicalAddress(PageDirTable);
+
+ for (i = 0; i < 4; i++)
+ {
+ Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn[i]);
+ if (!NT_SUCCESS(Status))
+ {
+ for (j = 0; j < i; j++)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn[j]);
+ }
+ ExUnmapPage(PageDirTable);
+ MmReleasePageMemoryConsumer(MC_NPPOOL, PhysPageDirectory.QuadPart >> PAGE_SHIFT);
+ return Status;
+ }
+ PageDirTable[i] = (Pfn[i] << PAGE_SHIFT) | PA_PRESENT;
+ }
+ ExUnmapPage(PageDirTable);
+ PageDir = (PULONGLONG)ExAllocatePageWithPhysPage(Pfn[3]);
+ if (PageDir == NULL)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn[i]);
+ }
+ ExUnmapPage(PageDirTable);
+ MmReleasePageMemoryConsumer(MC_NPPOOL, PhysPageDirectory.QuadPart >> PAGE_SHIFT);
+ return STATUS_UNSUCCESSFUL;
+ }
+ memcpy(PageDir, &MmGlobalKernelPageDirectoryForPAE[0], 512 * sizeof(ULONGLONG));
+ for (i = 0; i < 4; i++)
+ {
+ PageDir[PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + i] = (Pfn[i] << PAGE_SHIFT) | PA_PRESENT | PA_READWRITE;
+ }
+ ExUnmapPage(PageDir);
}
- PhysPageDirectory = MmGetPhysicalAddress(PageDirectory);
- KProcess->DirectoryTableBase = PhysPageDirectory;
+ else
+ {
+ PULONG PageDirectory;
+ PageDirectory = ExAllocatePage();
+ if (PageDirectory == NULL)
+ {
+ return(STATUS_UNSUCCESSFUL);
+ }
+ PhysPageDirectory = MmGetPhysicalAddress(PageDirectory);
- memset(PageDirectory,0, ADDR_TO_PDE_OFFSET(KERNEL_BASE) * sizeof(ULONG));
- memcpy(PageDirectory + ADDR_TO_PDE_OFFSET(KERNEL_BASE),
- MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(KERNEL_BASE),
- (1024 - ADDR_TO_PDE_OFFSET(KERNEL_BASE)) * sizeof(ULONG));
-
- DPRINT("Addr %x\n",PAGETABLE_MAP / (4*1024*1024));
- PageDirectory[PAGETABLE_MAP / (4*1024*1024)] =
- PhysPageDirectory.u.LowPart | PA_PRESENT | PA_READWRITE;
+ memcpy(PageDirectory + ADDR_TO_PDE_OFFSET(KERNEL_BASE),
+ MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(KERNEL_BASE),
+ (1024 - ADDR_TO_PDE_OFFSET(KERNEL_BASE)) * sizeof(ULONG));
- ExUnmapPage(PageDirectory);
+ DPRINT("Addr %x\n",PAGETABLE_MAP / (4*1024*1024));
+ PageDirectory[PAGETABLE_MAP / (4*1024*1024)] =
+ PhysPageDirectory.u.LowPart | PA_PRESENT | PA_READWRITE;
+ ExUnmapPage(PageDirectory);
+ }
+ KProcess->DirectoryTableBase = PhysPageDirectory;
DPRINT("Finished MmCopyMmInfo()\n");
return(STATUS_SUCCESS);
}
@@ -235,7 +358,16 @@
{
KeAttachProcess(Process);
}
- *(ADDR_TO_PDE(Address)) = 0;
+
+ if (PAE)
+ {
+ ULONGLONG ZeroPde = 0LL;
+ ExfpInterlockedExchange64(PAE_ADDR_TO_PDE(Address), &ZeroPde);
+ }
+ else
+ {
+ *(ADDR_TO_PDE(Address)) = 0;
+ }
if (Address >= (PVOID)KERNEL_BASE)
{
KEBUGCHECK(0);
@@ -251,27 +383,47 @@
VOID MmFreePageTable(PEPROCESS Process, PVOID Address)
{
PEPROCESS CurrentProcess = PsGetCurrentProcess();
- PULONG PageTable;
ULONG i;
- ULONG npage;
+ PFN_TYPE Pfn;
+ DPRINT("ProcessId %d, Address %x\n", Process->UniqueProcessId, Address);
if (Process != NULL && Process != CurrentProcess)
{
KeAttachProcess(Process);
}
-
- PageTable = (PULONG)PAGE_ROUND_DOWN((PVOID)ADDR_TO_PTE(Address));
- for (i = 0; i < 1024; i++)
+ if (PAE)
{
- if (PageTable[i] != 0)
+ PULONGLONG PageTable;
+ ULONGLONG ZeroPte = 0LL;
+ PageTable = (PULONGLONG)PAGE_ROUND_DOWN((PVOID)PAE_ADDR_TO_PTE(Address));
+ for (i = 0; i < 512; i++)
{
- DbgPrint("Page table entry not clear at %x/%x (is %x)\n",
- ((ULONG)Address / (4*1024*1024)), i, PageTable[i]);
- KEBUGCHECK(0);
+ if (PageTable[i] != 0LL)
+ {
+ DbgPrint("Page table entry not clear at %x/%x (is %I64x)\n",
+ ((ULONG)Address / (4*1024*1024)), i, PageTable[i]);
+ KEBUGCHECK(0);
+ }
+ }
+ Pfn = PAE_PTE_TO_PFN(*(PAE_ADDR_TO_PDE(Address)));
+ ExfpInterlockedExchange64(PAE_ADDR_TO_PDE(Address), &ZeroPte);
+ }
+ else
+ {
+ PULONG PageTable;
+ PageTable = (PULONG)PAGE_ROUND_DOWN((PVOID)ADDR_TO_PTE(Address));
+ for (i = 0; i < 1024; i++)
+ {
+ if (PageTable[i] != 0)
+ {
+ DbgPrint("Page table entry not clear at %x/%x (is %x)\n",
+ ((ULONG)Address / (4*1024*1024)), i, PageTable[i]);
+ KEBUGCHECK(0);
+ }
}
+ Pfn = PTE_TO_PFN(*(ADDR_TO_PDE(Address)));
+ *(ADDR_TO_PDE(Address)) = 0;
}
- npage = *(ADDR_TO_PDE(Address));
- *(ADDR_TO_PDE(Address)) = 0;
FLUSH_TLB;
if (Address >= (PVOID)KERNEL_BASE)
@@ -281,7 +433,7 @@
}
else
{
- MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(npage));
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
if (Process != NULL && Process != CurrentProcess)
{
@@ -289,6 +441,120 @@
}
}
+static PULONGLONG
+MmGetPageTableForProcessForPAE(PEPROCESS Process, PVOID Address, BOOLEAN Create)
+{
+ NTSTATUS Status;
+ PFN_TYPE Pfn;
+ ULONGLONG Entry;
+ ULONGLONG ZeroEntry = 0LL;
+ PULONGLONG Pt;
+ PULONGLONG PageDir;
+ PULONGLONG PageDirTable;
+
+ DPRINT("MmGetPageTableForProcessForPAE(%x %x %d)\n",
+ Process, Address, Create);
+ if (Address >= (PVOID)PAGETABLE_MAP && Address < (PVOID)PAGETABLE_MAP + 0x800000)
+ {
+ KEBUGCHECK(0);
+ }
+ if (Address < (PVOID)KERNEL_BASE && Process && Process != PsGetCurrentProcess())
+ {
+ PageDirTable = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT);
+ if (PageDirTable == NULL)
+ {
+ KEBUGCHECK(0);
+ }
+ PageDir = ExAllocatePageWithPhysPage(PageDirTable[PAE_ADDR_TO_PDTE_OFFSET(Address)] >> PAGE_SHIFT);
+ ExUnmapPage(PageDirTable);
+ if (PageDir == NULL)
+ {
+ KEBUGCHECK(0);
+ }
+ PageDir += PAE_ADDR_TO_PDE_OFFSET(Address);
+ Entry = ExfInterlockedCompareExchange64(PageDir, &ZeroEntry, &ZeroEntry);
+ if (Entry == 0LL)
+ {
+ if (Create == FALSE)
+ {
+ ExUnmapPage(PageDir);
+ return NULL;
+ }
+ Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
+ if (!NT_SUCCESS(Status))
+ {
+ KEBUGCHECK(0);
+ }
+ Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER;
+ Entry = ExfInterlockedCompareExchange64(PageDir, &Entry, &ZeroEntry);
+ if (Entry != 0LL)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
+ Pfn = PAE_PTE_TO_PFN(Entry);
+ }
+ }
+ else
+ {
+ Pfn = PAE_PTE_TO_PFN(Entry);
+ }
+ ExUnmapPage(PageDir);
+ Pt = ExAllocatePageWithPhysPage(Pfn);
+ if (Pt == NULL)
+ {
+ KEBUGCHECK(0);
+ }
+ return Pt + PAE_ADDR_TO_PTE_OFFSET(Address);
+ }
+ PageDir = PAE_ADDR_TO_PDE(Address);
+ if (0LL == ExfInterlockedCompareExchange64(PageDir, &ZeroEntry, &ZeroEntry))
+ {
+ if (Address >= (PVOID)KERNEL_BASE)
+ {
+ if (MmGlobalKernelPageDirectoryForPAE[PAE_ADDR_TO_PDE_OFFSET(Address)] == 0LL)
+ {
+ if (Create == FALSE)
+ {
+ return NULL;
+ }
+ Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
+ if (!NT_SUCCESS(Status))
+ {
+ KEBUGCHECK(0);
+ }
+ Entry = PAE_PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE;
+ if (Ke386CpuidFlags & X86_FEATURE_PGE)
+ {
+ Entry |= PA_GLOBAL;
+ }
+ if (0LL != ExfInterlockedCompareExchange64(&MmGlobalKernelPageDirectoryForPAE[PAE_ADDR_TO_PDE_OFFSET(Address)], &Entry, &ZeroEntry))
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
+ }
+ }
+ ExfInterlockedCompareExchange64(PageDir, &MmGlobalKernelPageDirectoryForPAE[PAE_ADDR_TO_PDE_OFFSET(Address)], &ZeroEntry);
+ }
+ else
+ {
+ if (Create == FALSE)
+ {
+ return NULL;
+ }
+ Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
+ if (!NT_SUCCESS(Status))
+ {
+ KEBUGCHECK(0);
+ }
+ Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER;
+ Entry = ExfInterlockedCompareExchange64(PageDir, &Entry, &ZeroEntry);
+ if (Entry != 0LL)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
+ }
+ }
+ }
+ return (PULONGLONG)PAE_ADDR_TO_PTE(Address);
+}
+
static PULONG
MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
{
@@ -329,7 +595,6 @@
Pfn = PTE_TO_PFN(PageDir[PdeOffset]);
}
ExUnmapPage(PageDir);
- DPRINT("%d\n", Pfn);
Pt = ExAllocatePageWithPhysPage(Pfn);
if (Pt == NULL)
{
@@ -388,16 +653,40 @@
BOOLEAN MmUnmapPageTable(PULONG Pt)
{
- if (Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024)
+ if (PAE)
+ {
+ if ((PULONGLONG)Pt >= (PULONGLONG)PAGETABLE_MAP && (PULONGLONG)Pt < (PULONGLONG)PAGETABLE_MAP + 4*512*512)
+ {
+ return TRUE;
+ }
+ }
+ else
{
- return TRUE;
+ if (Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024)
+ {
+ return TRUE;
+ }
}
if (Pt)
{
ExUnmapPage((PVOID)PAGE_ROUND_DOWN(Pt));
}
return FALSE;
+}
+static ULONGLONG MmGetPageEntryForProcessForPAE(PEPROCESS Process, PVOID Address)
+{
+ ULONGLONG Pte;
+ PULONGLONG Pt;
+
+ Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
+ if (Pt)
+ {
+ Pte = *Pt;
+ MmUnmapPageTable((PULONG)Pt);
+ return Pte;
+ }
+ return 0;
}
static ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
@@ -409,7 +698,6 @@
if (Pt)
{
Pte = *Pt;
-
MmUnmapPageTable(Pt);
return Pte;
}
@@ -420,15 +708,27 @@
MmGetPfnForProcess(PEPROCESS Process,
PVOID Address)
{
- ULONG Entry;
- Entry = MmGetPageEntryForProcess(Process, Address);
-
- if (!(Entry & PA_PRESENT))
+ if (PAE)
{
- return 0;
+ ULONGLONG Entry;
+ Entry = MmGetPageEntryForProcessForPAE(Process, Address);
+ if (!(Entry & PA_PRESENT))
+ {
+ return 0;
+ }
+ return(PAE_PTE_TO_PFN(Entry));
+ }
+ else
+ {
+ ULONG Entry;
+ Entry = MmGetPageEntryForProcess(Process, Address);
+ if (!(Entry & PA_PRESENT))
+ {
+ return 0;
+ }
+ return(PTE_TO_PFN(Entry));
}
- return(PTE_TO_PFN(Entry));
}
VOID
@@ -437,61 +737,121 @@
* FUNCTION: Delete a virtual mapping
*/
{
- ULONG Pte;
- PULONG Pt;
BOOLEAN WasValid;
-
- Pt = MmGetPageTableForProcess(Process, Address, FALSE);
- if (Pt == NULL)
+ if (PAE)
{
- KEBUGCHECK(0);
- }
+ ULONGLONG Pte;
+ ULONGLONG tmpPte;
+ PULONGLONG Pt;
+ Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
+ if (Pt == NULL)
+ {
+ KEBUGCHECK(0);
+ }
+ /*
+ * Atomically disable the present bit and get the old value.
+ */
+ do
+ {
+ Pte = *Pt;
+ tmpPte = Pte & ~PA_PRESENT;
+ } while (Pte != ExfInterlockedCompareExchange64(Pt, &tmpPte, &Pte));
- /*
- * Atomically set the entry to zero and get the old value.
- */
- do
- {
- Pte = *Pt;
- } while (Pte != InterlockedCompareExchange(Pt, Pte & ~PA_PRESENT, Pte));
+ if (MmUnmapPageTable((PULONG)Pt) || Address >= (PVOID)KERNEL_BASE)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
+ WasValid = PAE_PAGE_MASK(Pte) != 0LL ? TRUE : FALSE;
+ if (!WasValid)
+ {
+ KEBUGCHECK(0);
+ }
- if (MmUnmapPageTable(Pt) || Address >= (PVOID)KERNEL_BASE)
- {
- FLUSH_TLB_ONE(Address);
+ /*
+ * Return some information to the caller
+ */
+ if (WasDirty != NULL)
+ {
+ *WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
+ }
+ if (Page != NULL)
+ {
+ *Page = PAE_PTE_TO_PFN(Pte);
+ }
}
- WasValid = (PAGE_MASK(Pte) != 0);
- if (!WasValid)
+ else
{
- KEBUGCHECK(0);
- }
+ ULONG Pte;
+ PULONG Pt;
- /*
- * Return some information to the caller
- */
- if (WasDirty != NULL)
- {
- *WasDirty = Pte & PA_DIRTY;
- }
- if (Page != NULL)
- {
- *Page = PTE_TO_PFN(Pte);
+ Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+ if (Pt == NULL)
+ {
+ KEBUGCHECK(0);
+ }
+ /*
+ * Atomically disable the present bit and get the old value.
+ */
+ do
+ {
+ Pte = *Pt;
+ } while (Pte != InterlockedCompareExchange(Pt, Pte & ~PA_PRESENT, Pte));
+
+ if (MmUnmapPageTable(Pt) || Address >= (PVOID)KERNEL_BASE)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
+ WasValid = (PAGE_MASK(Pte) != 0);
+ if (!WasValid)
+ {
+ KEBUGCHECK(0);
+ }
+
+ /*
+ * Return some information to the caller
+ */
+ if (WasDirty != NULL)
+ {
+ *WasDirty = Pte & PA_DIRTY;
+ }
+ if (Page != NULL)
+ {
+ *Page = PTE_TO_PFN(Pte);
+ }
}
}
VOID
MmRawDeleteVirtualMapping(PVOID Address)
{
- PULONG Pt;
-
- Pt = MmGetPageTableForProcess(NULL, Address, FALSE);
- if (Pt && *Pt)
+ if (PAE)
{
- /*
- * Set the entry to zero
- */
- *Pt = 0;
- FLUSH_TLB_ONE(Address);
+ PULONGLONG Pt;
+ ULONGLONG ZeroPte = 0LL;
+ Pt = MmGetPageTableForProcessForPAE(NULL, Address, FALSE);
+ if (Pt)
+ {
+ /*
+ * Set the entry to zero
+ */
+ ExfpInterlockedExchange64(Pt, &ZeroPte);
+ FLUSH_TLB_ONE(Address);
+ }
+ }
+ else
+ {
+ PULONG Pt;
+
+ Pt = MmGetPageTableForProcess(NULL, Address, FALSE);
+ if (Pt && *Pt)
+ {
+ /*
+ * Set the entry to zero
+ */
+ *Pt = 0;
+ FLUSH_TLB_ONE(Address);
+ }
}
}
@@ -502,49 +862,127 @@
* FUNCTION: Delete a virtual mapping
*/
{
- ULONG Pte;
- PULONG Pt;
- BOOLEAN WasValid;
+ BOOLEAN WasValid = FALSE;
+ PFN_TYPE Pfn;
DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n",
- Process, Address, FreePage, WasDirty, Page);
+ Process, Address, FreePage, WasDirty, Page);
+ if (PAE)
+ {
+ ULONGLONG Pte;
+ PULONGLONG Pt;
- Pt = MmGetPageTableForProcess(Process, Address, FALSE);
+ Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
+ if (Pt == NULL)
+ {
+ if (WasDirty != NULL)
+ {
+ *WasDirty = FALSE;
+ }
+ if (Page != NULL)
+ {
+ *Page = 0;
+ }
+ return;
+ }
- if (Pt == NULL)
- {
+ /*
+ * Atomically set the entry to zero and get the old value.
+ */
+ Pte = 0LL;
+ Pte = ExfpInterlockedExchange64(Pt, &Pte);
+
+ if ((MmUnmapPageTable((PULONG)Pt) || Address >=(PVOID)KERNEL_BASE) && Pte)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
+
+ WasValid = PAE_PAGE_MASK(Pte) != 0 ? TRUE : FALSE;
+ if (WasValid)
+ {
+ Pfn = PAE_PTE_TO_PFN(Pte);
+ MmMarkPageUnmapped(Pfn);
+ }
+ else
+ {
+ Pfn = 0;
+ }
+
+ if (FreePage && WasValid)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
+ }
+
+ /*
+ * Return some information to the caller
+ */
if (WasDirty != NULL)
{
- *WasDirty = FALSE;
+ *WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
}
if (Page != NULL)
{
- *Page = 0;
+ *Page = Pfn;
}
- return;
}
+ else
+ {
+ ULONG Pte;
+ PULONG Pt;
- /*
- * Atomically set the entry to zero and get the old value.
- */
- Pte = InterlockedExchange(Pt, 0);
+ Pt = MmGetPageTableForProcess(Process, Address, FALSE);
- if ((MmUnmapPageTable(Pt) || Address >=(PVOID)KERNEL_BASE) && Pte)
- {
- FLUSH_TLB_ONE(Address);
- }
+ if (Pt == NULL)
+ {
+ if (WasDirty != NULL)
+ {
+ *WasDirty = FALSE;
+ }
+ if (Page != NULL)
+ {
+ *Page = 0;
+ }
+ return;
+ }
- WasValid = (PAGE_MASK(Pte) != 0);
- if (WasValid)
- {
- MmMarkPageUnmapped(PTE_TO_PFN(Pte));
- }
+ /*
+ * Atomically set the entry to zero and get the old value.
+ */
+ Pte = InterlockedExchange(Pt, 0);
- if (FreePage && WasValid)
- {
- MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(Pte));
- }
+ if ((MmUnmapPageTable(Pt) || Address >=(PVOID)KERNEL_BASE) && Pte)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
+
+ WasValid = (PAGE_MASK(Pte) != 0);
+ if (WasValid)
+ {
+ Pfn = PTE_TO_PFN(Pte);
+ MmMarkPageUnmapped(Pfn);
+ }
+ else
+ {
+ Pfn = 0;
+ }
+
+ if (FreePage && WasValid)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
+ }
+ /*
+ * Return some information to the caller
+ */
+ if (WasDirty != NULL)
+ {
+ *WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
+ }
+ if (Page != NULL)
+ {
+ *Page = Pfn;
+ }
+ }
/*
* Decrement the reference count for this page table.
*/
@@ -553,27 +991,17 @@
Address < (PVOID)KERNEL_BASE)
{
PUSHORT Ptrc;
-
+ ULONG Idx;
+
Ptrc = Process->AddressSpace.PageTableRefCountTable;
+ Idx = PAE ? PAE_ADDR_TO_PAGE_TABLE(Address) : ADDR_TO_PAGE_TABLE(Address);
- Ptrc[ADDR_TO_PAGE_TABLE(Address)]--;
- if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0)
+ Ptrc[Idx]--;
+ if (Ptrc[Idx] == 0)
{
MmFreePageTable(Process, Address);
}
}
-
- /*
- * Return some information to the caller
- */
- if (WasDirty != NULL)
- {
- *WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
- }
- if (Page != NULL)
- {
- *Page = PTE_TO_PFN(Pte);
- }
}
VOID
@@ -583,69 +1011,138 @@
* FUNCTION: Delete a virtual mapping
*/
{
- ULONG Pte;
- PULONG Pt;
-
- Pt = MmGetPageTableForProcess(Process, Address, FALSE);
-
- if (Pt == NULL)
+ if (PAE)
{
- *SwapEntry = 0;
- return;
- }
+ ULONGLONG Pte;
+ PULONGLONG Pt;
- /*
- * Atomically set the entry to zero and get the old value.
- */
- Pte = InterlockedExchange(Pt, 0);
+ Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
+ if (Pt == NULL)
+ {
+ *SwapEntry = 0;
+ return;
+ }
- if (MmUnmapPageTable(Pt) || Address >= (PVOID)KERNEL_BASE)
- {
- FLUSH_TLB_ONE(Address);
- }
+ /*
+ * Atomically set the entry to zero and get the old value.
+ */
+ Pte = 0LL;
+ Pte = ExfpInterlockedExchange64(Pt, &Pte);
- /*
- * Decrement the reference count for this page table.
- */
- if (Process != NULL && Pte &&
- Process->AddressSpace.PageTableRefCountTable != NULL &&
- Address < (PVOID)KERNEL_BASE)
+ if (MmUnmapPageTable((PULONG)Pt) || Address >= (PVOID)KERNEL_BASE)
+ {
+ FLUSH_TLB_ONE(Address);
+ }
+
+ /*
+ * Decrement the reference count for this page table.
+ */
+ if (Process != NULL && Pte &&
+ Process->AddressSpace.PageTableRefCountTable != NULL &&
+ Address < (PVOID)KERNEL_BASE)
+ {
+ PUSHORT Ptrc;
+
+ Ptrc = Process->AddressSpace.PageTableRefCountTable;
+
+ Ptrc[PAE_ADDR_TO_PAGE_TABLE(Address)]--;
+ if (Ptrc[PAE_ADDR_TO_PAGE_TABLE(Address)] == 0)
+ {
+ MmFreePageTable(Process, Address);
+ }
+ }
+
+
+ /*
+ * Return some information to the caller
+ */
+ *SwapEntry = Pte >> 1;
+ }
+ else
{
- PUSHORT Ptrc;
[truncated at 1000 lines; 1284 more skipped]