HELLO: Create page tables to identity map available RAM prior to jumping to kernel
This commit is contained in:
parent
9e3d9b18ea
commit
a54536660b
33
src/common/hos/page_table.d
Normal file
33
src/common/hos/page_table.d
Normal 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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ struct BootInfo
|
||||
{
|
||||
struct MemoryRegion
|
||||
{
|
||||
void * base;
|
||||
ulong base;
|
||||
size_t size;
|
||||
}
|
||||
struct Framebuffer
|
||||
|
Loading…
x
Reference in New Issue
Block a user