vmap: Use an arena allocator for kernel vmaps
[akaros.git] / kern / arch / riscv / ros / mmu.h
1 /* Contains macros and constants for the kernel VM mapping, page tables,
2  * definitions for the RISC-V MMU, etc. */
3
4 #pragma once
5
6 /* **************************************** */
7 /* Kernel Virtual Memory Mapping  (not really an MMU thing) */
8
9 // All physical memory mapped at this address
10 #ifdef __riscv64
11 # define KERNBASE       0xFFFFFC0000000000
12 # define ULIM           0x0000040000000000
13 # define KERN_LOAD_ADDR 0xFFFFFFFF80000000
14 # define KERN_VMAP_TOP          KERN_LOAD_ADDR // upper 2GB reserved (see mmu_init)
15 # define NPTLEVELS                       3
16 # define L1PGSHIFT              (13+10+10)
17 # define L1PGSIZE        (1L << L1PGSHIFT)
18 # define L2PGSHIFT                 (13+10)
19 # define L2PGSIZE        (1L << L2PGSHIFT)
20 # define L3PGSHIFT                    (13)
21 # define L3PGSIZE        (1L << L3PGSHIFT)
22 # define PGSHIFT                 L3PGSHIFT
23 # define PTSIZE                   L2PGSIZE
24 #else
25 # define KERNBASE               0x80000000
26 # define ULIM                   0x7F000000
27 # define KERN_LOAD_ADDR           KERNBASE
28 # define KERN_VMAP_TOP                  0xfec00000
29 # define NPTLEVELS                       2
30 # define L1PGSHIFT                 (13+11)
31 # define L1PGSIZE         (1 << L1PGSHIFT)
32 # define L2PGSHIFT                      13
33 # define L2PGSIZE         (1 << L2PGSHIFT)
34 # define PGSHIFT                 L2PGSHIFT
35 # define PTSIZE                   L1PGSIZE
36 #endif
37
38 /* This is the range of the dynamic virtual mappings. */
39 #define KERN_DYN_TOP    KERNBASE
40 #warning "pick a better DYN_BOT"
41 #define KERN_DYN_BOT    ULIM
42
43 /* **************************************** */
44 /* Page table constants, macros, etc */
45
46 #define PGSIZE (1 << PGSHIFT)
47
48 // RV64 virtual addresses are 48 bits, sign-extended out to 64 bits,
49 // creating a hole between 0x0000 7FFF FFFF FFFF and 0xFFFF 8000 0000 0000.
50 // Bits 11-0 are the page offset; L1/L2/L3/L4 page table indices are given
51 // by bits 47-39, 38-30, 29-21, and 20-12, respectively.
52 //
53 // In RV32, virtual addresses are 32 bits; bits 11-0 are the page offset;
54 // and L1/L2 page table indices are given by bits 31-22 and 21-12,
55 // respectively.
56 //
57 // In both cases, the last-level page size is 4KB, as is the page table size.
58
59 // page number field of address
60 #define LA2PPN(la)      (((uintptr_t) (la)) >> PGSHIFT)
61
62 // page number field of PPN
63 #define PTE2PPN(pte)    (((uintptr_t) (pte)) >> PTE_PPN_SHIFT)
64
65 // index into L1 PT
66 #define L1X(la)         ((((uintptr_t) (la)) >> L1PGSHIFT) & (NPTENTRIES-1))
67
68 // index into L2 PT
69 #define L2X(la)         ((((uintptr_t) (la)) >> L2PGSHIFT) & (NPTENTRIES-1))
70
71 #ifdef __riscv64
72 // index into L3 PT
73 #define L3X(la)         ((((uintptr_t) (la)) >> L3PGSHIFT) & (NPTENTRIES-1))
74
75 // index into L4 PT
76 #define L4X(la)         ((((uintptr_t) (la)) >> L4PGSHIFT) & (NPTENTRIES-1))
77
78 #endif
79
80 // offset in page
81 #define PGOFF(la)       (((uintptr_t) (la)) & (PGSIZE-1))
82
83 // construct PTD from physical address
84 #define PTD(pa) (((uintptr_t)(pa) >> PGSHIFT << PTE_PPN_SHIFT) | PTE_T)
85
86 // Page directory and page table constants
87 #define NPTENTRIES (PGSIZE/sizeof(pte_t))
88
89 // Page table/directory entry flags.
90 #define PTE_T    0x001 // Entry is a page Table descriptor
91 #define PTE_E    0x002 // Entry is a page table Entry
92 #define PTE_R    0x004 // Referenced
93 #define PTE_D    0x008 // Dirty
94 #define PTE_UX   0x010 // User eXecute permission
95 #define PTE_UW   0x020 // User Read permission
96 #define PTE_UR   0x040 // User Write permission
97 #define PTE_SX   0x080 // Supervisor eXecute permission
98 #define PTE_SW   0x100 // Supervisor Read permission
99 #define PTE_SR   0x200 // Supervisor Write permission
100 #define PTE_PERM (PTE_SR | PTE_SW | PTE_SX | PTE_UR | PTE_UW | PTE_UX)
101 #define PTE_PPN_SHIFT 13
102 #warning "Review RISCV PTE_modes, like NOCACHE/WRITECOMB"
103 #define PTE_NOCACHE     0 // PTE bits to turn off caching, if possible
104 #define PTE_WRITECOMB   0 // PTE bits to turn on write-combining, if possible
105
106 // commly used access modes
107
108 #warning "Review RISCV PTEs.  Maybe want PTE_E/PTE_R?"
109         /* arch-indep code doesn't set PTE_P, it just sets a perm */
110
111
112 #define PTE_KERN_RW     (PTE_SR | PTE_SW | PTE_SX)
113 #define PTE_KERN_RO     (PTE_SR | PTE_SX)
114 #define PTE_USER_RW     (PTE_SR | PTE_SW | PTE_UR | PTE_UW | PTE_UX)
115 #define PTE_USER_RO     (PTE_SR | PTE_UR | PTE_UX)
116 #define PTE_NONE        0
117
118 #warning "probably remove this"
119 // x86 equivalencies
120 #define PTE_P      PTE_E
121
122 // address in page table entry
123 #define PTE_ADDR(pte)   ((physaddr_t) (pte) & ~(PGSIZE-1))
124
125 // address in page table descriptor
126 #define PTD_ADDR(ptd)   PTE_ADDR(ptd)
127
128 // MMU Control Register flags
129 #define MMU_CR_E        0x00000001      // Protection Enable
130 #define MMU_CR_NF       0x00000002      // No Fault mode
131 #define MMU_CR_PSO      0x00000080      // Partial Store Order (TSO disabled)
132
133 // MMU Fault Status Register flags
134 #define MMU_FSR_USER    0x00000020      // Fault caused by user-space access
135 #define MMU_FSR_EX      0x00000040      // Fault occured in instruction-space
136 #define MMU_FSR_WR      0x00000080      // Fault caused by a store
137
138 // MMU Register Addresses
139 #define MMU_REG_CTRL    0x00000000      // MMU Control Register
140 #define MMU_REG_CTXTBL  0x00000100      // MMU Context Table Pointer Register
141 #define MMU_REG_CTX     0x00000200      // MMU Context Register
142 #define MMU_REG_FSR     0x00000300      // MMU Fault Status Register
143 #define MMU_REG_FAR     0x00000400      // MMU Fault Address Register
144
145 // we must guarantee that for any PTE, exactly one of the following is true
146 #define PAGE_PRESENT(pte) ((pte) & PTE_P)
147 #define PAGE_UNMAPPED(pte) ((pte) == 0)
148 #define PAGE_PAGED_OUT(pte) (!PAGE_PRESENT(pte) && !PAGE_UNMAPPED(pte))
149 #define NOVPT
150
151 #ifndef __ASSEMBLER__
152 typedef unsigned long pte_t;
153 typedef unsigned long pgdir_t;
154 #endif
155
156 /* Same as VPT but read-only for users */
157 #define UVPT            (ULIM - PTSIZE)
158
159 /* Arbitrary boundary between the break and the start of
160  * memory returned by calls to mmap with addr = 0 */
161 #define BRK_END 0x40000000
162 #warning "Check these addresses.  Seem to be small.  Are they 32 bit?"
163 /* Arbitrary boundary where the break (glibc's heap) starts.  You can safely
164  * mmap with MAP_FIXED below this address. */
165 #define BRK_START               0x0000100000000000