33MALLOC_DEFINE(M_PMAP,
"pmap",
"physical memory map structure");
39#define D_VALID (1ULL << 0)
40#define D_TABLE (1ULL << 1)
41#define D_ATTR(i) ((uint64_t) (i) << 2)
42#define D_AP_EL0 (1ULL << 6)
43#define D_AP_RO (1ULL << 7)
44#define D_SH_INNER (3ULL << 8)
45#define D_AF (1ULL << 10)
46#define D_NG (1ULL << 11)
47#define D_PXN (1ULL << 53)
48#define D_UXN (1ULL << 54)
50#define D_ADDR(e) ((e) & 0x0000FFFFFFFFF000ULL)
55#define IDX(va, level) (((va) >> (12 + 9 * (level))) & 0x1FF)
57#define KERNEL_HALF(va) ((va) >= ARCH_DMAP_BASE)
69#define cur_pmap (curcpu()->arch.pmap)
104 for (
int level = 3; level > 0; --level) {
123 return &t[
IDX(va, 0)];
141 asm volatile(
"dsb ishst" :::
"memory");
144 asm volatile(
"tlbi vmalle1" :::
"memory");
147 asm volatile(
"tlbi vaae1, %0" ::
"r"((va >> 12) & 0xFFFFFFFFFFFULL) :
"memory");
150 asm volatile(
"dsb ish; isb" :::
"memory");
197 extern char boot_l0_hi[], boot_l1[];
205 paddr_t end = (
ram_end() + (1ULL << 30) - 1) & ~((1ULL << 30) - 1);
215 panic(
"no memory for the kernel's page tables");
293 if (user || !(flags &
VM_KX))
295 if (!(flags &
VM_UX))
329 asm volatile(
"dsb ishst; isb" :::
"memory");
342 vaddr_t first = eva, last = sva;
349 first =
MIN(first, va);
365 for (
int i = 0; i < 512; ++i) {
386 for (
int i = 0; i < 512; ++i) {
404 vaddr_t first = eva, last = sva;
411 first =
MIN(first, va);
470 size_t len =
PAGE_ROUND(paddr + size) - start;
478 for (
size_t off = 0; off < len; off +=
PAGE_SIZE) {
487 return (
void *) (vaddr + (paddr - start));
499 if (paddr >= (1ULL << 30) && paddr + size <=
dmap_end)
#define write_sysreg(r, v)
static void tlb_flush(void)
Flushes every translation from this CPU's TLB.
void pmap_loaded(struct pmap *from, struct pmap *to)
void tlb_shootdown(struct pmap *pmap, vaddr_t sva, vaddr_t eva, int leave)
void mm_page_decref(paddr_t paddr)
Drops a reference to a page of RAM.
struct vm_page * mm_page_alloc(void)
Allocates a free page of physical memory.
void mm_page_dealloc(paddr_t paddr)
Frees a page of physical memory, back to the zone it came from.
#define MALLOC_DEFINE(type, _name, _desc)
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
void kfree(void *)
Frees an object that kmalloc() gave.
void * memset(void *dst, int c, size_t n)
Sets n bytes to c.
void * memcpy(void *dst, const void *src, size_t n)
Copies n bytes; dst and src must not overlap.
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.
static void table_free(paddr_t paddr)
Frees a page table.
paddr_t arch_page_get_mapping(struct pmap *pmap, vaddr_t vaddr)
Finds the page mapped at a virtual address of an address space.
void pmap_page_copy(paddr_t src, paddr_t dst)
Copies a page of physical memory to another.
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.
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.
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 h...
static uint64_t * table(paddr_t paddr)
Returns a page table, through the direct map.
static void pmap_release(struct pmap *pmap)
Frees a pmap whose last reference went.
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,...
void pmap_decref(struct pmap *pmap)
Drops a reference to an address space's page tables, freeing them with the last one.
static paddr_t ram_end(void)
Returns the end of the RAM that the boot loader found.
void arch_mm_setup(void)
Finishes setting up memory at boot, once mm_setup() has set up the page structures and the buddy allo...
static struct pmap k_pmap
struct pmap * pmap_switch(struct pmap *pmap)
Switches this CPU to an address space's page tables.
static uint64_t pte_flags(uint32_t flags)
Returns the descriptor bits for a page with the VM_* flags flags.
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.
void pmap_incref(struct pmap *pmap)
Adds a reference to an address space's page tables.
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.
static void tables_free(paddr_t paddr, int level)
Frees a table of the user half at level and the tables under it.
static void * window_map(uintptr_t paddr, size_t size, uint32_t flags)
Maps physical memory in the window, with flags.
struct pmap * pmap_create(void)
Makes the page tables of a new address space: an empty user half, and the kernel's half,...
static uint64_t * pte_get(struct pmap *pmap, vaddr_t va, int make)
Returns the page table entry that maps va, in pmap or in the kernel's half.
void pmap_remove_all(struct pmap *pmap)
Unmaps the whole user half of an address space, and frees its page tables.
static paddr_t table_alloc(void)
Allocates an empty page table.
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).
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
unsigned long long int uint64_t
An address space's page tables, on x86.
A page of physical memory (pages[] has one for every page of RAM).
paddr_t paddr
its physical address
struct pmap * pmap
its page tables (the architecture's)
#define VM_URWX
user read/write/execute
#define VM_KW
kernel write
#define VM_NOCACHE
not cached (device memory)
struct vm_space kvm_space
#define VM_UX
user execute
#define VM_KRW
kernel read/write
#define VM_KX
kernel execute