From d9466f3d250084ea4e01e93d7c5f092934a64098 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Wed, 14 Apr 2021 21:57:23 +0200 Subject: [PATCH] stivale2: Implement unmap NULL using 4KiB pages --- stage23/mm/vmm.c | 17 +++++++++++------ stage23/mm/vmm.h | 5 ++--- stage23/protos/stivale.c | 28 +++++++++++++++++----------- test/stivale2.c | 6 +++--- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/stage23/mm/vmm.c b/stage23/mm/vmm.c index 46c59eb6..ef681d50 100644 --- a/stage23/mm/vmm.c +++ b/stage23/mm/vmm.c @@ -31,14 +31,15 @@ pagemap_t new_pagemap(int lv) { return pagemap; } -void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags) { +void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, bool hugepages) { // Calculate the indices in the various tables using the virtual address size_t pml5_entry = (virt_addr & ((uint64_t)0x1ff << 48)) >> 48; size_t pml4_entry = (virt_addr & ((uint64_t)0x1ff << 39)) >> 39; size_t pml3_entry = (virt_addr & ((uint64_t)0x1ff << 30)) >> 30; size_t pml2_entry = (virt_addr & ((uint64_t)0x1ff << 21)) >> 21; + size_t pml1_entry = (virt_addr & ((uint64_t)0x1ff << 12)) >> 12; - pt_entry_t *pml5, *pml4, *pml3, *pml2; + pt_entry_t *pml5, *pml4, *pml3, *pml2, *pml1; // Paging levels switch (pagemap.levels) { @@ -58,8 +59,12 @@ level4: pml3 = get_next_level(pml4, pml4_entry); pml2 = get_next_level(pml3, pml3_entry); - // Set the entry as present and point it to the passed physical address - // Also set the specified flags - // We only use 2MiB pages else we would not have enough space - pml2[pml2_entry] = (pt_entry_t)(phys_addr | flags | (1 << 7)); + if (hugepages) { + pml2[pml2_entry] = (pt_entry_t)(phys_addr | flags | (1 << 7)); + return; + } + + pml1 = get_next_level(pml2, pml2_entry); + + pml1[pml1_entry] = (pt_entry_t)(phys_addr | flags | (1 << 7)); } diff --git a/stage23/mm/vmm.h b/stage23/mm/vmm.h index fe265903..9aa096c5 100644 --- a/stage23/mm/vmm.h +++ b/stage23/mm/vmm.h @@ -2,8 +2,7 @@ #define __MM__VMM_H__ #include - -#define PAGE_SIZE ((uint64_t)0x200000) +#include typedef struct { int levels; @@ -11,6 +10,6 @@ typedef struct { } pagemap_t; pagemap_t new_pagemap(int lv); -void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags); +void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, bool hugepages); #endif diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c index 5f910ea6..a9d055a2 100644 --- a/stage23/protos/stivale.c +++ b/stage23/protos/stivale.c @@ -218,15 +218,21 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null) { uint64_t higher_half_base = level5pg ? 0xff00000000000000 : 0xffff800000000000; // Map 0 to 2GiB at 0xffffffff80000000 - for (uint64_t i = 0; i < 0x80000000; i += PAGE_SIZE) { - map_page(pagemap, 0xffffffff80000000 + i, i, 0x03); + for (uint64_t i = 0; i < 0x80000000; i += 0x200000) { + map_page(pagemap, 0xffffffff80000000 + i, i, 0x03, true); } - // Map 0 to 4GiB at higher half base and 0 - for (uint64_t i = 0; i < 0x100000000; i += PAGE_SIZE) { + // Sub 2MiB mappings + for (uint64_t i = 0; i < 0x200000; i += 0x1000) { if (!(i == 0 && unmap_null)) - map_page(pagemap, i, i, 0x03); - map_page(pagemap, higher_half_base + i, i, 0x03); + map_page(pagemap, i, i, 0x03, false); + map_page(pagemap, higher_half_base + i, i, 0x03, false); + } + + // Map 2MiB to 4GiB at higher half base and 0 + for (uint64_t i = 0x200000; i < 0x100000000; i += 0x200000) { + map_page(pagemap, i, i, 0x03, true); + map_page(pagemap, higher_half_base + i, i, 0x03, true); } size_t _memmap_entries = memmap_entries; @@ -247,14 +253,14 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null) { if (base >= top) continue; - uint64_t aligned_base = ALIGN_DOWN(base, PAGE_SIZE); - uint64_t aligned_top = ALIGN_UP(top, PAGE_SIZE); + uint64_t aligned_base = ALIGN_DOWN(base, 0x200000); + uint64_t aligned_top = ALIGN_UP(top, 0x200000); uint64_t aligned_length = aligned_top - aligned_base; - for (uint64_t i = 0; i < aligned_length; i += PAGE_SIZE) { + for (uint64_t i = 0; i < aligned_length; i += 0x200000) { uint64_t page = aligned_base + i; - map_page(pagemap, page, page, 0x03); - map_page(pagemap, higher_half_base + page, page, 0x03); + map_page(pagemap, page, page, 0x03, true); + map_page(pagemap, higher_half_base + page, page, 0x03, true); } } diff --git a/test/stivale2.c b/test/stivale2.c index b51c0a35..e196eecd 100644 --- a/test/stivale2.c +++ b/test/stivale2.c @@ -23,15 +23,15 @@ struct stivale2_header_tag_smp smp_request = { .flags = 0 }; -struct stivale2_tag fb_mtrr_request = { - .identifier = STIVALE2_HEADER_TAG_FB_MTRR_ID, +struct stivale2_tag unmap_null_request = { + .identifier = STIVALE2_HEADER_TAG_UNMAP_NULL_ID, .next = (uint64_t)&smp_request }; struct stivale2_header_tag_framebuffer framebuffer_request = { .tag = { .identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID, - .next = (uint64_t)&fb_mtrr_request + .next = (uint64_t)&unmap_null_request }, .framebuffer_width = 0, .framebuffer_height = 0,