UnnamedOS

Virtual Memory Manager. More...

+ Collaboration diagram for VMM:

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_tvmm_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_tvmm_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_tvmm_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_tvmm_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_tvmm_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_tvmm_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_tpage_directory = 0
 the current page directory
 
static page_directory_told_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
 

Detailed Description

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.

See also
http://wiki.osdev.org/Paging
http://www.lowlevel.eu/wiki/Paging
http://www.rohitab.com/discuss/topic/31139-tutorial-paging-memory-mapping-with-a-recursive-page-directory/

Macro Definition Documentation

#define VMM_PAGEDIR   ((page_directory_t*) 0xFFFFF000)

the active page directory's address

See also
vmm_init

Definition at line 14 of file vmm.h.

#define VMM_PAGETAB (   i)    ((page_table_t*) (0xFFC00000 + (i) * PAGE_SIZE))

the address of a page table from the active page directory

See also
vmm_init

Definition at line 16 of file vmm.h.

Enumeration Type Documentation

Whether we are working with kernel or user memory.

This controls permissions and in which domain memory is stored.

Definition at line 20 of file vmm.h.

Function Documentation

void * vmm_alloc ( size_t  len,
vmm_flags_t  flags 
)

Marks some page(s) as used and maps them somewhere into memory.

Parameters
lenthe number of bytes to be mapped
flagsthe flags for mapping
Returns
the virtual address of the newly mapped memory

Definition at line 511 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

page_directory_t * vmm_create_page_directory ( )

Creates an empty page directory.

It itself is mapped into the last page table.

Returns
the physical address of the new page directory

Maps the last entry to itself, see vmm_init() for a detailed explanation.

Definition at line 72 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void vmm_destroy_page_directory ( page_directory_t dir_phys)

Destroys a page directory.

Parameters
dir_physthe 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.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void vmm_destroy_page_table ( uint16_t  page_table)
static

Destroys a page table in the current page directory.

Parameters
page_tablethe 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.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static uint8_t vmm_domain_check ( void *  vaddr,
vmm_flags_t  flags 
)
static

Checks whether a virtual address might be accessed with the given flags.

Parameters
vaddrthe virtual address
flagsthe flags
Returns
whether the virtual address belongs to the domain contained in the flags

Definition at line 237 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void vmm_dump ( )

Dumps the current page directory.

The dump is logged.

Definition at line 378 of file vmm.c.

+ Here is the call graph for this function:

void vmm_enable_domain_check ( uint8_t  enable)

Enables or disables domain checking.

Parameters
enablewhether to enable or disable domain checking

Definition at line 539 of file vmm.c.

+ Here is the caller graph for this function:

static void* vmm_find_free ( size_t  len,
vmm_domain_t domain 
)
static

Finds unmapped pages.

Parameters
lenrequested number of consecutive free bytes
domainrequested domain
Returns
the virtual address of a suitable unmapped memory range

Definition at line 407 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void vmm_free ( void *  vaddr,
size_t  len 
)

Frees the given page(s) and unmaps them from memory.

See also
vmm_alloc
Parameters
vaddra virtual address in the first page to be unmapped
lenthe number of bytes to be unmapped

Definition at line 528 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static vmm_domain_t* vmm_get_domain ( vmm_flags_t  flags)
static

Extracts a domain from the given flags.

Parameters
flagsthe flags containing a domain
Returns
the domain contained in the flags, either the kernel or user domain

Definition at line 206 of file vmm.c.

+ Here is the caller graph for this function:

static vmm_domain_t* vmm_get_domain_from_address ( void *  vaddr)
static

Returns the domain a virtual address belongs to.

Parameters
vaddrthe virtual address
Returns
the domain the virtual address belongs to

Definition at line 226 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static page_table_entry_t* vmm_get_page_table ( page_directory_entry_t dir_entry,
vmm_virtual_address_t  vaddr 
)
static

Returns a virtual or physical address to a page table in memory.

Parameters
dir_entrythe page directory entry for the requested page table
vaddra virtual address belonging to the requested page table
Returns
a usable pointer (virtual or physical) to the page table

Definition at line 180 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static page_table_entry_t* vmm_get_page_table_entry ( page_directory_entry_t dir_entry,
vmm_virtual_address_t  vaddr 
)
static

Returns a virtual or physical address to a page table entry in memory.

Parameters
dir_entrythe page directory entry for the requested page table entry
vaddra virtual address belonging to the requested page table entry
Returns
a usable pointer (virtual or physical) to the page table entry

Definition at line 196 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void * vmm_get_physical_address ( void *  _vaddr)

Translates a virtual address into a physical address.

Parameters
_vaddrthe virtual address to translate
Returns
the physical address associated with the virtual address

Definition at line 362 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static pmm_flags_t vmm_get_pmm_flags ( vmm_flags_t  flags)
static

Translates VMM into PMM flags.

Parameters
flagsthe VMM flags
Returns
the PMM flags

Definition at line 429 of file vmm.c.

+ Here is the caller graph for this function:

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:

1 0xFFFFF000 = 0b 1111111111 1111111111 000000000000
2  dir_idx tab_idx page_offset

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:

1 0xFFC00000 = 0b 1111111111 0000000000 000000000000
2  dir_idx tab_idx page_offset

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:

  • 0xFFC00000 - the first page table (handles 0x00000000-0x003FFFFF)
  • 0xFFC01000 - the second page table (handles 0x00400000-0x007FFFFF)
  • ... (formula: 0xFFC00000 + tab_idx * PAGE_SIZE), see VMM_PAGETAB()
  • 0xFFFFE000 - the last "regular" page table (0xFF800000-0xFFBFFFFF)
  • 0xFFFFF000 - the page directory, see VMM_PAGEDIR()

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.

+ Here is the call graph for this function:

static uint8_t vmm_is_in_domain ( void *  vaddr,
vmm_domain_t domain 
)
static

Returns whether a virtual address belongs to a given domain.

Parameters
vaddrthe virtual address
domainthe domain
Returns
whether the virtual address belongs to the domain

Definition at line 216 of file vmm.c.

+ Here is the caller graph for this function:

page_directory_t * vmm_load_page_directory ( page_directory_t new_directory)

Loads a new page directory.

Parameters
new_directorythe physical address of the page directory to be loaded
Returns
the physical address of the previously loaded page directory

Definition at line 129 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

uint8_t vmm_map ( void *  _vaddr,
void *  paddr,
vmm_flags_t  flags 
)

Maps the given page into memory.

Parameters
_vaddra virtual address in the page to map from
paddra physical address in the page to map to
flagsthe flags for mapping
Returns
whether mapping was successful

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.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void * vmm_map_physical_memory ( void *  paddr,
size_t  len,
vmm_flags_t  flags 
)

If necessary, maps the given page(s) somewhere into memory.

Parameters
paddra physical address in the first page to map to
lenthe number of bytes to be mapped
flagsthe flags for mapping
Returns
the virtual address of the newly mapped memory

Definition at line 440 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void vmm_map_range ( void *  vaddr,
void *  paddr,
size_t  len,
vmm_flags_t  flags 
)

Maps the given page(s) into memory.

Parameters
vaddra virtual address in the first page to map from
paddra physical address in the first page to map to
lenthe number of bytes to be mapped
flagsthe flags for mapping

Definition at line 341 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void vmm_map_range_detailed ( void *  vaddr,
void *  paddr,
size_t  len,
vmm_flags_t  flags,
uint8_t  map 
)
static

Maps or unmaps the given page(s) into memory.

Parameters
vaddra virtual address in the first page to map from
paddra physical address in the first page to map to
lenthe number of bytes to be mapped
flagsthe flags for mapping
mapwhether to map (1) or unmap (0) memory

Definition at line 314 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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).

See also
vmm_modify_page_directory

Definition at line 164 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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.

Parameters
new_directorythe physical address of the page directory to be modified

Definition at line 149 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void vmm_refresh_page_directory ( page_directory_t dir_phys)
static

Refreshes the page directory entries that are shared across page directories.

All memory inside the kernel domain will be shared.

Parameters
dir_physthe physical address of the page directory to be refreshed

Definition at line 112 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void vmm_unmap ( void *  _vaddr)

Unmaps the given page from memory.

See also
vmm_map
Parameters
_vaddra 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.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void vmm_unmap_physical_memory ( void *  vaddr,
size_t  len 
)

If necessary, unmaps the given page(s) from memory.

See also
vmm_map_physical_memory
Parameters
vaddra virtual address in the first page to be unmapped
lenthe number of bytes to be unmapped

Definition at line 456 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void vmm_unmap_range ( void *  vaddr,
size_t  len 
)

Unmaps the given page(s) from memory.

See also
vmm_map_range
Parameters
vaddra virtual address in the first page to be unmapped
lenthe number of bytes to be unmapped

Definition at line 352 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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.

Parameters
vaddra virtual address in the first page to map from
paddra physical address in the first page to map to
lenthe number of bytes to be mapped
flagsthe flags for mapping

Definition at line 468 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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.

Parameters
paddra physical address in the first page to map to
lenthe number of bytes to be mapped
flagsthe flags for mapping
Returns
the virtual address of the newly mapped memory

Definition at line 481 of file vmm.c.

+ Here is the call graph for this function:

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.

Parameters
vaddra virtual address in the first page to map from
lenthe number of bytes to be mapped
flagsthe flags for mapping
Returns
the physical address of the newly mapped memory

Definition at line 496 of file vmm.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

vmm_domain_t kernel_domain
static
Initial value:
= {.start = (void*) 0x400000,
.end = (void*) 0x3FFFFFFF}

We use 0-1GiB as kernel memory.

This will be mapped into all processes. We exclude the first page table so we can use it freely for VM86.

Definition at line 49 of file vmm.c.

vmm_domain_t user_domain
static
Initial value:
= {.start = (void*) 0x40000000,
.end = (void*) 0xFFFFFFFF - ENTRIES * PAGE_SIZE}
#define PAGE_SIZE
The number of bytes per page directory "happens" to equal the size of a page.
Definition: vmm.c:23
#define ENTRIES
number of entries in page directories and tables
Definition: vmm.c:21

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).

Definition at line 53 of file vmm.c.