Split PageTable struct out from hulk.hurl to hulk.pagetable

This commit is contained in:
josh committed 2022-10-25 23:30:17 -04:00
1 parent c11361d40f
commit 555ec9b627
3 files changed
+174 -77

No files matched your search

+164
View File
@@ -0,0 +1,164 @@
/**
* Page table structures.
*/
module hulk.pagetable;
/** Page table entry attributes. @{ */
enum ulong PT_PRESENT = 0x1u;
enum ulong PT_WRITABLE = 0x2u;
enum ulong PT_USER = 0x4u;
enum ulong PT_WRITE_THROUGH = 0x8u;
enum ulong PT_DISABLE_CACHE = 0x10u;
enum ulong PT_HUGE_PAGE = 0x80u;
enum ulong PT_GLOBAL = 0x100u;
enum ulong PT_NO_EXECUTE = 0x8000_0000_0000_0000u;
/** @} */
/**
* Structure that represents a page table entry.
*/
struct PageTableEntry
{
/** The raw page table entry is a 64-bit ulong. */
private ulong entry;
alias entry this;
/**
* Construct a page table entry.
*
* @param address
* Address pointed to by the page table entry (ulong or pointer).
* @param flags
* Page table flags (ORed set of PT_*).
*/
this(T)(T address, ulong flags = 0u)
{
entry = cast(ulong)address | flags;
}
/**
* Return whether the page is present.
*/
public @property bool present() const
{
return (entry & PT_PRESENT) != 0u;
}
/**
* Return whether the page is writable.
*/
public @property bool writable() const
{
return (entry & PT_WRITABLE) != 0u;
}
/**
* Return whether the page is a user page.
*/
public @property bool user() const
{
return (entry & PT_USER) != 0u;
}
/**
* Return whether the page is write-through.
*/
public @property bool write_through() const
{
return (entry & PT_WRITE_THROUGH) != 0u;
}
/**
* Return whether the page has disable cache set.
*/
public @property bool disable_cache() const
{
return (entry & PT_DISABLE_CACHE) != 0u;
}
/**
* Return whether the page is huge.
*/
public @property bool huge() const
{
return (entry & PT_HUGE_PAGE) != 0u;
}
/**
* Return whether the page is global.
*/
public @property bool global() const
{
return (entry & PT_GLOBAL) != 0u;
}
/**
* Return whether the page is no-execute.
*/
public @property bool no_execute() const
{
return (entry & PT_NO_EXECUTE) != 0u;
}
/**
* Follow the page table entry to the next page table it points to.
*/
public PageTable * follow() const
{
return cast(PageTable *)(entry & 0x7FFF_FFFF_FFFF_F000u);
}
}
static assert(PageTableEntry.sizeof == 8u);
/**
* Structure that represents a page table.
*/
struct PageTable
{
/** Page table entries. */
private PageTableEntry[512] entries;
/**
* Access the PageTableEntry for the given address and page table level.
*
* @param address
* Address to look up the page table entry (ulong or pointer).
* @param level
* Page table level (0-4).
*/
public PageTableEntry opIndex(T)(T address, ulong level)
{
return entries[pt_index(cast(ulong)address, level)];
}
/**
* Assign the PageTableEntry for the given address and page table level.
*
* @param pte
* PageTableEntry value to assign.
* @param address
* Address to look up the page table entry (ulong or pointer).
* @param level
* Page table level (0-4).
*/
public PageTableEntry opIndexAssign(T)(PageTableEntry pte, T address, ulong level)
{
entries[pt_index(cast(ulong)address, level)] = pte;
return pte;
}
/**
* Determine the index into the page table for the given address and page
* table level.
*
* @param address
* Address to look up the page table entry (ulong or pointer).
* @param level
* Page table level (0-4).
*/
public ulong pt_index(T)(T address, ulong level)
{
return (cast(ulong)address >> (39u - (9u * level))) & 0x1FFu;
}
}
static assert(PageTable.sizeof == 4096u);