Virtual Memory Manager. More...
Data Structures | |
struct | vmm_domain_t |
We use two domains, kernel and user memory. More... | |
union | vmm_virtual_address_t |
A virtual address. More... | |
struct | page_directory_entry_t |
An entry in a page directory. More... | |
struct | page_table_entry_t |
An entry in a page table. More... | |
Macros | |
#define | ENTRIES 1024 |
number of entries in page directories and tables | |
#define | PAGE_SIZE (ENTRIES * sizeof(page_directory_entry_t)) |
The number of bytes per page directory "happens" to equal the size of a page. | |
#define | MEMORY_SIZE 0x100000000 |
4GB address space | |
#define | PAGE_NUMBER (MEMORY_SIZE / PAGE_SIZE) |
total number of pages | |
#define | VMM_PAGEDIR ((page_directory_t*) 0xFFFFF000) |
the active page directory's address More... | |
#define | VMM_PAGETAB(i) ((page_table_t*) (0xFFC00000 + (i) * PAGE_SIZE)) |
the address of a page table from the active page directory More... | |
Typedefs | |
typedef page_directory_entry_t | page_directory_t |
a page directory is a pointer to its first entry | |
typedef page_table_entry_t | page_table_t |
a page table is a pointer to its first entry | |
Enumerations | |
enum | vmm_flags_t { VMM_KERNEL = 0b0, VMM_USER = 0b1, VMM_WRITABLE = 0b100 } |
Whether we are working with kernel or user memory. More... | |
Functions | |
static void | vmm_destroy_page_table (uint16_t page_table) |
Destroys a page table in the current page directory. More... | |
page_directory_t * | vmm_create_page_directory () |
Creates an empty page directory. More... | |
void | vmm_destroy_page_directory (page_directory_t *dir_phys) |
Destroys a page directory. More... | |
static void | vmm_refresh_page_directory (page_directory_t *dir_phys) |
Refreshes the page directory entries that are shared across page directories. More... | |
page_directory_t * | vmm_load_page_directory (page_directory_t *new_directory) |
Loads a new page directory. More... | |
void | vmm_modify_page_directory (page_directory_t *new_directory) |
Loads a page directory for temporary modification. More... | |
void | vmm_modified_page_directory () |
Ends a page directory modification. More... | |
static page_table_entry_t * | vmm_get_page_table (page_directory_entry_t *dir_entry, vmm_virtual_address_t vaddr) |
Returns a virtual or physical address to a page table in memory. More... | |
static page_table_entry_t * | vmm_get_page_table_entry (page_directory_entry_t *dir_entry, vmm_virtual_address_t vaddr) |
Returns a virtual or physical address to a page table entry in memory. More... | |
static vmm_domain_t * | vmm_get_domain (vmm_flags_t flags) |
Extracts a domain from the given flags. More... | |
static uint8_t | vmm_is_in_domain (void *vaddr, vmm_domain_t *domain) |
Returns whether a virtual address belongs to a given domain. More... | |
static vmm_domain_t * | vmm_get_domain_from_address (void *vaddr) |
Returns the domain a virtual address belongs to. More... | |
static uint8_t | vmm_domain_check (void *vaddr, vmm_flags_t flags) |
Checks whether a virtual address might be accessed with the given flags. More... | |
uint8_t | vmm_map (void *_vaddr, void *paddr, vmm_flags_t flags) |
Maps the given page into memory. More... | |
void | vmm_unmap (void *_vaddr) |
Unmaps the given page from memory. More... | |
static void | vmm_map_range_detailed (void *vaddr, void *paddr, size_t len, vmm_flags_t flags, uint8_t map) |
Maps or unmaps the given page(s) into memory. More... | |
void | vmm_map_range (void *vaddr, void *paddr, size_t len, vmm_flags_t flags) |
Maps the given page(s) into memory. More... | |
void | vmm_unmap_range (void *vaddr, size_t len) |
Unmaps the given page(s) from memory. More... | |
void * | vmm_get_physical_address (void *_vaddr) |
Translates a virtual address into a physical address. More... | |
void | vmm_dump () |
Dumps the current page directory. More... | |
static void * | vmm_find_free (size_t len, vmm_domain_t *domain) |
Finds unmapped pages. More... | |
static pmm_flags_t | vmm_get_pmm_flags (vmm_flags_t flags) |
Translates VMM into PMM flags. More... | |
void * | vmm_map_physical_memory (void *paddr, size_t len, vmm_flags_t flags) |
If necessary, maps the given page(s) somewhere into memory. More... | |
void | vmm_unmap_physical_memory (void *vaddr, size_t len) |
If necessary, unmaps the given page(s) from memory. More... | |
void | vmm_use (void *vaddr, void *paddr, size_t len, vmm_flags_t flags) |
Marks the given page(s) as used and maps them into memory. More... | |
void * | vmm_use_physical_memory (void *paddr, size_t len, vmm_flags_t flags) |
Marks the given page(s) as used and maps them somewhere into memory. More... | |
void * | vmm_use_virtual_memory (void *vaddr, size_t len, vmm_flags_t flags) |
Marks some page(s) as used and maps them into memory. More... | |
void * | vmm_alloc (size_t len, vmm_flags_t flags) |
Marks some page(s) as used and maps them somewhere into memory. More... | |
void | vmm_free (void *vaddr, size_t len) |
Frees the given page(s) and unmaps them from memory. More... | |
void | vmm_enable_domain_check (uint8_t enable) |
Enables or disables domain checking. More... | |
void | vmm_init () |
Initializes the VMM. More... | |
Variables | |
static page_directory_t * | page_directory = 0 |
the current page directory | |
static page_directory_t * | old_directory = 0 |
for temporary modifications | |
static uint8_t | old_interrupts = 0 |
for temporary modifications | |
static vmm_domain_t | kernel_domain |
We use 0-1GiB as kernel memory. More... | |
static vmm_domain_t | user_domain |
The memory 1GiB-4GiB is process-specific. More... | |
static uint8_t | domain_check_enabled = 0 |
whether domain checking is performed | |
Virtual Memory Manager.
The VMM manages paging and memory contexts. It maps virtual to physical memory, allocates and frees virtual memory and switches page directories.
#define VMM_PAGEDIR ((page_directory_t*) 0xFFFFF000) |
#define VMM_PAGETAB | ( | i | ) | ((page_table_t*) (0xFFC00000 + (i) * PAGE_SIZE)) |
enum vmm_flags_t |
void * vmm_alloc | ( | size_t | len, |
vmm_flags_t | flags | ||
) |
Marks some page(s) as used and maps them somewhere into memory.
len | the number of bytes to be mapped |
flags | the flags for mapping |
Definition at line 511 of file vmm.c.
page_directory_t * vmm_create_page_directory | ( | ) |
Creates an empty page directory.
It itself is mapped into the last page table.
Maps the last entry to itself, see vmm_init() for a detailed explanation.
Definition at line 72 of file vmm.c.
void vmm_destroy_page_directory | ( | page_directory_t * | dir_phys | ) |
Destroys a page directory.
dir_phys | the physical address of the page directory to be destroyed |
Operates on the directory we want to destroy.
Deletes any unique page tables associated with this directory:
First VM86, then user domain page tables.
Frees the page directory itself.
Definition at line 90 of file vmm.c.
|
static |
Destroys a page table in the current page directory.
page_table | the index of the page table to destroy |
Frees the page table memory using its physical address.
Tells the page directory that this page table was deleted.
Definition at line 61 of file vmm.c.
|
static |
Checks whether a virtual address might be accessed with the given flags.
vaddr | the virtual address |
flags | the flags |
Definition at line 237 of file vmm.c.
void vmm_dump | ( | ) |
void vmm_enable_domain_check | ( | uint8_t | enable | ) |
|
static |
void vmm_free | ( | void * | vaddr, |
size_t | len | ||
) |
|
static |
|
static |
|
static |
Returns a virtual or physical address to a page table in memory.
dir_entry | the page directory entry for the requested page table |
vaddr | a virtual address belonging to the requested page table |
Definition at line 180 of file vmm.c.
|
static |
Returns a virtual or physical address to a page table entry in memory.
dir_entry | the page directory entry for the requested page table entry |
vaddr | a virtual address belonging to the requested page table entry |
Definition at line 196 of file vmm.c.
void * vmm_get_physical_address | ( | void * | _vaddr | ) |
|
static |
void vmm_init | ( | ) |
Initializes the VMM.
Identity maps all up to now used kernel pages. The PMM has memorized up to which page we need to map at most to speed up the process.
In vmm_create_page_directory() the last entry points to itself so we can use it as a page table to be able to dynamically (un)map and virtual addresses. This allows us to refer to the page directory (wherever it is in physical memory) with the virtual address 0xFFFFF000 as soon as paging is enabled:
So 0xFFFFF000 refers to the last PDE (which is the directory itself) and then the last PTE which is the directory again, in a recursive manner. So 0xFFFFF000 points to the page directory and is one page (4096 or 0x1000 bytes) long, so it lies at 0xFFFFF000-0xFFFFFFFF (at the very end).
Loads the new page directory.
Now we are working with virtual addresses, so to access our directory we use 0xFFFFF000 as explained above. From now on all addresses are virtual addresses, but this is transparent because we identity-mapped the kernel! Note that in this way, we can access all page tables as well. Take, for example, the first page table: Because we mapped the last directory entry to the directory itself, the last 4MB of our address space (0xFFC00000- 0xFFFFFFFF) represent the whole page directory. To access the first page table, we just have to use the address 0xFFC00000 as explained above:
So 0xFFC00000 refers to the last PDE (the page directory) and then the first table inside the directory which points to the physical location of the page table. In other words, to access arbitrary parts of the page directory after we enabled paging, we need to use following pointers:
In this way, we can map addresses as we like even with paging enabled.
Maps video memory in order to keep print working.
Definition at line 544 of file vmm.c.
|
static |
page_directory_t * vmm_load_page_directory | ( | page_directory_t * | new_directory | ) |
uint8_t vmm_map | ( | void * | _vaddr, |
void * | paddr, | ||
vmm_flags_t | flags | ||
) |
Maps the given page into memory.
_vaddr | a virtual address in the page to map from |
paddr | a physical address in the page to map to |
flags | the flags for mapping |
Finds the page directory entry associated with this page.
If the table doesn't exist yet, creates it.
If we already mapped this page, cancels and returns 0.
Otherwise, maps the page.
if we changed the current directory, flushes the TLB to apply changes.
Definition at line 253 of file vmm.c.
void * vmm_map_physical_memory | ( | void * | paddr, |
size_t | len, | ||
vmm_flags_t | flags | ||
) |
If necessary, maps the given page(s) somewhere into memory.
paddr | a physical address in the first page to map to |
len | the number of bytes to be mapped |
flags | the flags for mapping |
Definition at line 440 of file vmm.c.
void vmm_map_range | ( | void * | vaddr, |
void * | paddr, | ||
size_t | len, | ||
vmm_flags_t | flags | ||
) |
Maps the given page(s) into memory.
vaddr | a virtual address in the first page to map from |
paddr | a physical address in the first page to map to |
len | the number of bytes to be mapped |
flags | the flags for mapping |
Definition at line 341 of file vmm.c.
|
static |
Maps or unmaps the given page(s) into memory.
vaddr | a virtual address in the first page to map from |
paddr | a physical address in the first page to map to |
len | the number of bytes to be mapped |
flags | the flags for mapping |
map | whether to map (1) or unmap (0) memory |
Definition at line 314 of file vmm.c.
void vmm_modified_page_directory | ( | ) |
Ends a page directory modification.
The previous page directory is loaded and interrupts are re-enabled (if they were enabled before).
Definition at line 164 of file vmm.c.
void vmm_modify_page_directory | ( | page_directory_t * | new_directory | ) |
Loads a page directory for temporary modification.
Disables interrupts until vmm_modified_page_directory() is called.
new_directory | the physical address of the page directory to be modified |
Definition at line 149 of file vmm.c.
|
static |
Refreshes the page directory entries that are shared across page directories.
All memory inside the kernel domain will be shared.
dir_phys | the physical address of the page directory to be refreshed |
Definition at line 112 of file vmm.c.
void vmm_unmap | ( | void * | _vaddr | ) |
Unmaps the given page from memory.
_vaddr | a virtual address in the page to be unmapped |
if the page table doesn't exist yet, does nothing.
If the page was not yet mapped, does nothing.
Removes the mapping.
Searches the page table for other present entries.
If there are none, the page table is freed.
Definition at line 286 of file vmm.c.
void vmm_unmap_physical_memory | ( | void * | vaddr, |
size_t | len | ||
) |
If necessary, unmaps the given page(s) from memory.
vaddr | a virtual address in the first page to be unmapped |
len | the number of bytes to be unmapped |
Definition at line 456 of file vmm.c.
void vmm_unmap_range | ( | void * | vaddr, |
size_t | len | ||
) |
Unmaps the given page(s) from memory.
vaddr | a virtual address in the first page to be unmapped |
len | the number of bytes to be unmapped |
Definition at line 352 of file vmm.c.
void vmm_use | ( | void * | vaddr, |
void * | paddr, | ||
size_t | len, | ||
vmm_flags_t | flags | ||
) |
Marks the given page(s) as used and maps them into memory.
vaddr | a virtual address in the first page to map from |
paddr | a physical address in the first page to map to |
len | the number of bytes to be mapped |
flags | the flags for mapping |
Definition at line 468 of file vmm.c.
void * vmm_use_physical_memory | ( | void * | paddr, |
size_t | len, | ||
vmm_flags_t | flags | ||
) |
Marks the given page(s) as used and maps them somewhere into memory.
paddr | a physical address in the first page to map to |
len | the number of bytes to be mapped |
flags | the flags for mapping |
Definition at line 481 of file vmm.c.
void * vmm_use_virtual_memory | ( | void * | vaddr, |
size_t | len, | ||
vmm_flags_t | flags | ||
) |
Marks some page(s) as used and maps them into memory.
vaddr | a virtual address in the first page to map from |
len | the number of bytes to be mapped |
flags | the flags for mapping |
Definition at line 496 of file vmm.c.
|
static |
|
static |
The memory 1GiB-4GiB is process-specific.
Process images are loaded to 1GiB. The last page table is excluded (it contains the page directory and tables).