Use uintptr_t, not intptr_t, for memory addresses!
[marionette.git] / kernel / mm / paging.h
blobfa32ddad33bfddc3438715a9fe1f37535b176fe3
1 /*
2 * Copyright (c) 2008 Joshua Phillips. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
15 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * This deals with paging (mapping virtual addresses to physical memory)
32 #ifndef MM_PAGING
33 #define MM_PAGING
35 #include "stddef.h"
36 #include "stdint.h"
38 // Types for page directory entries and
39 // page table entries (they're almost the same format,
40 // but it's clearer if we use two different identifiers)
41 typedef uint32_t pte_t, pde_t;
43 // page table/directory format
44 // as defined in the documentation for the CPU
45 #define PTE_PRESENT (1 << 0) // page is valid
46 #define PTE_WRITABLE (1 << 1) // write access bit
47 #define PTE_USER (1 << 2) // user (ring1 - ring3) accessible
48 #define PTE_WRITE_THROUGH (1 << 3)
49 #define PTE_CACHE_DISABLED (1 << 4)
50 #define PTE_ACCESSED (1 << 5) // set by CPU when page is accessed
51 #define PTE_DIRTY (1 << 6) // set by CPU when page is written to
52 #define PTE_PAT (1 << 7)
53 #define PTE_GLOBAL (1 << 8)
54 #define PTE_ADDRESS 0xFFFFF000
56 #define PDE_PRESENT (1 << 0)
57 #define PDE_WRITABLE (1 << 1)
58 #define PDE_USER (1 << 2)
59 #define PDE_WRITE_THROUGH (1 << 3)
60 #define PDE_CACHE_DISABLED (1 << 4)
61 #define PDE_ACCESSED (1 << 5)
62 #define PDE_PAGESIZE (1 << 7)
63 #define PDE_GLOBAL (1 << 8)
64 #define PDE_ADDRESS 0xFFFFF000
66 // XXX: these values are set here, but if the
67 // kernel base address changes, these will
68 // change too!
69 #define PDE_N 1024 // number of PDEs
70 #define PDE_N_KERNEL 256 // number of kernel PDEs
71 #define PDE_N_USER 768 // number of user PDEs
72 #define PDE_KERNEL_FIRST 768
74 // Store a data structure mirroring the page directory
75 // and page tables, but with virtual addresses.
76 struct vpde {
77 unsigned unused: 12; // this may be useful
78 unsigned vaddr : 20; // TODO: vaddr is in kernel address space - save 2 bits or more!
81 struct pagedir {
82 struct pagedir *prev, *next; // linked list (so we can update all page directories at once)
83 uintptr_t phys_addr; // physical address of page directory
84 pde_t *virt_addr; // kernel-virtual address of page directory
85 struct vpde vpd[768];
88 // functions to get/set cr2 and cr3
89 // cr2 contains the virtual address of the last page fault.
90 // cr3 contains the address of the page directory.
92 static inline uint32_t get_cr2(void)
94 uint32_t old_cr3;
95 asm volatile ("movl %%cr2,%%eax" : "=a" (old_cr3));
96 return old_cr3;
99 static inline uint32_t get_cr3(void)
101 uint32_t old_cr3;
102 asm volatile ("movl %%cr3,%%eax" : "=a" (old_cr3));
103 return old_cr3;
106 static inline void set_cr3(uint32_t new_cr3)
108 asm volatile ("movl %%eax,%%cr3" :: "a" (new_cr3));
111 // Create the initial page directory structure.
112 // (The actual page directory will already exist)
113 void create_init_pagedir(struct pagedir *init_pagedir);
115 // Create a page directory. The page directory entries for the kernel's
116 // address space are duplicated.
117 // Caller is expected to provide storage for the 'struct pagedir'.
118 // The address of the 'struct pagedir' must not change!
119 // Returns 0=ok, 1=error (out of memory)
120 int pagedir_create(struct pagedir *pagedir);
122 // Destroy a page directory
123 void pagedir_destroy(struct pagedir *pagedir);
125 // Return the physical address pointed to by 'virtual'
126 uintptr_t xlat_v2p(struct pagedir *pd, uintptr_t virtual);
128 // Alter the current memory map: map a physical region to the
129 // current virtual address space.
130 // Flags are PTE_* constants
131 // Return: 0=ok, 1=error
132 int map_mem(struct pagedir *pd, uintptr_t physical, uintptr_t virtual, size_t n_pages, int flags);
134 // Sets up an initial 'struct pagedir' to represent the initial page directory
135 // (that was created in start.asm)
136 void paging_init(void);
138 // Switch to a new page directory. Be careful. Paging is confusing.
139 void pagedir_switch(struct pagedir *new_pagedir);
141 #endif