A Total Overhaul on the Lunaix's Virtual Memory Model (#26)
[lunaix-os.git] / lunaix-os / includes / lunaix / mm / vmm.h
1 #ifndef __LUNAIX_VMM_H
2 #define __LUNAIX_VMM_H
3
4 #include <lunaix/mm/pagetable.h>
5 #include <lunaix/process.h>
6 #include <lunaix/types.h>
7 // Virtual memory manager
8
9 #define VMAP_NULL 0
10
11 /**
12  * @brief 映射模式:忽略已存在映射
13  *
14  */
15 #define VMAP_IGNORE 1
16
17 /**
18  * @brief 映射模式:不作实际映射。该功能用于预留出特定的地址空间
19  *
20  */
21 #define VMAP_NOMAP 2
22
23 /**
24  * @brief 映射页墙:将虚拟地址映射为页墙,忽略给定的物理地址和页属性
25  *
26  */
27 #define VMAP_GUARDPAGE 4
28
29 /**
30  * @brief 规定下一个可用页映射应当限定在指定的4MB地址空间内
31  *
32  */
33 #define VALLOC_PDE 1
34
35 /**
36  * @brief 初始化虚拟内存管理器
37  *
38  */
39 void
40 vmm_init();
41
42 /**
43  * @brief 在指定地址空间中,添加一个映射
44  *
45  * @param mnt 地址空间挂载点
46  * @param va 虚拟地址
47  * @param pa 物理地址
48  * @param attr 映射属性
49  * @return int
50  */
51 int
52 vmm_set_mapping(ptr_t mnt, ptr_t va, ptr_t pa, pte_attr_t prot);
53
54 static inline void 
55 vmm_set_ptes_contig(pte_t* ptep, pte_t pte, size_t lvl_size, size_t n)
56 {
57     do {
58         set_pte(ptep, pte);
59         pte_val(pte) += lvl_size;
60         ptep++;
61     } while (--n > 0);
62 }
63
64 static inline void 
65 vmm_set_ptes(pte_t* ptep, pte_t pte, size_t n)
66 {
67     do {
68         set_pte(ptep, pte);
69         ptep++;
70     } while (--n > 0);
71 }
72
73
74 static inline void 
75 vmm_unset_ptes(pte_t* ptep, size_t n)
76 {
77     do {
78         set_pte(ptep, null_pte);
79         ptep++;
80     } while (--n > 0);
81 }
82
83
84 /**
85  * @brief 删除一个映射
86  *
87  * @param mnt
88  * @param pid
89  * @param va
90  * @return int
91  */
92 ptr_t
93 vmm_del_mapping(ptr_t mnt, ptr_t va);
94
95 pte_t
96 vmm_tryptep(pte_t* ptep, size_t lvl_size);
97
98 /**
99  * @brief 在指定的虚拟地址空间里查找一个映射
100  *
101  * @param mnt 地址空间锚定点
102  * @param va 虚拟地址
103  * @param mapping 映射相关属性
104  * @return int
105  */
106 static inline bool
107 vmm_lookupat(ptr_t mnt, ptr_t va, pte_t* pte_out)
108 {
109     pte_t pte = vmm_tryptep(mkptep_va(mnt, va), LFT_SIZE);
110     *pte_out = pte;
111
112     return !pte_isnull(pte);
113 }
114
115
116 /**
117  * @brief (COW) 为虚拟页创建副本。
118  *
119  * @return void* 包含虚拟页副本的物理页地址。
120  *
121  */
122 ptr_t
123 vmm_dup_page(ptr_t pa);
124
125 /**
126  * @brief 挂载另一个虚拟地址空间至当前虚拟地址空间
127  *
128  * @param pde 页目录的物理地址
129  * @return ptr_t
130  */
131 ptr_t
132 vms_mount(ptr_t mnt, ptr_t pde);
133
134 /**
135  * @brief 卸载已挂载的虚拟地址空间
136  *
137  */
138 ptr_t
139 vms_unmount(ptr_t mnt);
140
141 static inline ptr_t 
142 mount_page(ptr_t mnt, ptr_t pa) {
143     assert(pa);
144     pte_t* ptep = mkptep_va(VMS_SELF, mnt);
145     set_pte(ptep, mkpte(pa, KERNEL_DATA));
146     cpu_flush_page(mnt);
147     return mnt;
148 }
149
150 static inline ptr_t 
151 unmount_page(ptr_t mnt) {
152     pte_t* ptep = mkptep_va(VMS_SELF, mnt);
153     set_pte(ptep, null_pte);
154     return mnt;
155 }
156
157 void*
158 vmm_ioremap(ptr_t paddr, size_t size);
159
160 void*
161 vmm_next_free(ptr_t start, int options);
162
163 /**
164  * @brief 将指定地址空间的虚拟地址转译为物理地址
165  *
166  * @param mnt 地址空间锚定点
167  * @param va 虚拟地址
168  * @return void*
169  */
170 ptr_t
171 vmm_v2pat(ptr_t mnt, ptr_t va);
172
173 /**
174  * @brief 将当前地址空间的虚拟地址转译为物理地址。
175  *
176  * @param va 虚拟地址
177  * @return void*
178  */
179 static inline ptr_t
180 vmm_v2p(ptr_t va)
181 {
182     return vmm_v2pat(VMS_SELF, va);
183 }
184
185 /**
186  * @brief Maps a number of contiguous ptes in kernel 
187  *        address space
188  * 
189  * @param pte the pte to be mapped
190  * @param lvl_size size of the page pointed by the given pte
191  * @param n number of ptes
192  * @return ptr_t 
193  */
194 ptr_t
195 vmap_ptes_at(pte_t pte, size_t lvl_size, int n);
196
197 /**
198  * @brief Maps a number of contiguous ptes in kernel 
199  *        address space (leaf page size)
200  * 
201  * @param pte the pte to be mapped
202  * @param n number of ptes
203  * @return ptr_t 
204  */
205 static inline ptr_t
206 vmap_leaf_ptes(pte_t pte, int n)
207 {
208     return vmap_ptes_at(pte, LFT_SIZE, n);
209 }
210
211 /**
212  * @brief Maps a contiguous range of physical address 
213  *        into kernel address space (leaf page size)
214  * 
215  * @param paddr start of the physical address range
216  * @param size size of the physical range
217  * @param prot default protection to be applied
218  * @return ptr_t 
219  */
220 static inline ptr_t
221 vmap(ptr_t paddr, size_t size, pte_attr_t prot)
222 {
223     pte_t _pte = mkpte(paddr, prot);
224     return vmap_ptes_at(_pte, LFT_SIZE, leaf_count(size));
225 }
226
227 #endif /* __LUNAIX_VMM_H */