Split PageTable struct out from hulk.hurl to hulk.pagetable
This commit is contained in:
parent
c11361d40f
commit
555ec9b627
@ -62,7 +62,7 @@ struct apic
|
||||
ApicRegisters * apic_registers =
|
||||
cast(ApicRegisters *)acpi.apic_address;
|
||||
hurl.map(cast(ulong)apic_registers, cast(ulong)apic_registers,
|
||||
MAP_WRITABLE | MAP_WRITE_THROUGH | MAP_DISABLE_CACHE | MAP_NO_EXECUTE);
|
||||
PT_WRITABLE | PT_WRITE_THROUGH | PT_DISABLE_CACHE | PT_NO_EXECUTE);
|
||||
klog.writefln("LAPIC ID: 0x%08x", apic_registers.lapic_id.read());
|
||||
klog.writefln("LAPIC version: 0x%08x", apic_registers.lapic_version.read());
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
module hulk.hurl;
|
||||
|
||||
public import hulk.pagetable;
|
||||
import hos.cpu;
|
||||
import hulk.hippo;
|
||||
import hos.memory;
|
||||
@ -21,76 +22,8 @@ enum ulong HULK_VIRTUAL_STACK_TOP_ADDRESS = 0xFFFF_A000_0000_0000u;
|
||||
/** HULK virtual framebuffer address. */
|
||||
enum ulong HULK_VIRTUAL_FRAMEBUFFER_ADDRESS = 0xFFFF_A000_0000_0000u;
|
||||
|
||||
/** Page table entry attributes. @{ */
|
||||
enum ulong MAP_PRESENT = 0x1u;
|
||||
enum ulong MAP_WRITABLE = 0x2u;
|
||||
enum ulong MAP_USER = 0x4u;
|
||||
enum ulong MAP_WRITE_THROUGH = 0x8u;
|
||||
enum ulong MAP_DISABLE_CACHE = 0x10u;
|
||||
enum ulong MAP_HUGE_PAGE = 0x20u;
|
||||
enum ulong MAP_GLOBAL = 0x40u;
|
||||
enum ulong MAP_NO_EXECUTE = 0x8000_0000_0000_0000u;
|
||||
/** @} */
|
||||
|
||||
struct hurl
|
||||
{
|
||||
private struct PageTableEntry
|
||||
{
|
||||
private ulong m_entry;
|
||||
alias m_entry this;
|
||||
|
||||
this(ulong address, ulong flags)
|
||||
{
|
||||
m_entry = address | flags;
|
||||
}
|
||||
|
||||
this(void * address, ulong flags)
|
||||
{
|
||||
m_entry = cast(ulong)address | flags;
|
||||
}
|
||||
|
||||
public @property bool present()
|
||||
{
|
||||
return (m_entry & MAP_PRESENT) != 0u;
|
||||
}
|
||||
|
||||
public PageTable * follow()
|
||||
{
|
||||
return cast(PageTable *)(m_entry & 0x7FFF_FFFF_FFFF_F000u);
|
||||
}
|
||||
}
|
||||
|
||||
private struct PageTable
|
||||
{
|
||||
public PageTableEntry opIndex(ulong address, ulong level)
|
||||
{
|
||||
PageTableEntry * entries = cast(PageTableEntry *)&this;
|
||||
return entries[pt_index(address, level)];
|
||||
}
|
||||
|
||||
public PageTableEntry opIndex(void * address, ulong level)
|
||||
{
|
||||
return opIndex(cast(ulong)address, level);
|
||||
}
|
||||
|
||||
public PageTableEntry opIndexAssign(PageTableEntry pte, ulong address, ulong level)
|
||||
{
|
||||
PageTableEntry * entries = cast(PageTableEntry *)&this;
|
||||
entries[pt_index(address, level)] = pte;
|
||||
return pte;
|
||||
}
|
||||
|
||||
public PageTableEntry opIndexAssign(PageTableEntry pte, void * address, ulong level)
|
||||
{
|
||||
return opIndexAssign(pte, cast(ulong)address, level);
|
||||
}
|
||||
|
||||
public ulong pt_index(ulong address, ulong level)
|
||||
{
|
||||
return (address >> (39u - (9u * level))) & 0x1FFu;
|
||||
}
|
||||
}
|
||||
|
||||
private static __gshared PageTable * m_pt_base;
|
||||
|
||||
/**
|
||||
@ -106,27 +39,27 @@ struct hurl
|
||||
map_range(0u,
|
||||
0u,
|
||||
hippo.physical_address_limit,
|
||||
MAP_WRITABLE | MAP_NO_EXECUTE);
|
||||
PT_WRITABLE | PT_NO_EXECUTE);
|
||||
/* Map HULK binary region. */
|
||||
map_range(HULK_VIRTUAL_BASE_ADDRESS,
|
||||
header.bootinfo.hulk_phys,
|
||||
hulk_bin_phys_size,
|
||||
MAP_WRITABLE);
|
||||
PT_WRITABLE);
|
||||
/* Map HULK BSS region. */
|
||||
map_range(HULK_VIRTUAL_BASE_ADDRESS + hulk_bin_phys_size,
|
||||
header.bootinfo.bss_phys,
|
||||
LinkerAddresses.hulk_bss_size,
|
||||
MAP_WRITABLE | MAP_NO_EXECUTE);
|
||||
PT_WRITABLE | PT_NO_EXECUTE);
|
||||
/* Map HULK stack. */
|
||||
map_range(HULK_VIRTUAL_STACK_TOP_ADDRESS - header.stack_size,
|
||||
header.bootinfo.stack_phys,
|
||||
header.stack_size,
|
||||
MAP_WRITABLE | MAP_NO_EXECUTE);
|
||||
PT_WRITABLE | PT_NO_EXECUTE);
|
||||
/* Map HULK framebuffer. */
|
||||
map_range(HULK_VIRTUAL_FRAMEBUFFER_ADDRESS,
|
||||
cast(ulong)header.bootinfo.fb.buffer,
|
||||
header.bootinfo.fb.height * header.bootinfo.fb.stride * 4u,
|
||||
MAP_WRITABLE | MAP_NO_EXECUTE);
|
||||
PT_WRITABLE | PT_NO_EXECUTE);
|
||||
write_cr3(cast(ulong)m_pt_base);
|
||||
}
|
||||
|
||||
@ -145,13 +78,13 @@ struct hurl
|
||||
else
|
||||
{
|
||||
PageTable * next_pt = allocate_pt();
|
||||
(*pt)[virtual, level] = PageTableEntry(next_pt, MAP_WRITABLE | MAP_PRESENT);
|
||||
(*pt)[virtual, level] = PageTableEntry(next_pt, PT_WRITABLE | PT_PRESENT);
|
||||
pt = next_pt;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*pt)[virtual, level] = PageTableEntry(physical, flags | MAP_PRESENT);
|
||||
(*pt)[virtual, level] = PageTableEntry(physical, flags | PT_PRESENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -192,7 +125,7 @@ struct hurl
|
||||
{
|
||||
break;
|
||||
}
|
||||
if ((entry & MAP_HUGE_PAGE) != 0u)
|
||||
if (entry.huge)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
164
src/hulk/pagetable.d
Normal file
164
src/hulk/pagetable.d
Normal 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);
|
Loading…
x
Reference in New Issue
Block a user