Build new page tables in HULK

This commit is contained in:
Josh Holtrop 2022-10-19 23:59:11 -04:00
parent c8a81b1101
commit c11361d40f
4 changed files with 75 additions and 16 deletions

View File

@ -58,7 +58,7 @@ struct acpi
public static void initialize(ulong acpi_xsdt_phys) public static void initialize(ulong acpi_xsdt_phys)
{ {
/* Map the XSDT header. */ /* Map the XSDT header. */
hurl.map_range(acpi_xsdt_phys, Xsdt.sizeof, 0u); hurl.identity_map_range(acpi_xsdt_phys, Xsdt.sizeof, 0u);
const(Xsdt) * xsdt = cast(const(Xsdt) *)acpi_xsdt_phys; const(Xsdt) * xsdt = cast(const(Xsdt) *)acpi_xsdt_phys;
if (xsdt.header.signature != XSDT_SIGNATURE) if (xsdt.header.signature != XSDT_SIGNATURE)
{ {
@ -66,12 +66,12 @@ struct acpi
return; return;
} }
/* Map the entire XSDT. */ /* Map the entire XSDT. */
hurl.map_range(acpi_xsdt_phys, xsdt.header.length, 0u); hurl.identity_map_range(acpi_xsdt_phys, xsdt.header.length, 0u);
size_t n_entries = (xsdt.header.length - xsdt.header.sizeof) / xsdt.tables[0].sizeof; size_t n_entries = (xsdt.header.length - xsdt.header.sizeof) / xsdt.tables[0].sizeof;
for (size_t i = 0u; i < n_entries; i++) for (size_t i = 0u; i < n_entries; i++)
{ {
ulong address = xsdt.tables[i]; ulong address = xsdt.tables[i];
hurl.map_range(address, 4u, 0u); hurl.identity_map_range(address, 4u, 0u);
uint signature = *cast(const(uint) *)address; uint signature = *cast(const(uint) *)address;
if (signature == APIC_SIGNATURE) if (signature == APIC_SIGNATURE)
{ {
@ -83,7 +83,7 @@ struct acpi
private static parse_apic_table(ulong address) private static parse_apic_table(ulong address)
{ {
const(MadtHeader) * madt_header = cast(const(MadtHeader) *)address; const(MadtHeader) * madt_header = cast(const(MadtHeader) *)address;
hurl.map_range(address, madt_header.length, 0u); hurl.identity_map_range(address, madt_header.length, 0u);
apic_address = madt_header.local_apic_address; apic_address = madt_header.local_apic_address;
klog.writefln("Found 32-bit APIC address: 0x%x", apic_address); klog.writefln("Found 32-bit APIC address: 0x%x", apic_address);
const(void) * madt_end = cast(const(void) *)(address + madt_header.length); const(void) * madt_end = cast(const(void) *)(address + madt_header.length);

View File

@ -31,6 +31,11 @@ struct hippo
*/ */
private static __gshared size_t n_free_pages; private static __gshared size_t n_free_pages;
/**
* Physical address limit.
*/
public static __gshared size_t physical_address_limit;
/** /**
* Initialize HIPPO. * Initialize HIPPO.
* *
@ -54,7 +59,7 @@ struct hippo
[header.bootinfo.hulk_phys, cast(ulong)header.total_size - LinkerAddresses.hulk_bss_size], [header.bootinfo.hulk_phys, cast(ulong)header.total_size - LinkerAddresses.hulk_bss_size],
[header.bootinfo.bss_phys, LinkerAddresses.hulk_bss_size], [header.bootinfo.bss_phys, LinkerAddresses.hulk_bss_size],
[header.bootinfo.stack_phys, header.stack_size], [header.bootinfo.stack_phys, header.stack_size],
[cast(ulong)header.bootinfo.fb.buffer, header.bootinfo.fb.height * header.bootinfo.fb.stride], [cast(ulong)header.bootinfo.fb.buffer, header.bootinfo.fb.height * header.bootinfo.fb.stride * 4u],
[header.bootinfo.pt_phys, header.bootinfo.pt_size], [header.bootinfo.pt_phys, header.bootinfo.pt_size],
]; ];
for (size_t ri = 0u; ri < reserved.length; ri++) for (size_t ri = 0u; ri < reserved.length; ri++)
@ -67,6 +72,10 @@ struct hippo
{ {
ulong phys = header.bootinfo.memory_map[bii].base; ulong phys = header.bootinfo.memory_map[bii].base;
ulong phys_end = phys + header.bootinfo.memory_map[bii].size; ulong phys_end = phys + header.bootinfo.memory_map[bii].size;
if (phys_end > physical_address_limit)
{
physical_address_limit = phys_end;
}
usable_memory += header.bootinfo.memory_map[bii].size; usable_memory += header.bootinfo.memory_map[bii].size;
while (phys < phys_end) while (phys < phys_end)
{ {

View File

@ -41,7 +41,6 @@ void hulk_start()
cli(); cli();
gdt.initialize(); gdt.initialize();
idt.initialize(); idt.initialize();
hurl.initialize();
fb.initialize(cast(uint *)HULK_VIRTUAL_FRAMEBUFFER_ADDRESS, hulk_header.bootinfo.fb.width, hulk_header.bootinfo.fb.height, hulk_header.bootinfo.fb.stride); fb.initialize(cast(uint *)HULK_VIRTUAL_FRAMEBUFFER_ADDRESS, hulk_header.bootinfo.fb.width, hulk_header.bootinfo.fb.height, hulk_header.bootinfo.fb.stride);
console.initialize(); console.initialize();
console.clear(); console.clear();
@ -50,6 +49,7 @@ void hulk_start()
klog.writefln("Welcome to HULK, the HOS UltraLight Kernel!"); klog.writefln("Welcome to HULK, the HOS UltraLight Kernel!");
hippo.initialize(&hulk_header); hippo.initialize(&hulk_header);
hurl.initialize(&hulk_header);
pci.initialize(); pci.initialize();
pic.initialize(); pic.initialize();
acpi.initialize(hulk_header.bootinfo.acpi_xsdt_phys); acpi.initialize(hulk_header.bootinfo.acpi_xsdt_phys);

View File

@ -9,6 +9,8 @@ import hos.cpu;
import hulk.hippo; import hulk.hippo;
import hos.memory; import hos.memory;
import hulk.klog; import hulk.klog;
import hulk.header;
import hulk.linker_addresses;
/** HULK virtual base address. */ /** HULK virtual base address. */
enum ulong HULK_VIRTUAL_BASE_ADDRESS = 0xFFFF_8000_0000_0000u; enum ulong HULK_VIRTUAL_BASE_ADDRESS = 0xFFFF_8000_0000_0000u;
@ -91,18 +93,49 @@ struct hurl
private static __gshared PageTable * m_pt_base; private static __gshared PageTable * m_pt_base;
public static void initialize() /**
* Initialize HURL.
*
* @param bootinfo HULK boot information structure.
*/
public static void initialize(HulkHeader * header)
{ {
m_pt_base = cast(PageTable *)read_cr3(); m_pt_base = allocate_pt();
size_t hulk_bin_phys_size = cast(ulong)header.total_size - LinkerAddresses.hulk_bss_size;
/* Identity map all physical RAM. */
map_range(0u,
0u,
hippo.physical_address_limit,
MAP_WRITABLE | MAP_NO_EXECUTE);
/* Map HULK binary region. */
map_range(HULK_VIRTUAL_BASE_ADDRESS,
header.bootinfo.hulk_phys,
hulk_bin_phys_size,
MAP_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);
/* 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);
/* 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);
write_cr3(cast(ulong)m_pt_base);
} }
public static void map(ulong virtual, ulong physical, ulong flags) public static void map(ulong virtual, ulong physical, ulong flags)
{ {
size_t last_level = ((flags & MAP_HUGE_PAGE) != 0u) ? 2u : 3u;
PageTable * pt = m_pt_base; PageTable * pt = m_pt_base;
for (size_t level = 0; level <= last_level; level++) for (size_t level = 0; level < 4u; level++)
{ {
if (level < last_level) if (level < 3u)
{ {
PageTableEntry entry = (*pt)[virtual, level]; PageTableEntry entry = (*pt)[virtual, level];
if (entry.present) if (entry.present)
@ -111,8 +144,7 @@ struct hurl
} }
else else
{ {
PageTable * next_pt = cast(PageTable *)hippo.allocate_page(); PageTable * next_pt = allocate_pt();
memset64(next_pt, 0u, PAGE_SIZE / 8u);
(*pt)[virtual, level] = PageTableEntry(next_pt, MAP_WRITABLE | MAP_PRESENT); (*pt)[virtual, level] = PageTableEntry(next_pt, MAP_WRITABLE | MAP_PRESENT);
pt = next_pt; pt = next_pt;
} }
@ -124,12 +156,23 @@ struct hurl
} }
} }
public static void map_range(size_t address, size_t length, ulong flags) public static void map_range(size_t virtual, size_t physical, size_t length, ulong flags)
{
size_t end = virtual + length;
while (virtual < end)
{
map(virtual, physical, flags);
virtual += PAGE_SIZE;
physical += PAGE_SIZE;
}
}
public static void identity_map_range(size_t address, size_t length, ulong flags)
{ {
size_t end = address + length; size_t end = address + length;
for (size_t page = address & ~0xFFFu; page < end; page += 0x1000u) for (size_t page = address & ~0xFFFu; page < end; page += PAGE_SIZE)
{ {
map(address, address, flags); map(page, page, flags);
} }
} }
@ -155,4 +198,11 @@ struct hurl
} }
} }
} }
private static PageTable * allocate_pt()
{
PageTable * pt = cast(PageTable *)hippo.allocate_page();
memset64(pt, 0u, PAGE_SIZE / 8u);
return pt;
}
} }