679 lines
15 KiB
C++
679 lines
15 KiB
C++
/**
|
|
* PROJECT: ExectOS
|
|
* COPYRIGHT: See COPYING.md in the top level directory
|
|
* FILE: xtoskrnl/mm/i686/pagemap.cc
|
|
* DESCRIPTION: Low-level support for i686 page map manipulation
|
|
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
|
*/
|
|
|
|
#include <xtos.hh>
|
|
|
|
|
|
/**
|
|
* Clears the contents of a page table entry (PTE).
|
|
*
|
|
* @param PtePointer
|
|
* Pointer to the page table entry (PTE) to be cleared.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMap::ClearPte(PHARDWARE_PTE PtePointer)
|
|
{
|
|
/* Clear PTE */
|
|
PtePointer->Long = 0;
|
|
}
|
|
|
|
/**
|
|
* Gets the value representing an empty PTE list.
|
|
*
|
|
* @return This routine returns the value representing an empty PTE list.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
ULONG
|
|
MM::PageMap::GetEmptyPteList(VOID)
|
|
{
|
|
/* Return empty PTE list mask */
|
|
return PageMapInfo.EmptyPteList;
|
|
}
|
|
|
|
/**
|
|
* Gets the address of the PDE (Page Directory Entry), that maps given address.
|
|
*
|
|
* @param Address
|
|
* Specifies the virtual address for which to retrieve the corresponding PDE.
|
|
*
|
|
* @return This routine returns the address of the PDE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
PMMPDE
|
|
MM::PageMap::GetPdeAddress(PVOID Address)
|
|
{
|
|
ULONG Offset;
|
|
|
|
/* Calculate offset and return PDE address */
|
|
Offset = ((((ULONG_PTR)(Address)) >> PageMapInfo.PdiShift) << PageMapInfo.PteShift);
|
|
return (PMMPDE)(PageMapInfo.PdeBase + Offset);
|
|
}
|
|
|
|
/**
|
|
* Gets the index of the PDE (Page Directory Entry), that maps given address.
|
|
*
|
|
* @param Address
|
|
* Specifies the virtual address for which to retrieve the corresponding PDE.
|
|
*
|
|
* @return This routine returns the index of the PDE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
ULONG
|
|
MM::PageMap::GetPdeIndex(PVOID Address)
|
|
{
|
|
/* Return PDE index */
|
|
return ((((ULONG_PTR)(Address)) >> PageMapInfo.PdiShift) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF));
|
|
}
|
|
|
|
/**
|
|
* Gets the virtual address that is mapped by a given Page Directory Entry.
|
|
*
|
|
* @param PdePointer
|
|
* Specifies the address of the PDE.
|
|
*
|
|
* @return This routine returns the virtual address mapped by the PDE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
PVOID
|
|
MM::PageMap::GetPdeVirtualAddress(PMMPDE PdePointer)
|
|
{
|
|
/* Return PDE virtual address */
|
|
return ((PVOID)((ULONG)(PdePointer) << 20));
|
|
}
|
|
|
|
/**
|
|
* Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address.
|
|
*
|
|
* @param Address
|
|
* Specifies the virtual address for which to retrieve the corresponding PDE.
|
|
*
|
|
* @return This routine returns the address of the PPE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
PMMPPE
|
|
MM::PageMap::GetPpeAddress(PVOID Address)
|
|
{
|
|
/* Return zero */
|
|
return (PMMPPE)0;
|
|
}
|
|
|
|
/**
|
|
* Gets the index of the PPE (Page Directory Pointer Table Entry), that maps given address.
|
|
*
|
|
* @param Address
|
|
* Specifies the virtual address for which to retrieve the corresponding PPE.
|
|
*
|
|
* @return This routine returns the index of the PPE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
ULONG
|
|
MM::PageMap::GetPpeIndex(PVOID Address)
|
|
{
|
|
/* Return PPE index */
|
|
return ((((ULONG_PTR)(Address)) >> MM_PPI_SHIFT) & 0x3) * PageMapInfo.Xpa;
|
|
}
|
|
|
|
/**
|
|
* Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry.
|
|
*
|
|
* @param PpePointer
|
|
* Specifies the virtual address of the PPE.
|
|
*
|
|
* @return This routine returns the virtual address mapped by the PPE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
PVOID
|
|
MM::PageMap::GetPpeVirtualAddress(PMMPPE PpePointer)
|
|
{
|
|
/* Return PPE virtual address */
|
|
return (PVOID)((ULONG)(PpePointer) << 30);
|
|
}
|
|
|
|
/**
|
|
* Gets the address of the PTE (Page Table Entry), that maps given address.
|
|
*
|
|
* @param Address
|
|
* Specifies the virtual address for which to retrieve the corresponding PTE.
|
|
*
|
|
* @return This routine returns the address of the PTE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
PMMPTE
|
|
MM::PageMap::GetPteAddress(PVOID Address)
|
|
{
|
|
ULONG Offset;
|
|
|
|
/* Calculate offset and return PTE address */
|
|
Offset = ((((ULONG_PTR)(Address)) >> MM_PTI_SHIFT) << PageMapInfo.PteShift);
|
|
return (PMMPTE)(PageMapInfo.PteBase + Offset);
|
|
}
|
|
|
|
/**
|
|
* Gets the index of the PTE (Page Table Entry), that maps given address.
|
|
*
|
|
* @param Address
|
|
* Specifies the virtual address for which to retrieve the corresponding PTE.
|
|
*
|
|
* @return This routine returns the index of the PTE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
ULONG
|
|
MM::PageMap::GetPteIndex(PVOID Address)
|
|
{
|
|
/* Return PTE index */
|
|
return ((((ULONG_PTR)(Address)) >> MM_PTI_SHIFT) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF));
|
|
}
|
|
|
|
/**
|
|
* Gets the virtual address that is mapped by a given Page Table Entry.
|
|
*
|
|
* @param PtePointer
|
|
* Specifies the virtual address of the PTE.
|
|
*
|
|
* @return This routine returns the virtual address mapped by the PTE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
PVOID
|
|
MM::PageMap::GetPteVirtualAddress(PMMPTE PtePointer)
|
|
{
|
|
/* Return PTE virtual address */
|
|
return ((PVOID)((ULONG)(PtePointer) << 10));
|
|
}
|
|
|
|
/**
|
|
* Advances a PTE pointer by a given number of entries, considering the actual PTE size for PML2.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to advance.
|
|
*
|
|
* @param Count
|
|
* The number of PTE entries to advance by.
|
|
*
|
|
* @return This routine returns the advanced PTE pointer.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
PMMPTE
|
|
MM::PageMapBasic::AdvancePte(PMMPTE Pte,
|
|
ULONG Count)
|
|
{
|
|
/* Return advanced PTE pointer */
|
|
return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML2_PTE)));
|
|
}
|
|
|
|
/**
|
|
* Gets the next entry in a PTE list.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to get the next entry from.
|
|
*
|
|
* @return This routine returns the next entry in the PTE list.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
ULONG_PTR
|
|
MM::PageMapBasic::GetNextEntry(PMMPTE Pte)
|
|
{
|
|
/* Return next entry in PTE list */
|
|
return Pte->Pml2.List.NextEntry;
|
|
}
|
|
|
|
/**
|
|
* Advances a PTE pointer, considering the actual PTE size for PML2.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to advance.
|
|
*
|
|
* @return The advanced PTE pointer.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
PMMPTE
|
|
MM::PageMapBasic::GetNextPte(PMMPTE Pte)
|
|
{
|
|
/* Return advanced PTE pointer */
|
|
return AdvancePte(Pte, 1);
|
|
}
|
|
|
|
/**
|
|
* Checks if a PTE list contains only one entry.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to check.
|
|
*
|
|
* @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
BOOLEAN
|
|
MM::PageMapBasic::GetOneEntry(PMMPTE Pte)
|
|
{
|
|
/* Return one entry status */
|
|
return Pte->Pml2.List.OneEntry;
|
|
}
|
|
|
|
/**
|
|
* Gets the size of a PTE for basic paging (PML2).
|
|
*
|
|
* @return This routine returns the size of a PTE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
ULONG
|
|
MM::PageMapBasic::GetPteSize(VOID)
|
|
{
|
|
/* Return the size of MMPTE */
|
|
return sizeof(MMPML2_PTE);
|
|
}
|
|
|
|
/**
|
|
* Initializes page map information for basic paging (PML2).
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMapBasic::InitializePageMapInfo(VOID)
|
|
{
|
|
/* Set PML2 page map information */
|
|
PageMapInfo.Xpa = FALSE;
|
|
|
|
/* Set PML2 empty PTE list mask */
|
|
PageMapInfo.EmptyPteList = (ULONG)0xFFFFF;
|
|
|
|
/* Set PML2 base addresses */
|
|
PageMapInfo.PteBase = MM_PTE_BASE;
|
|
PageMapInfo.PdeBase = MM_PDE_LEGACY_BASE;
|
|
|
|
/* Set PML2 shift values */
|
|
PageMapInfo.PdiShift = MM_PDI_LEGACY_SHIFT;
|
|
PageMapInfo.PteShift = MM_PTE_LEGACY_SHIFT;
|
|
}
|
|
|
|
/**
|
|
* Checks whether the given PML2 page table entry (PTE) is valid.
|
|
*
|
|
* @param PtePointer
|
|
* Pointer to the page table entry (PTE) to check.
|
|
*
|
|
* @return Returns TRUE if the entry is valid, FALSE otherwise.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
BOOLEAN
|
|
MM::PageMapBasic::PteValid(PHARDWARE_PTE PtePointer)
|
|
{
|
|
/* Check if PTE is valid */
|
|
return (BOOLEAN)PtePointer->Pml2.Valid;
|
|
}
|
|
|
|
/**
|
|
* Sets the next entry in a PTE list.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to modify.
|
|
*
|
|
* @param Value
|
|
* The value to set as the next entry.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMapBasic::SetNextEntry(PMMPTE Pte,
|
|
ULONG_PTR Value)
|
|
{
|
|
/* Set next entry in PTE list */
|
|
Pte->Pml2.List.NextEntry = Value;
|
|
}
|
|
|
|
/**
|
|
* Sets the flag indicating whether a PTE list contains only one entry.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to modify.
|
|
*
|
|
* @param Value
|
|
* The value to set. TRUE if the list has only one entry, FALSE otherwise.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMapBasic::SetOneEntry(PMMPTE Pte,
|
|
BOOLEAN Value)
|
|
{
|
|
/* Set one entry status */
|
|
Pte->Pml2.List.OneEntry = Value;
|
|
}
|
|
|
|
/**
|
|
* Sets a PML2 page table entry (PTE) with the specified physical page and access flags.
|
|
*
|
|
* @param PtePointer
|
|
* Pointer to the page table entry (PTE) to set.
|
|
*
|
|
* @param PageFrameNumber
|
|
* Physical frame number to map.
|
|
*
|
|
* @param Writable
|
|
* Indicates whether the page should be writable.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMapBasic::SetPte(PHARDWARE_PTE PtePointer,
|
|
PFN_NUMBER PageFrameNumber,
|
|
BOOLEAN Writable)
|
|
{
|
|
/* Set PTE */
|
|
PtePointer->Pml2.PageFrameNumber = PageFrameNumber;
|
|
PtePointer->Pml2.Valid = 1;
|
|
PtePointer->Pml2.Writable = Writable;
|
|
}
|
|
|
|
/**
|
|
* Sets caching attributes for a PML2 page table entry (PTE).
|
|
*
|
|
* @param PtePointer
|
|
* Pointer to the page table entry (PTE) to modify.
|
|
*
|
|
* @param CacheDisable
|
|
* Indicates whether caching should be disabled for this page.
|
|
*
|
|
* @param WriteThrough
|
|
* Indicates whether write-through caching should be enabled.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMapBasic::SetPteCaching(PHARDWARE_PTE PtePointer,
|
|
BOOLEAN CacheDisable,
|
|
BOOLEAN WriteThrough)
|
|
{
|
|
/* Set caching attributes */
|
|
PtePointer->Pml2.CacheDisable = CacheDisable;
|
|
PtePointer->Pml2.WriteThrough = WriteThrough;
|
|
}
|
|
|
|
/**
|
|
* Advances a PTE pointer by a given number of entries, considering the actual PTE size for PML3.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to advance.
|
|
*
|
|
* @param Count
|
|
* The number of PTE entries to advance by.
|
|
*
|
|
* @return The advanced PTE pointer.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
PMMPTE
|
|
MM::PageMapXpa::AdvancePte(PMMPTE Pte,
|
|
ULONG Count)
|
|
{
|
|
/* Return advanced PTE pointer */
|
|
return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML3_PTE)));
|
|
}
|
|
|
|
/**
|
|
* Gets the next entry in a PTE list.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to get the next entry from.
|
|
*
|
|
* @return This routine returns the next entry in the PTE list.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
ULONG_PTR
|
|
MM::PageMapXpa::GetNextEntry(PMMPTE Pte)
|
|
{
|
|
/* Return next entry in PTE list */
|
|
return Pte->Pml3.List.NextEntry;
|
|
}
|
|
|
|
/**
|
|
* Advances a PTE pointer, considering the actual PTE size for PML3.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to advance.
|
|
*
|
|
* @return The advanced PTE pointer.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
PMMPTE
|
|
MM::PageMapXpa::GetNextPte(PMMPTE Pte)
|
|
{
|
|
/* Return advanced PTE pointer */
|
|
return AdvancePte(Pte, 1);
|
|
}
|
|
|
|
/**
|
|
* Checks if a PTE list contains only one entry.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to check.
|
|
*
|
|
* @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
BOOLEAN
|
|
MM::PageMapXpa::GetOneEntry(PMMPTE Pte)
|
|
{
|
|
/* Return one entry status */
|
|
return Pte->Pml3.List.OneEntry;
|
|
}
|
|
|
|
/**
|
|
* Gets the size of a PTE for XPA paging (PML3).
|
|
*
|
|
* @return This routine returns the size of a PTE.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
ULONG
|
|
MM::PageMapXpa::GetPteSize(VOID)
|
|
{
|
|
/* Return the size of MMPTE */
|
|
return sizeof(MMPML3_PTE);
|
|
}
|
|
|
|
/**
|
|
* Initializes page map information for basic paging (PML3).
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMapXpa::InitializePageMapInfo(VOID)
|
|
{
|
|
/* Set PML3 page map information */
|
|
PageMapInfo.Xpa = TRUE;
|
|
|
|
/* Set PML3 empty PTE list mask */
|
|
PageMapInfo.EmptyPteList = (ULONG)0xFFFFFFFF;
|
|
|
|
/* Set PML3 base addresses */
|
|
PageMapInfo.PteBase = MM_PTE_BASE;
|
|
PageMapInfo.PdeBase = MM_PDE_BASE;
|
|
|
|
/* Set PML3 shift values */
|
|
PageMapInfo.PdiShift = MM_PDI_SHIFT;
|
|
PageMapInfo.PteShift = MM_PTE_SHIFT;
|
|
}
|
|
|
|
/**
|
|
* Checks whether the given PML3 page table entry (PTE) is valid.
|
|
*
|
|
* @param PtePointer
|
|
* Pointer to the page table entry (PTE) to check.
|
|
*
|
|
* @return Returns TRUE if the entry is valid, FALSE otherwise.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
BOOLEAN
|
|
MM::PageMapXpa::PteValid(PHARDWARE_PTE PtePointer)
|
|
{
|
|
return (BOOLEAN)PtePointer->Pml3.Valid;
|
|
}
|
|
|
|
/**
|
|
* Sets the next entry in a PTE list.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to modify.
|
|
*
|
|
* @param Value
|
|
* The value to set as the next entry.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMapXpa::SetNextEntry(PMMPTE Pte,
|
|
ULONG_PTR Value)
|
|
{
|
|
/* Set next entry in PTE list */
|
|
Pte->Pml3.List.NextEntry = Value;
|
|
}
|
|
|
|
/**
|
|
* Sets the flag indicating whether a PTE list contains only one entry.
|
|
*
|
|
* @param Pte
|
|
* The PTE pointer to modify.
|
|
*
|
|
* @param Value
|
|
* The value to set. TRUE if the list has only one entry, FALSE otherwise.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMapXpa::SetOneEntry(PMMPTE Pte,
|
|
BOOLEAN Value)
|
|
{
|
|
/* Set one entry status */
|
|
Pte->Pml3.List.OneEntry = Value;
|
|
}
|
|
|
|
/**
|
|
* Sets a PML3 page table entry (PTE) with the specified physical page and access flags.
|
|
*
|
|
* @param PtePointer
|
|
* Pointer to the page table entry (PTE) to set.
|
|
*
|
|
* @param PageFrameNumber
|
|
* Physical frame number to map.
|
|
*
|
|
* @param Writable
|
|
* Indicates whether the page should be writable.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMapXpa::SetPte(PHARDWARE_PTE PtePointer,
|
|
PFN_NUMBER PageFrameNumber,
|
|
BOOLEAN Writable)
|
|
{
|
|
/* Set PTE */
|
|
PtePointer->Pml3.PageFrameNumber = PageFrameNumber;
|
|
PtePointer->Pml3.Valid = 1;
|
|
PtePointer->Pml3.Writable = Writable;
|
|
}
|
|
|
|
/**
|
|
* Sets caching attributes for a PML3 page table entry (PTE).
|
|
*
|
|
* @param PtePointer
|
|
* Pointer to the page table entry (PTE) to modify.
|
|
*
|
|
* @param CacheDisable
|
|
* Indicates whether caching should be disabled for this page.
|
|
*
|
|
* @param WriteThrough
|
|
* Indicates whether write-through caching should be enabled.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
VOID
|
|
MM::PageMapXpa::SetPteCaching(PHARDWARE_PTE PtePointer,
|
|
BOOLEAN CacheDisable,
|
|
BOOLEAN WriteThrough)
|
|
{
|
|
/* Set caching attributes */
|
|
PtePointer->Pml3.CacheDisable = CacheDisable;
|
|
PtePointer->Pml3.WriteThrough = WriteThrough;
|
|
}
|