|
AquilaOS documentation
How it works, and its code
|
i386: page tables, with 32-bit paging (two levels, 4 KiB pages). More...
#include <core/arch.h>#include <core/panic.h>#include <core/printk.h>#include <core/string.h>#include <core/system.h>#include <cpu/cpu.h>#include <sys/cpu.h>#include <mm/pmap.h>#include <mm/buddy.h>#include <mm/mm.h>#include <mm/vm.h>Go to the source code of this file.
Macros | |
| #define | PG_PRESENT 0x001 |
| #define | PG_WRITE 0x002 |
| #define | PG_USER 0x004 |
| #define | PG_PWT 0x008 |
| #define | PG_PCD 0x010 |
| #define | PG_ADDR(e) |
| #define | VDIR(va) |
| #define | VTBL(va) |
| #define | KERNEL_PDE 768 |
| #define | cur_pmap (curcpu()->arch.pmap) |
Functions | |
| static uint32_t * | table (paddr_t paddr) |
| Returns a page table's kernel address, in the direct map. | |
| static paddr_t | table_alloc (void) |
| Allocates an empty page table. | |
| static paddr_t | table_alloc_boot (void) |
| Allocates a page table that the kernel can't boot without: it panics if there is no memory. | |
| static void | table_free (paddr_t paddr) |
| Frees a page table. | |
| static uint32_t * | pte_get (struct pmap *pmap, vaddr_t va, int make) |
| Returns the page table entry that maps va in pmap. | |
| struct pmap * | pmap_switch (struct pmap *pmap) |
| Switches this CPU to an address space's page tables. | |
| void | pmap_init (void) |
| Takes over the boot page tables as the kernel's, at boot, and makes the page tables of the kernel's half, which every address space shares. | |
| static struct pmap * | pmap_alloc (void) |
| Allocates a struct pmap. | |
| static void | pmap_release (struct pmap *pmap) |
| Frees an address space's page directory, once no CPU has it loaded. | |
| struct pmap * | pmap_create (void) |
| Makes the page tables of a new address space: an empty user half, and the kernel's half, which every address space shares. | |
| void | pmap_incref (struct pmap *pmap) |
| Adds a reference to an address space's page tables. | |
| void | pmap_decref (struct pmap *pmap) |
| Drops a reference to an address space's page tables, freeing them with the last one. | |
| static uint32_t | pte_flags (uint32_t flags) |
| Returns the page table entry bits for the VM_* flags flags. | |
| int | pmap_add (struct pmap *pmap, vaddr_t va, paddr_t pa, uint32_t flags) |
| Maps a page in an address space, replacing what was mapped there. | |
| void | pmap_remove (struct pmap *pmap, vaddr_t sva, vaddr_t eva) |
| Unmaps the pages of a range of an address space, and flushes them from the TLBs that may have them. | |
| void | pmap_remove_all (struct pmap *pmap) |
| Unmaps the whole user half of an address space, and frees its page tables. | |
| void | pmap_protect (struct pmap *pmap, vaddr_t sva, vaddr_t eva, uint32_t prot) |
| Changes the permissions of the mapped pages of a range of an address space. | |
| void | pmap_copy (struct pmap *dst_map, struct pmap *src_map, vaddr_t dst_addr, size_t len, vaddr_t src_addr) |
| Does nothing: the generic pmap_copy() isn't used on x86. | |
| void | pmap_update (struct pmap *pmap) |
| Makes the changes to an address space's page tables take effect. | |
| void | pmap_page_copy (paddr_t src, paddr_t dst) |
| Copies a page of physical memory to another. | |
| void | pmap_page_protect (struct vm_page *pg, uint32_t flags) |
| Not implemented on x86 (it does nothing), and nothing uses it. | |
| int | pmap_clear_modify (struct vm_page *pg) |
| Not implemented on x86, and nothing uses it. | |
| int | pmap_clear_reference (struct vm_page *pg) |
| Not implemented on x86, and nothing uses it. | |
| int | pmap_is_modified (struct vm_page *pg) |
| Not implemented on x86, and nothing uses it. | |
| int | pmap_is_referenced (struct vm_page *pg) |
| Not implemented on x86, and nothing uses it. | |
| paddr_t | arch_page_get_mapping (struct pmap *pmap, vaddr_t vaddr) |
| Finds the page mapped at a virtual address of an address space. | |
| int | arch_page_unmap (vaddr_t vaddr) |
| Unmaps a page of the running CPU's address space. | |
| int | arch_mm_page_fault (vaddr_t vaddr, int err) |
| Handles a page fault: turns the CPU's error code into the kernel's PF_* flags, and calls mm_page_fault() (mm/i386.c, mm/x86_64.c). | |
| int | pmap_page_read (paddr_t paddr, off_t off, size_t size, void *buf) |
| Reads from a page of physical memory, through the kernel's mapping. | |
| int | pmap_page_write (paddr_t paddr, off_t off, size_t size, void *buf) |
| Writes to a page of physical memory, through the kernel's mapping. | |
| static void * | phys_window_map (uintptr_t paddr, size_t size, uint32_t flags) |
| Maps a range of physical memory in the window, with flags. | |
| void * | arch_phys_map (uintptr_t paddr, size_t size) |
| Returns a kernel address for a range of physical memory: its address in the direct map if it's there, or a mapping made in a window. | |
| void * | arch_mmio_map (uintptr_t paddr, size_t size) |
| Maps a device's registers into the kernel's address space, uncached (memory-mapped I/O). | |
Variables | |
| static struct pmap | k_pmap |
| static vaddr_t | phys_window_next = ARCH_PHYS_WINDOW_BASE |
i386: page tables, with 32-bit paging (two levels, 4 KiB pages).
RAM is mapped from 0xC0000000 (ARCH_DMAP_BASE, the direct map, 768 MiB at most), and page tables and pages are reached there. Every address space has its own page directory. The page tables of the kernel's half (from KERNEL_PDE) are all made at boot and shared by every directory, so the kernel's mappings are the same in every address space, and a directory's kernel entries never change. Switching address spaces is loading CR3.
References: [1] - Intel(R) 64 and IA-32 Architectures Software Developer's Manual, Volume 3 (System Programming Guide), Chapter 4 (Paging)
Definition in file i386.c.
| #define KERNEL_PDE 768 |
Definition at line 45 of file i386.c.
Referenced by pmap_create(), pmap_init(), pmap_remove_all(), and pte_get().
| #define PG_ADDR | ( | e | ) |
Definition at line 39 of file i386.c.
Referenced by arch_page_get_mapping(), pmap_init(), pmap_protect(), pmap_remove_all(), pte_get(), pte_get(), and tables_free().
| #define PG_PCD 0x010 |
Definition at line 37 of file i386.c.
Referenced by pte_flags(), and pte_flags().
| #define PG_PWT 0x008 |
Definition at line 36 of file i386.c.
Referenced by pte_flags(), and pte_flags().
| #define PG_USER 0x004 |
Definition at line 35 of file i386.c.
Referenced by pte_flags(), pte_flags(), pte_get(), and pte_get().
| #define VDIR | ( | va | ) |
| #define VTBL | ( | va | ) |
| int arch_mm_page_fault | ( | vaddr_t | vaddr, |
| int | err ) |
Handles a page fault: turns the CPU's error code into the kernel's PF_* flags, and calls mm_page_fault() (mm/i386.c, mm/x86_64.c).
| vaddr | the address that faulted (CR2) |
| err | the CPU's error code |
Maps a device's registers into the kernel's address space, uncached (memory-mapped I/O).
| paddr | the registers' physical address |
| size | their size, in bytes |
Definition at line 529 of file i386.c.
References arch_mmio_map(), phys_window_map(), VM_KRW, and VM_NOCACHE.
Finds the page mapped at a virtual address of an address space.
| pmap | the address space's page tables |
| vaddr | the virtual address |
Definition at line 423 of file i386.c.
References arch_page_get_mapping(), PG_ADDR, PG_PRESENT, and pte_get().
| int arch_page_unmap | ( | vaddr_t | vaddr | ) |
Unmaps a page of the running CPU's address space.
| vaddr | the page's virtual address, page-aligned |
Definition at line 436 of file i386.c.
References arch_page_unmap(), cur_pmap, PAGE_MASK, PAGE_SIZE, and pmap_remove().
Referenced by arch_page_unmap().
Returns a kernel address for a range of physical memory: its address in the direct map if it's there, or a mapping made in a window.
| paddr | the range's physical address |
| size | its size, in bytes |
Definition at line 518 of file i386.c.
References arch_phys_map(), PHYS2VIRT, phys_window_map(), and VM_KRW.
Maps a range of physical memory in the window, with flags.
Returns its kernel address, or NULL if there's no room left in the window, or no memory for a page table. The window's addresses are never reused.
Definition at line 491 of file i386.c.
References k_pmap, NULL, PAGE_ALIGN, PAGE_ROUND, PAGE_SIZE, phys_window_map(), phys_window_next, pmap_add(), and pmap_remove().
Referenced by arch_mmio_map(), arch_phys_map(), and phys_window_map().
Maps a page in an address space, replacing what was mapped there.
| pmap | the page tables (an address in the kernel's half is mapped in every address space) |
| va | the virtual address, page-aligned |
| pa | the page's physical address, page-aligned |
| flags | the mapping's permissions and caching (VM_*) |
Definition at line 242 of file i386.c.
References PAGE_MASK, PAGE_SIZE, PG_PRESENT, pmap_add(), pte_flags(), pte_get(), and tlb_shootdown().
|
static |
Allocates a struct pmap.
Definition at line 157 of file i386.c.
References kmalloc(), and pmap_alloc().
Referenced by pmap_alloc(), pmap_alloc(), and pmap_create().
| int pmap_clear_modify | ( | struct vm_page * | pg | ) |
Not implemented on x86, and nothing uses it.
| pg | the page |
Definition at line 382 of file i386.c.
References pmap_clear_modify().
Referenced by pmap_clear_modify().
| int pmap_clear_reference | ( | struct vm_page * | pg | ) |
Not implemented on x86, and nothing uses it.
| pg | the page |
Definition at line 393 of file i386.c.
References pmap_clear_reference().
Referenced by pmap_clear_reference().
| void pmap_copy | ( | struct pmap * | dst_map, |
| struct pmap * | src_map, | ||
| vaddr_t | dst_addr, | ||
| size_t | len, | ||
| vaddr_t | src_addr ) |
Does nothing: the generic pmap_copy() isn't used on x86.
Definition at line 340 of file i386.c.
References pmap_copy().
Referenced by pmap_copy().
| struct pmap * pmap_create | ( | void | ) |
Makes the page tables of a new address space: an empty user half, and the kernel's half, which every address space shares.
Definition at line 178 of file i386.c.
References k_pmap, KERNEL_PDE, kfree(), pmap::map, memset(), NULL, pmap_alloc(), pmap_create(), pmap::ref, table(), and table_alloc().
| void pmap_decref | ( | struct pmap * | pmap | ) |
Drops a reference to an address space's page tables, freeing them with the last one.
| pmap | the page tables |
Definition at line 215 of file i386.c.
References pmap_decref(), pmap_release(), and pmap::ref.
| void pmap_incref | ( | struct pmap * | pmap | ) |
Adds a reference to an address space's page tables.
| pmap | the page tables |
Definition at line 206 of file i386.c.
References pmap_incref(), and pmap::ref.
| void pmap_init | ( | void | ) |
Takes over the boot page tables as the kernel's, at boot, and makes the page tables of the kernel's half, which every address space shares.
Definition at line 132 of file i386.c.
References cur_pmap, k_pmap, KERNEL_PDE, kvm_space, pmap::map, NULL, PAGE_MASK, PG_PRESENT, PG_WRITE, vm_space::pmap, pmap_init(), pmap_loaded(), read_cr3(), pmap::ref, table(), table_alloc_boot(), and tlb_flush().
| int pmap_is_modified | ( | struct vm_page * | pg | ) |
Not implemented on x86, and nothing uses it.
| pg | the page |
Definition at line 404 of file i386.c.
References pmap_is_modified().
Referenced by pmap_is_modified().
| int pmap_is_referenced | ( | struct vm_page * | pg | ) |
Not implemented on x86, and nothing uses it.
| pg | the page |
Definition at line 415 of file i386.c.
References pmap_is_referenced().
Referenced by pmap_is_referenced().
Not implemented on x86 (it does nothing), and nothing uses it.
| pg | the page |
| flags | the permissions |
Definition at line 371 of file i386.c.
References pmap_page_protect().
Referenced by pmap_page_protect().
Reads from a page of physical memory, through the kernel's mapping.
| paddr | the page's physical address |
| off | the offset to read from, in the page |
| size | how much to read, at most what's left of the page |
| buf | where to put it |
Definition at line 464 of file i386.c.
References memcpy(), MIN, PAGE_SIZE, PHYS2VIRT, and pmap_page_read().
Writes to a page of physical memory, through the kernel's mapping.
| paddr | the page's physical address |
| off | the offset to write at, in the page |
| size | how much to write, at most what's left of the page |
| buf | what to write |
Definition at line 476 of file i386.c.
References memcpy(), MIN, PAGE_SIZE, PHYS2VIRT, and pmap_page_write().
Changes the permissions of the mapped pages of a range of an address space.
Pages that aren't mapped stay unmapped.
| pmap | the page tables |
| sva | the range's start, page-aligned |
| eva | its end |
| prot | the new permissions (VM_*) |
Definition at line 318 of file i386.c.
References MIN, PAGE_MASK, PAGE_SIZE, PG_ADDR, PG_PRESENT, pmap_protect(), pte_flags(), pte_get(), and tlb_shootdown().
|
static |
Frees an address space's page directory, once no CPU has it loaded.
Definition at line 163 of file i386.c.
References kfree(), pmap::map, pmap_release(), table_free(), and tlb_shootdown().
Unmaps the pages of a range of an address space, and flushes them from the TLBs that may have them.
The pages lose no references.
| pmap | the page tables |
| sva | the range's start, page-aligned |
| eva | its end, page-aligned |
Definition at line 267 of file i386.c.
References MIN, PAGE_MASK, PAGE_SIZE, PG_PRESENT, pmap_remove(), pte_get(), and tlb_shootdown().
| void pmap_remove_all | ( | struct pmap * | pmap | ) |
Unmaps the whole user half of an address space, and frees its page tables.
The pages it mapped lose the reference that the page fault handler gave them (mm_page_incref()).
| pmap | the page tables |
Definition at line 293 of file i386.c.
References KERNEL_PDE, pmap::map, mm_page_decref(), PG_ADDR, PG_PRESENT, pmap_remove_all(), table(), table_free(), tlb_shootdown(), and USER_STACK.
Switches this CPU to an address space's page tables.
| pmap | the page tables to switch to |
Definition at line 111 of file i386.c.
References cur_pmap, pmap::map, panic, pmap_loaded(), and pmap_switch().
| void pmap_update | ( | struct pmap * | pmap | ) |
Makes the changes to an address space's page tables take effect.
It does nothing on x86, where they take effect at once.
| pmap | the page tables |
Definition at line 352 of file i386.c.
References pmap_update().
Referenced by pmap_update().
Returns the page table entry bits for the VM_* flags flags.
Definition at line 222 of file i386.c.
References PG_PCD, PG_PRESENT, PG_PWT, PG_USER, PG_WRITE, pte_flags(), VM_KW, VM_NOCACHE, VM_URWX, and VM_UW.
Returns the page table entry that maps va in pmap.
With make, the page table is made if there's none (NULL if there's no memory for it); without it, NULL if there's no page table.
Definition at line 92 of file i386.c.
References KERNEL_PDE, pmap::map, NULL, PG_ADDR, PG_PRESENT, PG_USER, PG_WRITE, pte_get(), table(), table_alloc(), VDIR, and VTBL.
|
static |
Allocates an empty page table.
Returns its physical address, or 0 if there is no memory for it.
Definition at line 60 of file i386.c.
References memset(), mm_page_alloc(), vm_page::paddr, PAGE_SIZE, table(), and table_alloc().
|
static |
Allocates a page table that the kernel can't boot without: it panics if there is no memory.
Definition at line 73 of file i386.c.
References vm_page::paddr, panic, table_alloc(), and table_alloc_boot().
Referenced by pmap_init(), table_alloc_boot(), and table_alloc_boot().
|
static |
Frees a page table.
Definition at line 84 of file i386.c.
References mm_page_dealloc(), vm_page::paddr, and table_free().
|
static |
Definition at line 486 of file i386.c.
Referenced by phys_window_map().