#pragma once /// \file paging.h /// Page table structure and related definitions #include #include #include "kernel_args.h" namespace boot { namespace paging { /// Struct to allow easy accessing of a memory page being used as a page table. struct page_table { uint64_t entries[512]; inline page_table * get(int i, uint16_t *flags = nullptr) const { uint64_t entry = entries[i]; if ((entry & 1) == 0) return nullptr; if (flags) *flags = entry & 0xfff; return reinterpret_cast(entry & ~0xfffull); } inline void set(int i, void *p, uint16_t flags) { entries[i] = reinterpret_cast(p) | (flags & 0xfff); } }; /// Allocate memory to be used for initial page tables. Initial offset-mapped /// page tables are pre-filled. All pages are saved as a module in kernel args /// and kernel args' `page_table_cache` and `num_free_tables` are updated with /// the leftover space. void allocate_tables( kernel::args::header *args, uefi::boot_services *bs); /// Copy existing page table entries to a new page table. Does not do a deep /// copy - the new PML4 is updated to point to the existing next-level page /// tables in the current PML4. void add_current_mappings(page_table *new_pml4); /// Map a physical address to a virtual address in the given page tables. /// \arg args The kernel args header, used for the page table cache and pml4 /// \arg phys The phyiscal address to map in /// \arg virt The virtual address to map in /// \arg size The size in bytes of the mapping void map_pages( kernel::args::header *args, uintptr_t phys, uintptr_t virt, size_t bytes); } // namespace paging } // namespace boot