📄 page.c
字号:
{
ULONG Pte;
PULONG Pt;
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
if (Pt == NULL)
{
if (WasDirty != NULL)
{
*WasDirty = FALSE;
}
if (Page != NULL)
{
*Page = 0;
}
return;
}
/*
* Atomically set the entry to zero and get the old value.
*/
Pte = InterlockedExchangeUL(Pt, 0);
MiFlushTlb(Pt, 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.
*/
if (Process != NULL && WasValid &&
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
Address < MmSystemRangeStart)
{
PUSHORT Ptrc;
ULONG Idx;
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
Idx = Ke386Pae ? PAE_ADDR_TO_PAGE_TABLE(Address) : ADDR_TO_PAGE_TABLE(Address);
Ptrc[Idx]--;
if (Ptrc[Idx] == 0)
{
MmFreePageTable(Process, Address);
}
}
}
VOID
NTAPI
MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
SWAPENTRY* SwapEntry)
/*
* FUNCTION: Delete a virtual mapping
*/
{
if (Ke386Pae)
{
ULONGLONG Pte;
PULONGLONG Pt;
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt == NULL)
{
*SwapEntry = 0;
return;
}
/*
* Atomically set the entry to zero and get the old value.
*/
Pte = 0LL;
Pte = ExfpInterlockedExchange64UL(Pt, &Pte);
MiFlushTlb((PULONG)Pt, Address);
/*
* Decrement the reference count for this page table.
*/
if (Process != NULL && Pte &&
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
Address < MmSystemRangeStart)
{
PUSHORT Ptrc;
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->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
{
ULONG Pte;
PULONG Pt;
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
if (Pt == NULL)
{
*SwapEntry = 0;
return;
}
/*
* Atomically set the entry to zero and get the old value.
*/
Pte = InterlockedExchangeUL(Pt, 0);
MiFlushTlb(Pt, Address);
/*
* Decrement the reference count for this page table.
*/
if (Process != NULL && Pte &&
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
Address < MmSystemRangeStart)
{
PUSHORT Ptrc;
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
Ptrc[ADDR_TO_PAGE_TABLE(Address)]--;
if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0)
{
MmFreePageTable(Process, Address);
}
}
/*
* Return some information to the caller
*/
*SwapEntry = Pte >> 1;
}
}
BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
{
if (Ke386Pae)
{
PULONGLONG Pt;
PULONGLONG Pde;
Pde = PAE_ADDR_TO_PDE(PAddress);
if (*Pde == 0LL)
{
Pt = MmGetPageTableForProcessForPAE(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 (Pt != NULL)
{
return TRUE;
}
}
}
else
{
PULONG Pt, Pde;
Pde = ADDR_TO_PDE(PAddress);
if (*Pde == 0)
{
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 (Pt != NULL)
{
return TRUE;
}
}
}
return(FALSE);
}
BOOLEAN
NTAPI
MmIsDirtyPage(PEPROCESS Process, PVOID Address)
{
if (Ke386Pae)
{
return MmGetPageEntryForProcessForPAE(Process, Address) & PA_DIRTY ? TRUE : FALSE;
}
else
{
return MmGetPageEntryForProcess(Process, Address) & PA_DIRTY ? TRUE : FALSE;
}
}
BOOLEAN
NTAPI
MmIsAccessedAndResetAccessPage(PEPROCESS Process, PVOID Address)
{
if (Address < MmSystemRangeStart && Process == NULL)
{
DPRINT1("MmIsAccessedAndResetAccessPage is called for user space without a process.\n");
KEBUGCHECK(0);
}
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
ULONGLONG tmpPte;
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
do
{
Pte = *Pt;
tmpPte = Pte & ~PA_ACCESSED;
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
if (Pte & PA_ACCESSED)
{
MiFlushTlb((PULONG)Pt, Address);
return TRUE;
}
else
{
MmUnmapPageTable((PULONG)Pt);
return FALSE;
}
}
else
{
PULONG Pt;
ULONG Pte;
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
do
{
Pte = *Pt;
} while (Pte != InterlockedCompareExchangeUL(Pt, Pte & ~PA_ACCESSED, Pte));
if (Pte & PA_ACCESSED)
{
MiFlushTlb(Pt, Address);
return TRUE;
}
else
{
MmUnmapPageTable(Pt);
return FALSE;
}
}
}
VOID
NTAPI
MmSetCleanPage(PEPROCESS Process, PVOID Address)
{
if (Address < MmSystemRangeStart && Process == NULL)
{
DPRINT1("MmSetCleanPage is called for user space without a process.\n");
KEBUGCHECK(0);
}
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
ULONGLONG tmpPte;
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
do
{
Pte = *Pt;
tmpPte = Pte & ~PA_DIRTY;
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
if (Pte & PA_DIRTY)
{
MiFlushTlb((PULONG)Pt, Address);
}
else
{
MmUnmapPageTable((PULONG)Pt);
}
}
else
{
PULONG Pt;
ULONG Pte;
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
do
{
Pte = *Pt;
} while (Pte != InterlockedCompareExchangeUL(Pt, Pte & ~PA_DIRTY, Pte));
if (Pte & PA_DIRTY)
{
MiFlushTlb(Pt, Address);
}
else
{
MmUnmapPageTable(Pt);
}
}
}
VOID
NTAPI
MmSetDirtyPage(PEPROCESS Process, PVOID Address)
{
if (Address < MmSystemRangeStart && Process == NULL)
{
DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
KEBUGCHECK(0);
}
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
ULONGLONG tmpPte;
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
do
{
Pte = *Pt;
tmpPte = Pte | PA_DIRTY;
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
if (!(Pte & PA_DIRTY))
{
MiFlushTlb((PULONG)Pt, Address);
}
else
{
MmUnmapPageTable((PULONG)Pt);
}
}
else
{
PULONG Pt;
ULONG Pte;
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
do
{
Pte = *Pt;
} while (Pte != InterlockedCompareExchangeUL(Pt, Pte | PA_DIRTY, Pte));
if (!(Pte & PA_DIRTY))
{
MiFlushTlb(Pt, Address);
}
else
{
MmUnmapPageTable(Pt);
}
}
}
VOID
NTAPI
MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
{
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
ULONGLONG tmpPte;
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
do
{
Pte = *Pt;
tmpPte = Pte | PA_PRESENT;
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
if (!(Pte & PA_PRESENT))
{
MiFlushTlb((PULONG)Pt, Address);
}
else
{
MmUnmapPageTable((PULONG)Pt);
}
}
else
{
PULONG Pt;
ULONG Pte;
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
if (Pt == NULL)
{
KEBUGCHECK(0);
}
do
{
Pte = *Pt;
} while (Pte != InterlockedCompareExchangeUL(Pt, Pte | PA_PRESENT, Pte));
if (!(Pte & PA_PRESENT))
{
MiFlushTlb(Pt, Address);
}
else
{
MmUnmapPageTable(Pt);
}
}
}
BOOLEAN
NTAPI
MmIsPagePresent(PEPROCESS Process, PVOID Address)
{
if (Ke386Pae)
{
return MmGetPageEntryForProcessForPAE(Process, Address) & PA_PRESENT ? TRUE : FALSE;
}
else
{
return MmGetPageEntryForProcess(Process, Address) & PA_PRESENT ? TRUE : FALSE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -