ArvernOS
Loading...
Searching...
No Matches
paging.h File Reference
#include <mmu/frame.h>
#include <stdint.h>
#include <sys/types.h>
Include dependency graph for paging.h:

Data Structures

struct  page_table_t

Macros

#define USER_SPACE_END   0x80000000
 End of the user address space.
#define PAGING_FLAG_PRESENT   (1 << 0)
 Specifies whether the mapped page is loaded in memory.
#define PAGING_FLAG_WRITABLE   (1 << 1)
 Controls whether writes to the mapped frames are allowed.
#define PAGING_FLAG_USER_ACCESSIBLE   (1 << 2)
 Controls whether accesses from userspace (i.e. ring 3) are permitted.
#define PAGING_FLAG_HUGE_PAGE   (1 << 7)
 Tells whether the mapped page is a huge page.
#define PAGING_FLAG_NO_EXECUTE   ((uint64_t)1 << 63)
 Forbids executing code on this page.
#define USER_P3_INDEX   1
 The user space lives in P3 index 1.

Functions

void paging_init ()
 Initializes paging to separate virtual and physical memory.
page_number_t page_containing_address (uint64_t virtual_address)
uint64_t page_start_address (page_number_t page_number)
opt_uint64_t translate_page (page_number_t page_number)
opt_uint64_t translate (uint64_t virtual_address)
void map (page_number_t page_number, uint64_t flags)
void map_multiple (page_number_t start_page_number, uint32_t number_of_pages, uint64_t flags)
void unmap (page_number_t page_number)
void unmap_multiple (page_number_t start_page_number, uint32_t number_of_pages)
uint32_t paging_amount_for_byte_size (uint64_t start_address, uint64_t byte_size)
void identity_map (uint64_t address, uint64_t flags)
void * paging_create_user_space ()
void paging_activate (void *space)
void paging_deactivate (void *space)

Function Documentation

◆ identity_map()

void identity_map ( uint64_t address,
uint64_t flags )

Maps a page (virtual address) to the equivalent frame (physical address).

Parameters
addressthe address to map
flagspaging flags

◆ map()

void map ( page_number_t page_number,
uint64_t flags )

Convenient function to map a page (number) without providing a frame. The frame is automatically allocated.

Parameters
page_numbera page number (not an address)
flagspaging flags

◆ map_multiple()

void map_multiple ( page_number_t start_page_number,
uint32_t number_of_pages,
uint64_t flags )

Maps multiple pages in a row if possible.

Parameters
start_page_numberthe first page of the sequence
number_of_pagesthe amount of pages to map
flagsthe paging flags

◆ page_containing_address()

page_number_t page_containing_address ( uint64_t virtual_address)

Returns a page number given a virtual address.

Parameters
virtual_addressa virtual address (page)
Returns
a page number

◆ page_start_address()

uint64_t page_start_address ( page_number_t page_number)

Returns the virtual start address of a page.

Parameters
page_numbera page number
Returns
a virtual address (page)

◆ paging_activate()

void paging_activate ( void * space)

Activates an address space.

Parameters
spacean address space returned by paging_create_user_space(), or NULL for the kernel address space

◆ paging_amount_for_byte_size()

uint32_t paging_amount_for_byte_size ( uint64_t start_address,
uint64_t byte_size )

Calculates how many pages are needed for a range of addresses.

Parameters
start_addressthe starting virtual address
byte_sizethe amount of bytes
Returns
the amount of pages required for mapping from start_address until start_address + byte_size

◆ paging_create_user_space()

void * paging_create_user_space ( )

Creates a new (empty) user address space that shares the kernel mappings.

Returns
the physical address of the new P4 table, or NULL on failure

Do not free the frames that we temporarily map while writing the tables.

◆ paging_deactivate()

void paging_deactivate ( void * space)

Deactivates an address space created by paging_create_user_space(), freeing its user pages and private page tables.

Parameters
spacethe address space to deactivate

running on it.

◆ paging_init()

void paging_init ( )

Initializes paging to separate virtual and physical memory.

The bootloader (assembly code) already set up a 4-level paging hierarchy that maps every page of our kernel to a physical frame. It does this because paging is mandatory in 64-bit mode on x86_64.

This means that every memory address that we used in our kernel was a virtual address. Accessing the VGA buffer at address 0xb8000 only worked because the bootloader identity mapped that memory page, which means that it mapped the virtual page 0xb8000 to the physical frame 0xb8000.

In addition, this improves safety since illegal memory accesses cause page fault exceptions instead of modifying arbitrary physical memory. That being said, identity mapping clutters the virtual address space and makes it more difficult to find continuous memory regions of larger sizes (like 1000 KiB).

We remap the kernel and other useful sections/addresses in this function, then we enable write protection, the NXE bit and we switch to our own table. This allows us to make everything safer. Memory is still identity mapped, which isn't great but it works for now.

◆ translate()

opt_uint64_t translate ( uint64_t virtual_address)

Translates a virtual address to the corresponding physical address.

Parameters
virtual_addressa virtual address
Returns
a physical address (optional)

◆ translate_page()

opt_uint64_t translate_page ( page_number_t page_number)

Translates a page number to a frame number.

Parameters
page_numbera page number (not an address)
Returns
a frame number (optional)

◆ unmap()

void unmap ( page_number_t page_number)

Unmaps (free) a page.

Parameters
page_numbera page number (not an address)
Todo
Free p(1,2,3) table if empty.

◆ unmap_multiple()

void unmap_multiple ( page_number_t start_page_number,
uint32_t number_of_pages )

Unmaps multiple consecutive pages.

Parameters
start_page_numberthe first page of the sequence
number_of_pagesthe amount of pages to unmap