source: trunk/hal/x86_64/core/hal_gpt.c @ 112

Last change on this file since 112 was 112, checked in by max@…, 5 years ago

In fact, we need to enter all of the VA space, because we massively
make this assumption later. The thing is, also need to keep the
same offset for the PA and VA, so it needs to be rethought. Until
then, add a commented code.

File size: 7.6 KB
Line 
1/*
2 * hal_gpt.c - implementation of the Generic Page Table API for x86_64
3 *
4 * Copyright (c) 2017 Maxime Villard
5 *
6 * This file is part of ALMOS-MKH.
7 *
8 * ALMOS-MKH is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.0 of the License.
11 *
12 * ALMOS-MKH is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <hal_types.h>
23#include <hal_boot.h> /* XXX */
24#include <hal_gpt.h>
25#include <hal_special.h>
26#include <hal_internal.h>
27
28#include <printk.h>
29#include <bits.h>
30#include <string.h>
31#include <process.h>
32#include <kmem.h>
33#include <thread.h>
34#include <cluster.h>
35#include <ppm.h>
36#include <page.h>
37
38#define VA_SIGN_MASK            0xffff000000000000
39#define VA_SIGN_POS(va)         ((va) & ~VA_SIGN_MASK)
40
41#define pl1_i(VA)       (((VA_SIGN_POS(VA)) & L1_FRAME) >> L1_SHIFT)
42#define pl2_i(VA)       (((VA_SIGN_POS(VA)) & L2_FRAME) >> L2_SHIFT)
43#define pl3_i(VA)       (((VA_SIGN_POS(VA)) & L3_FRAME) >> L3_SHIFT)
44#define pl4_i(VA)       (((VA_SIGN_POS(VA)) & L4_FRAME) >> L4_SHIFT)
45
46extern vaddr_t __kernel_end;
47size_t kimg_size __in_kdata = 0;
48
49paddr_t pa_avail __in_kdata = 0;
50vaddr_t va_avail __in_kdata = 0;
51vaddr_t tmpva __in_kdata = (KERNBASE + NKL2_KIMG_ENTRIES * NBPD_L2);
52
53paddr_t hal_gpt_bootstrap_palloc(size_t npages)
54{
55        paddr_t pa = pa_avail;
56        pa_avail += npages * PAGE_SIZE;
57        return pa;
58}
59
60vaddr_t hal_gpt_bootstrap_valloc(size_t npages)
61{
62        vaddr_t va = va_avail;
63        va_avail += npages * PAGE_SIZE;
64        return va;
65}
66
67/*
68 * Reset the bootstrap VA we've used in cluster0 so far. After this
69 * function, cluster0's heap is empty.
70 */
71void hal_gpt_bootstrap_reset()
72{
73        size_t npages = (va_avail - (CLUSTER_MIN_VA(0) + KERNEL_VA_SIZE)) / PAGE_SIZE;
74        hal_gpt_leave_range(CLUSTER_MIN_VA(0) + KERNEL_VA_SIZE, npages);
75}
76
77void hal_gpt_enter(vaddr_t va, paddr_t pa, pt_entry_t flags)
78{
79        XASSERT(va % PAGE_SIZE == 0);
80        XASSERT(pa % PAGE_SIZE == 0);
81        XASSERT(va == tmpva || PTE_BASE[pl1_i(va)] == 0);
82        PTE_BASE[pl1_i(va)] = (pa & PG_FRAME) | flags;
83        invlpg(va);
84}
85
86void hal_gpt_enter_range(vaddr_t va, paddr_t pa, size_t n)
87{
88        pt_entry_t flags = PG_V | PG_KW | PG_NX;
89        size_t i;
90        for (i = 0; i < n; i++) {
91                hal_gpt_enter(va + i * PAGE_SIZE, pa + i * PAGE_SIZE, flags);
92        }
93}
94
95void hal_gpt_leave(vaddr_t va)
96{
97        XASSERT(va % PAGE_SIZE == 0);
98        XASSERT(PTE_BASE[pl1_i(va)] != 0);
99        PTE_BASE[pl1_i(va)] = 0;
100        invlpg(va);
101}
102
103void hal_gpt_leave_range(vaddr_t va, size_t n)
104{
105        size_t i;
106        for (i = 0; i < n; i++) {
107                hal_gpt_leave(va + i * PAGE_SIZE);
108        }
109}
110
111/*
112 * Create a page tree that can map va_start->va_end. The caller can then
113 * enter these addresses to physical locations.
114 *
115 * This functions is a bit complicated, and may need to be revisited.
116 */
117void hal_gpt_maptree_area(vaddr_t va_start, vaddr_t va_end)
118{
119        pt_entry_t flags = PG_V | PG_KW | PG_NX;
120        size_t L4start, L4end, nL4e;
121        size_t L3start, L3end, nL3e;
122        size_t L2start, L2end, nL2e;
123        paddr_t L3page, L2page, L1page;
124        paddr_t pa;
125        size_t i, npa;
126        pt_entry_t *pde;
127
128        /* Allocate L3 */
129        L4start = pl4_i(va_start);
130        L4end = pl4_i(va_end);
131        nL4e = (L4end - L4start + 1);
132        L3page = hal_gpt_bootstrap_palloc(nL4e);
133
134        /* Allocate L2 */
135        L3start = pl3_i(va_start);
136        L3end = pl3_i(va_end);
137        nL3e = (L3end - L3start + 1);
138        L2page = hal_gpt_bootstrap_palloc(nL3e);
139
140        /* Allocate L1 */
141        L2start = pl2_i(va_start);
142        L2end = pl2_i(va_end);
143        nL2e = (L2end - L2start + 1);
144        L1page = hal_gpt_bootstrap_palloc(nL2e);
145
146        /* Zero out L1 */
147        for (i = 0; i < nL2e; i++) {
148                pa = L1page + i * PAGE_SIZE;
149                hal_gpt_enter(tmpva, pa, flags);
150
151                memset((void *)tmpva, 0, PAGE_SIZE);
152        }
153
154        /* Zero out L2 */
155        for (i = 0; i < nL3e; i++) {
156                pa = L2page + i * PAGE_SIZE;
157                hal_gpt_enter(tmpva, pa, flags);
158
159                memset((void *)tmpva, 0, PAGE_SIZE);
160        }
161
162        /* Zero out L3 */
163        for (i = 0; i < nL4e; i++) {
164                pa = L3page + i * PAGE_SIZE;
165                hal_gpt_enter(tmpva, pa, flags);
166
167                memset((void *)tmpva, 0, PAGE_SIZE);
168        }
169
170        /* Create L2, linked to L1 */
171        npa = (L2start / NPDPG) * PAGE_SIZE;
172        for (i = L2start; i <= L2end; i++) {
173                pa = (paddr_t)&(((pt_entry_t *)L2page)[i]);
174                pa -= npa;      /* shift on the left */
175                pa &= PG_FRAME; /* rounddown to a page boundary */
176                hal_gpt_enter(tmpva, pa, flags);
177
178                pde = (pt_entry_t *)tmpva;
179                pa = L1page + (i - L2start) * PAGE_SIZE;
180                pde[i % NPDPG] = (pa & PG_FRAME) | PG_V | PG_KW;
181        }
182
183        /* Create L3, linked to L2 */
184        npa = (L3start / NPDPG) * PAGE_SIZE;
185        for (i = L3start; i <= L3end; i++) {
186                pa = (paddr_t)&(((pt_entry_t *)L3page)[i]);
187                pa -= npa;      /* shift on the left */
188                pa &= PG_FRAME; /* rounddown to a page boundary */
189                hal_gpt_enter(tmpva, pa, flags);
190
191                pde = (pt_entry_t *)tmpva;
192                pa = L2page + (i - L3start) * PAGE_SIZE;
193                pde[i % NPDPG] = (pa & PG_FRAME) | PG_V | PG_KW;
194        }
195
196        /* Link L3 into L4 */
197        for (i = 0; i < nL4e; i++) {
198                pa = L3page + i * PAGE_SIZE;
199                L4_BASE[L4start + i] = (pa & PG_FRAME) | PG_V | PG_KW;
200        }
201}
202
203void hal_gpt_init(paddr_t firstpa)
204{
205        paddr_t kimg_min_pa, kimg_max_pa;
206
207        /* Initialize global values */
208        pa_avail = firstpa;
209        va_avail = CLUSTER_MIN_VA(0) + KERNEL_VA_SIZE;
210        kimg_size = ((uint64_t)&__kernel_end - KERNBASE);
211        XASSERT(kimg_size % PAGE_SIZE == 0);
212
213        kimg_min_pa = 0;
214        kimg_max_pa = kimg_min_pa + kimg_size;
215
216        /* Create cluster0's heap entry. */
217        hal_gpt_maptree_area(CLUSTER_MIN_VA(0), CLUSTER_MAX_VA(0));
218
219        /* Manually enter cluster0's kimg */
220        hal_gpt_enter_range(CLUSTER_MIN_VA(0), kimg_min_pa, kimg_size / PAGE_SIZE);
221
222        /* Manually enter cluster0's heap */
223/*
224        hal_gpt_enter_range(CLUSTER_MIN_VA(0) + kimg_size, kimg_max_pa,
225            (CLUSTER_VA_SIZE - kimg_size) / PAGE_SIZE);
226*/
227}
228
229/* -------------------------------------------------------------------------- */
230
231/****************************************************************************************
232 * These global variables defines the masks for the Generic Page Table Entry attributes,
233 * and must be defined in all GPT implementation.
234 ***************************************************************************************/
235
236uint32_t  GPT_MAPPED;
237uint32_t  GPT_SMALL;
238uint32_t  GPT_READABLE;
239uint32_t  GPT_WRITABLE; 
240uint32_t  GPT_EXECUTABLE;
241uint32_t  GPT_CACHABLE; 
242uint32_t  GPT_USER; 
243uint32_t  GPT_DIRTY;
244uint32_t  GPT_ACCESSED;
245uint32_t  GPT_GLOBAL;
246uint32_t  GPT_COW;
247uint32_t  GPT_SWAP;
248uint32_t  GPT_LOCKED;
249
250error_t hal_gpt_create( gpt_t * gpt )
251{
252        x86_panic((char *)__func__);
253        return 0;
254}
255
256void hal_gpt_destroy( gpt_t * gpt )
257{
258        x86_panic((char *)__func__);
259}
260
261void hal_gpt_print( gpt_t * gpt )
262{
263        x86_panic((char *)__func__);
264}
265
266error_t hal_gpt_set_pte( gpt_t   * gpt,
267                         vpn_t     vpn,
268                         ppn_t     ppn,
269                         uint32_t  attr )
270{
271        x86_panic((char *)__func__);
272        return 0;
273}
274
275void hal_gpt_get_pte( gpt_t    * gpt,
276                      vpn_t      vpn,
277                      uint32_t * attr,
278                      ppn_t    * ppn )
279{
280        x86_panic((char *)__func__);
281}
282
283void hal_gpt_reset_pte( gpt_t * gpt,
284                        vpn_t   vpn )
285{
286        x86_panic((char *)__func__);
287}
288
289error_t hal_gpt_lock_pte( gpt_t * gpt,
290                          vpn_t   vpn )
291{
292        x86_panic((char *)__func__);
293        return 0;
294}
295
296error_t hal_gpt_unlock_pte( gpt_t * gpt,
297                            vpn_t   vpn )
298{
299        x86_panic((char *)__func__);
300        return 0;
301}
302
303error_t hal_gpt_copy( gpt_t  * dst_gpt,
304                      gpt_t  * src_gpt,
305                      bool_t   cow )
306{
307        x86_panic((char *)__func__);
308    return 0;
309}
310
Note: See TracBrowser for help on using the repository browser.