From c11361d40f939dc62584cf46968e20e49f4648b9 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Wed, 19 Oct 2022 23:59:11 -0400 Subject: [PATCH] Build new page tables in HULK --- src/hulk/acpi.d | 8 +++--- src/hulk/hippo.d | 11 +++++++- src/hulk/hulk.d | 2 +- src/hulk/hurl.d | 70 +++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/src/hulk/acpi.d b/src/hulk/acpi.d index 35f112b..2763dd1 100644 --- a/src/hulk/acpi.d +++ b/src/hulk/acpi.d @@ -58,7 +58,7 @@ struct acpi public static void initialize(ulong acpi_xsdt_phys) { /* 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; if (xsdt.header.signature != XSDT_SIGNATURE) { @@ -66,12 +66,12 @@ struct acpi return; } /* 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; for (size_t i = 0u; i < n_entries; 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; if (signature == APIC_SIGNATURE) { @@ -83,7 +83,7 @@ struct acpi private static parse_apic_table(ulong 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; klog.writefln("Found 32-bit APIC address: 0x%x", apic_address); const(void) * madt_end = cast(const(void) *)(address + madt_header.length); diff --git a/src/hulk/hippo.d b/src/hulk/hippo.d index a63c26f..8106d10 100644 --- a/src/hulk/hippo.d +++ b/src/hulk/hippo.d @@ -31,6 +31,11 @@ struct hippo */ private static __gshared size_t n_free_pages; + /** + * Physical address limit. + */ + public static __gshared size_t physical_address_limit; + /** * Initialize HIPPO. * @@ -54,7 +59,7 @@ struct hippo [header.bootinfo.hulk_phys, cast(ulong)header.total_size - LinkerAddresses.hulk_bss_size], [header.bootinfo.bss_phys, LinkerAddresses.hulk_bss_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], ]; 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_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; while (phys < phys_end) { diff --git a/src/hulk/hulk.d b/src/hulk/hulk.d index 27f1950..412c3c2 100644 --- a/src/hulk/hulk.d +++ b/src/hulk/hulk.d @@ -41,7 +41,6 @@ void hulk_start() cli(); gdt.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); console.initialize(); console.clear(); @@ -50,6 +49,7 @@ void hulk_start() klog.writefln("Welcome to HULK, the HOS UltraLight Kernel!"); hippo.initialize(&hulk_header); + hurl.initialize(&hulk_header); pci.initialize(); pic.initialize(); acpi.initialize(hulk_header.bootinfo.acpi_xsdt_phys); diff --git a/src/hulk/hurl.d b/src/hulk/hurl.d index 1988444..057c1e2 100644 --- a/src/hulk/hurl.d +++ b/src/hulk/hurl.d @@ -9,6 +9,8 @@ import hos.cpu; import hulk.hippo; import hos.memory; import hulk.klog; +import hulk.header; +import hulk.linker_addresses; /** HULK virtual base address. */ enum ulong HULK_VIRTUAL_BASE_ADDRESS = 0xFFFF_8000_0000_0000u; @@ -91,18 +93,49 @@ struct hurl 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) { - size_t last_level = ((flags & MAP_HUGE_PAGE) != 0u) ? 2u : 3u; 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]; if (entry.present) @@ -111,8 +144,7 @@ struct hurl } else { - PageTable * next_pt = cast(PageTable *)hippo.allocate_page(); - memset64(next_pt, 0u, PAGE_SIZE / 8u); + PageTable * next_pt = allocate_pt(); (*pt)[virtual, level] = PageTableEntry(next_pt, MAP_WRITABLE | MAP_PRESENT); 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; - 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; + } }