HELLO: Create page tables to identity map available RAM prior to jumping to kernel

This commit is contained in:
Josh Holtrop 2022-03-18 21:15:58 -04:00
parent 9e3d9b18ea
commit a54536660b
3 changed files with 90 additions and 2 deletions

View File

@ -0,0 +1,33 @@
struct PageTableEntry
{
ulong entry;
this(ulong address, ulong no_execute, ulong global,
ulong huge, ulong disable_cache, ulong write_through, ulong user,
ulong writable, ulong present)
{
entry = (present |
(writable << 1) |
(user << 2) |
(write_through << 3) |
(disable_cache << 4) |
(huge << 7) |
(global << 8) |
(no_execute << 63)) | address;
}
bool present()
{
return (entry & 0x1u) != 0u;
}
PageTableEntry * next()
{
return cast(PageTableEntry *)(entry & 0x7FFF_FFFF_FFFF_F000u);
}
static ulong page_table_index(ulong address, size_t level)
{
return ((address >> (39u - 9u * level)) & 0x1FFu);
}
}

View File

@ -2,6 +2,8 @@ import uefi;
import output;
import scratch;
import hulk.bootinfo;
import hos.page_table;
import hos.cpu;
__gshared EFI_SYSTEM_TABLE * st;
__gshared BootInfo bootinfo;
@ -111,7 +113,7 @@ private bool get_memory_map()
(descriptor.Type == EfiBootServicesCode) ||
(descriptor.Type == EfiBootServicesData))
{
bootinfo.memory_map[di].base = cast(void *)descriptor.PhysicalStart;
bootinfo.memory_map[di].base = descriptor.PhysicalStart;
bootinfo.memory_map[di].size = descriptor.NumberOfPages * 4096u;
di++;
}
@ -120,6 +122,57 @@ private bool get_memory_map()
return true;
}
private PageTableEntry * new_page_table()
{
return cast(PageTableEntry *)scratch_alloc(1u);
}
private void map(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
{
PageTableEntry * pt = pt_base;
PageTableEntry * next_pt;
for (size_t level = 0; level < 4u; level++)
{
size_t pt_index = PageTableEntry.page_table_index(source_page, level);
if (pt[pt_index].present())
{
pt = pt[pt_index].next();
}
else
{
ulong addr;
if (level < 3u)
{
next_pt = new_page_table();
addr = cast(ulong)next_pt;
}
else
{
addr = dest_page;
}
pt[pt_index] = PageTableEntry(addr,
0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u);
pt = next_pt;
}
}
}
private void build_page_tables()
{
PageTableEntry * pt_base = new_page_table();
for (size_t i = 0u; i < bootinfo.memory_map_count; i++)
{
size_t n_pages = bootinfo.memory_map[i].size / 4096u;
for (size_t p = 0u; p < n_pages; p++)
{
ulong page_addr = bootinfo.memory_map[i].base + 4096u * p;
/* Identity map all pages. */
map(page_addr, page_addr, pt_base);
}
}
write_cr3(cast(ulong)pt_base);
}
extern (C) EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * st)
{
.st = st;
@ -153,5 +206,7 @@ extern (C) EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * st)
return EFI_SUCCESS;
}
build_page_tables();
return EFI_SUCCESS;
}

View File

@ -2,7 +2,7 @@ struct BootInfo
{
struct MemoryRegion
{
void * base;
ulong base;
size_t size;
}
struct Framebuffer