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

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

less magic

File size: 8.0 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
38extern vaddr_t __kernel_end;
39size_t kimg_size __in_kdata = 0;
40
41paddr_t pa_avail __in_kdata = 0;
42vaddr_t va_avail __in_kdata = 0;
43vaddr_t tmpva __in_kdata = (KERNBASE + NKL2_KIMG_ENTRIES * NBPD_L2);
44
45paddr_t hal_gpt_bootstrap_palloc(size_t npages)
46{
47        paddr_t pa = pa_avail;
48        pa_avail += npages * PAGE_SIZE;
49        return pa;
50}
51
52vaddr_t hal_gpt_bootstrap_valloc(size_t npages)
53{
54        vaddr_t va = va_avail;
55        va_avail += npages * PAGE_SIZE;
56        return va;
57}
58
59/*
60 * Reset the bootstrap VA we've used in cluster0 so far. After this
61 * function, cluster0's heap is empty.
62 */
63void hal_gpt_bootstrap_reset()
64{
65        size_t npages = (va_avail - (CLUSTER_MIN_VA(0) + KERNEL_VA_SIZE)) / PAGE_SIZE;
66        hal_gpt_leave_range(CLUSTER_MIN_VA(0) + KERNEL_VA_SIZE, npages);
67        va_avail = CLUSTER_MIN_VA(0) + KERNEL_VA_SIZE;
68}
69
70/*
71 * Uniformize the PA and VA offsets, and return the value. After this function,
72 * we are guaranteed to have [VA = PA + constant_offset]. And therefore we can
73 * only call hal_gpt_bootstrap_valloc, without entering it in a PA.
74 */
75size_t hal_gpt_bootstrap_uniformize()
76{
77        size_t pa_offset = pa_avail - 0;
78        size_t va_offset = va_avail - CLUSTER_MIN_VA(0);
79
80        if (pa_offset < va_offset)
81                pa_avail += (va_offset - pa_offset);
82        else if (pa_offset > va_offset)
83                va_avail += (pa_offset - va_offset);
84
85        return MAX(pa_offset, va_offset);
86}
87
88void hal_gpt_enter(vaddr_t va, paddr_t pa, pt_entry_t flags)
89{
90        XASSERT(va % PAGE_SIZE == 0);
91        XASSERT(pa % PAGE_SIZE == 0);
92        //XASSERT(va == tmpva || PTE_BASE[pl1_i(va)] == 0);
93        PTE_BASE[pl1_i(va)] = (pa & PG_FRAME) | flags;
94        invlpg(va);
95}
96
97void hal_gpt_enter_range(vaddr_t va, paddr_t pa, size_t n)
98{
99        pt_entry_t flags = PG_V | PG_KW | PG_NX;
100        size_t i;
101        for (i = 0; i < n; i++) {
102                hal_gpt_enter(va + i * PAGE_SIZE, pa + i * PAGE_SIZE, flags);
103        }
104}
105
106void hal_gpt_leave(vaddr_t va)
107{
108        XASSERT(va % PAGE_SIZE == 0);
109        XASSERT(PTE_BASE[pl1_i(va)] != 0);
110        PTE_BASE[pl1_i(va)] = 0;
111        invlpg(va);
112}
113
114void hal_gpt_leave_range(vaddr_t va, size_t n)
115{
116        size_t i;
117        for (i = 0; i < n; i++) {
118                hal_gpt_leave(va + i * PAGE_SIZE);
119        }
120}
121
122/*
123 * Create a page tree that can map va_start->va_end. The caller can then
124 * enter these addresses to physical locations.
125 *
126 * This functions is a bit complicated, and may need to be revisited.
127 */
128void hal_gpt_maptree_area(vaddr_t va_start, vaddr_t va_end)
129{
130        pt_entry_t flags = PG_V | PG_KW | PG_NX;
131        size_t L4start, L4end, nL4e;
132        size_t L3start, L3end, nL3e;
133        size_t L2start, L2end, nL2e;
134        paddr_t L3page, L2page, L1page;
135        paddr_t pa;
136        size_t i, npa;
137        pt_entry_t *pde;
138
139        /* Allocate L3 */
140        L4start = pl4_i(va_start);
141        L4end = pl4_i(va_end);
142        nL4e = (L4end - L4start + 1);
143        L3page = hal_gpt_bootstrap_palloc(nL4e);
144
145        /* Allocate L2 */
146        L3start = pl3_i(va_start);
147        L3end = pl3_i(va_end);
148        nL3e = (L3end - L3start + 1);
149        L2page = hal_gpt_bootstrap_palloc(nL3e);
150
151        /* Allocate L1 */
152        L2start = pl2_i(va_start);
153        L2end = pl2_i(va_end);
154        nL2e = (L2end - L2start + 1);
155        L1page = hal_gpt_bootstrap_palloc(nL2e);
156
157        /* Zero out L1 */
158        for (i = 0; i < nL2e; i++) {
159                pa = L1page + i * PAGE_SIZE;
160                hal_gpt_enter(tmpva, pa, flags);
161
162                memset((void *)tmpva, 0, PAGE_SIZE);
163        }
164
165        /* Zero out L2 */
166        for (i = 0; i < nL3e; i++) {
167                pa = L2page + i * PAGE_SIZE;
168                hal_gpt_enter(tmpva, pa, flags);
169
170                memset((void *)tmpva, 0, PAGE_SIZE);
171        }
172
173        /* Zero out L3 */
174        for (i = 0; i < nL4e; i++) {
175                pa = L3page + i * PAGE_SIZE;
176                hal_gpt_enter(tmpva, pa, flags);
177
178                memset((void *)tmpva, 0, PAGE_SIZE);
179        }
180
181        /* Create L2, linked to L1 */
182        npa = (L2start / NPDPG) * PAGE_SIZE;
183        for (i = L2start; i <= L2end; i++) {
184                pa = (paddr_t)&(((pt_entry_t *)L2page)[i]);
185                pa -= npa;      /* shift on the left */
186                pa &= PG_FRAME; /* rounddown to a page boundary */
187                hal_gpt_enter(tmpva, pa, flags);
188
189                pde = (pt_entry_t *)tmpva;
190                pa = L1page + (i - L2start) * PAGE_SIZE;
191                pde[i % NPDPG] = (pa & PG_FRAME) | PG_V | PG_KW;
192        }
193
194        /* Create L3, linked to L2 */
195        npa = (L3start / NPDPG) * PAGE_SIZE;
196        for (i = L3start; i <= L3end; i++) {
197                pa = (paddr_t)&(((pt_entry_t *)L3page)[i]);
198                pa -= npa;      /* shift on the left */
199                pa &= PG_FRAME; /* rounddown to a page boundary */
200                hal_gpt_enter(tmpva, pa, flags);
201
202                pde = (pt_entry_t *)tmpva;
203                pa = L2page + (i - L3start) * PAGE_SIZE;
204                pde[i % NPDPG] = (pa & PG_FRAME) | PG_V | PG_KW;
205        }
206
207        /* Link L3 into L4 */
208        for (i = 0; i < nL4e; i++) {
209                pa = L3page + i * PAGE_SIZE;
210                L4_BASE[L4start + i] = (pa & PG_FRAME) | PG_V | PG_KW;
211        }
212}
213
214void hal_gpt_init(paddr_t firstpa)
215{
216        paddr_t kimg_min_pa, kimg_max_pa;
217
218        /* Initialize global values */
219        pa_avail = firstpa;
220        va_avail = CLUSTER_MIN_VA(0) + KERNEL_VA_SIZE;
221        kimg_size = ((uint64_t)&__kernel_end - KERNBASE);
222        XASSERT(kimg_size % PAGE_SIZE == 0);
223
224        kimg_min_pa = 0;
225        kimg_max_pa = kimg_min_pa + kimg_size;
226
227        /* Create cluster0's page tree */
228        hal_gpt_maptree_area(CLUSTER_MIN_VA(0), CLUSTER_MAX_VA(0));
229
230        /* Manually enter cluster0's kimg */
231        hal_gpt_enter_range(CLUSTER_MIN_VA(0), kimg_min_pa, kimg_size / PAGE_SIZE);
232
233        /* Manually enter cluster0's heap */
234        hal_gpt_enter_range(CLUSTER_MIN_VA(0) + kimg_size, kimg_max_pa,
235            (CLUSTER_VA_SIZE - kimg_size) / PAGE_SIZE);
236
237        /* Unmap the area below the kernel */
238        hal_gpt_leave_range(CLUSTER_MIN_VA(0), (KERNTEXTOFF - KERNBASE) / PAGE_SIZE);
239}
240
241/* -------------------------------------------------------------------------- */
242
243/****************************************************************************************
244 * These global variables defines the masks for the Generic Page Table Entry attributes,
245 * and must be defined in all GPT implementation.
246 ***************************************************************************************/
247
248uint32_t  GPT_MAPPED;
249uint32_t  GPT_SMALL;
250uint32_t  GPT_READABLE;
251uint32_t  GPT_WRITABLE;
252uint32_t  GPT_EXECUTABLE;
253uint32_t  GPT_CACHABLE;
254uint32_t  GPT_USER;
255uint32_t  GPT_DIRTY;
256uint32_t  GPT_ACCESSED;
257uint32_t  GPT_GLOBAL;
258uint32_t  GPT_COW;
259uint32_t  GPT_SWAP;
260uint32_t  GPT_LOCKED;
261
262error_t hal_gpt_create( gpt_t * gpt )
263{
264        x86_panic((char *)__func__);
265        return 0;
266}
267
268void hal_gpt_destroy( gpt_t * gpt )
269{
270        x86_panic((char *)__func__);
271}
272
273void hal_gpt_print( gpt_t * gpt )
274{
275        x86_panic((char *)__func__);
276}
277
278error_t hal_gpt_set_pte( gpt_t   * gpt,
279                         vpn_t     vpn,
280                         ppn_t     ppn,
281                         uint32_t  attr )
282{
283        x86_panic((char *)__func__);
284        return 0;
285}
286
287void hal_gpt_get_pte( gpt_t    * gpt,
288                      vpn_t      vpn,
289                      uint32_t * attr,
290                      ppn_t    * ppn )
291{
292        x86_panic((char *)__func__);
293}
294
295void hal_gpt_reset_pte( gpt_t * gpt,
296                        vpn_t   vpn )
297{
298        x86_panic((char *)__func__);
299}
300
301error_t hal_gpt_lock_pte( gpt_t * gpt,
302                          vpn_t   vpn )
303{
304        x86_panic((char *)__func__);
305        return 0;
306}
307
308error_t hal_gpt_unlock_pte( gpt_t * gpt,
309                            vpn_t   vpn )
310{
311        x86_panic((char *)__func__);
312        return 0;
313}
314
315error_t hal_gpt_copy( gpt_t  * dst_gpt,
316                      gpt_t  * src_gpt,
317                      bool_t   cow )
318{
319        x86_panic((char *)__func__);
320    return 0;
321}
322
Note: See TracBrowser for help on using the repository browser.