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 =
|
ApicRegisters * apic_registers =
|
||||||
cast(ApicRegisters *)acpi.apic_address;
|
cast(ApicRegisters *)acpi.apic_address;
|
||||||
hurl.map(cast(ulong)apic_registers, cast(ulong)apic_registers,
|
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 ID: 0x%08x", apic_registers.lapic_id.read());
|
||||||
klog.writefln("LAPIC version: 0x%08x", apic_registers.lapic_version.read());
|
klog.writefln("LAPIC version: 0x%08x", apic_registers.lapic_version.read());
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
module hulk.hurl;
|
module hulk.hurl;
|
||||||
|
|
||||||
|
public import hulk.pagetable;
|
||||||
import hos.cpu;
|
import hos.cpu;
|
||||||
import hulk.hippo;
|
import hulk.hippo;
|
||||||
import hos.memory;
|
import hos.memory;
|
||||||
@ -21,76 +22,8 @@ enum ulong HULK_VIRTUAL_STACK_TOP_ADDRESS = 0xFFFF_A000_0000_0000u;
|
|||||||
/** HULK virtual framebuffer address. */
|
/** HULK virtual framebuffer address. */
|
||||||
enum ulong HULK_VIRTUAL_FRAMEBUFFER_ADDRESS = 0xFFFF_A000_0000_0000u;
|
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
|
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;
|
private static __gshared PageTable * m_pt_base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,27 +39,27 @@ struct hurl
|
|||||||
map_range(0u,
|
map_range(0u,
|
||||||
0u,
|
0u,
|
||||||
hippo.physical_address_limit,
|
hippo.physical_address_limit,
|
||||||
MAP_WRITABLE | MAP_NO_EXECUTE);
|
PT_WRITABLE | PT_NO_EXECUTE);
|
||||||
/* Map HULK binary region. */
|
/* Map HULK binary region. */
|
||||||
map_range(HULK_VIRTUAL_BASE_ADDRESS,
|
map_range(HULK_VIRTUAL_BASE_ADDRESS,
|
||||||
header.bootinfo.hulk_phys,
|
header.bootinfo.hulk_phys,
|
||||||
hulk_bin_phys_size,
|
hulk_bin_phys_size,
|
||||||
MAP_WRITABLE);
|
PT_WRITABLE);
|
||||||
/* Map HULK BSS region. */
|
/* Map HULK BSS region. */
|
||||||
map_range(HULK_VIRTUAL_BASE_ADDRESS + hulk_bin_phys_size,
|
map_range(HULK_VIRTUAL_BASE_ADDRESS + hulk_bin_phys_size,
|
||||||
header.bootinfo.bss_phys,
|
header.bootinfo.bss_phys,
|
||||||
LinkerAddresses.hulk_bss_size,
|
LinkerAddresses.hulk_bss_size,
|
||||||
MAP_WRITABLE | MAP_NO_EXECUTE);
|
PT_WRITABLE | PT_NO_EXECUTE);
|
||||||
/* Map HULK stack. */
|
/* Map HULK stack. */
|
||||||
map_range(HULK_VIRTUAL_STACK_TOP_ADDRESS - header.stack_size,
|
map_range(HULK_VIRTUAL_STACK_TOP_ADDRESS - header.stack_size,
|
||||||
header.bootinfo.stack_phys,
|
header.bootinfo.stack_phys,
|
||||||
header.stack_size,
|
header.stack_size,
|
||||||
MAP_WRITABLE | MAP_NO_EXECUTE);
|
PT_WRITABLE | PT_NO_EXECUTE);
|
||||||
/* Map HULK framebuffer. */
|
/* Map HULK framebuffer. */
|
||||||
map_range(HULK_VIRTUAL_FRAMEBUFFER_ADDRESS,
|
map_range(HULK_VIRTUAL_FRAMEBUFFER_ADDRESS,
|
||||||
cast(ulong)header.bootinfo.fb.buffer,
|
cast(ulong)header.bootinfo.fb.buffer,
|
||||||
header.bootinfo.fb.height * header.bootinfo.fb.stride * 4u,
|
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);
|
write_cr3(cast(ulong)m_pt_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,13 +78,13 @@ struct hurl
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PageTable * next_pt = allocate_pt();
|
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;
|
pt = next_pt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(*pt)[virtual, level] = PageTableEntry(physical, flags | MAP_PRESENT);
|
(*pt)[virtual, level] = PageTableEntry(physical, flags | PT_PRESENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,7 +125,7 @@ struct hurl
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((entry & MAP_HUGE_PAGE) != 0u)
|
if (entry.huge)
|
||||||
{
|
{
|
||||||
break;
|
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