source: trunk/hal/x86_64/hal_gpt.c @ 47

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

Use mcmodel=large, in order to have a kernel image that is located at the
beginning of each cluster in virtual memory, as discussed with Alain. The
performance cost will be taken care of later.

Now, the active kernel is located at 0xfffff00000000000, and the base of
the clusters is 0xffff800000000000.

File size: 7.2 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
77
78void hal_gpt_enter(vaddr_t va, paddr_t pa)
79{
80        XASSERT(va % PAGE_SIZE == 0);
81        XASSERT(pa % PAGE_SIZE == 0);
82        XASSERT(va == tmpva || PTE_BASE[pl1_i(va)] == 0);
83        PTE_BASE[pl1_i(va)] = (pa & PG_FRAME) | PG_V | PG_KW | PG_NX;
84}
85
86void hal_gpt_enter_range(vaddr_t va, paddr_t pa, size_t n)
87{
88        size_t i;
89        for (i = 0; i < n; i++) {
90                hal_gpt_enter(va + i * PAGE_SIZE, pa + i * PAGE_SIZE);
91                invlpg(va + i * PAGE_SIZE);
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}
101
102void hal_gpt_leave_range(vaddr_t va, size_t n)
103{
104        size_t i;
105        for (i = 0; i < n; i++) {
106                hal_gpt_leave(va + i * PAGE_SIZE);
107                invlpg(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        size_t L4start, L4end, nL4e;
120        size_t L3start, L3end, nL3e;
121        size_t L2start, L2end, nL2e;
122        paddr_t L3page, L2page, L1page;
123        paddr_t pa;
124        size_t i, npa;
125        pt_entry_t *pde;
126
127        /* Allocate L3 */
128        L4start = pl4_i(va_start);
129        L4end = pl4_i(va_end);
130        nL4e = (L4end - L4start + 1);
131        L3page = hal_gpt_bootstrap_palloc(nL4e);
132
133        /* Allocate L2 */
134        L3start = pl3_i(va_start);
135        L3end = pl3_i(va_end);
136        nL3e = (L3end - L3start + 1);
137        L2page = hal_gpt_bootstrap_palloc(nL3e);
138
139        /* Allocate L1 */
140        L2start = pl2_i(va_start);
141        L2end = pl2_i(va_end);
142        nL2e = (L2end - L2start + 1);
143        L1page = hal_gpt_bootstrap_palloc(nL2e);
144
145        /* Zero out L1 */
146        for (i = 0; i < nL2e; i++) {
147                pa = L1page + i * PAGE_SIZE;
148                hal_gpt_enter(tmpva, pa);
149                invlpg(tmpva);
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);
158                invlpg(tmpva);
159
160                memset((void *)tmpva, 0, PAGE_SIZE);
161        }
162
163        /* Zero out L3 */
164        for (i = 0; i < nL4e; i++) {
165                pa = L3page + i * PAGE_SIZE;
166                hal_gpt_enter(tmpva, pa);
167                invlpg(tmpva);
168
169                memset((void *)tmpva, 0, PAGE_SIZE);
170        }
171
172        /* Create L2, linked to L1 */
173        npa = (L2start / NPDPG) * PAGE_SIZE;
174        for (i = L2start; i <= L2end; i++) {
175                pa = (paddr_t)&(((pt_entry_t *)L2page)[i]);
176                pa -= npa;      /* shift on the left */
177                pa &= PG_FRAME; /* rounddown to a page boundary */
178                hal_gpt_enter(tmpva, pa);
179                invlpg(tmpva);
180
181                pde = (pt_entry_t *)tmpva;
182                pa = L1page + (i - L2start) * PAGE_SIZE;
183                pde[i % NPDPG] = (pa & PG_FRAME) | PG_V | PG_KW;
184        }
185
186        /* Create L3, linked to L2 */
187        npa = (L3start / NPDPG) * PAGE_SIZE;
188        for (i = L3start; i <= L3end; i++) {
189                pa = (paddr_t)&(((pt_entry_t *)L3page)[i]);
190                pa -= npa;      /* shift on the left */
191                pa &= PG_FRAME; /* rounddown to a page boundary */
192                hal_gpt_enter(tmpva, pa);
193                invlpg(tmpva);
194
195                pde = (pt_entry_t *)tmpva;
196                pa = L2page + (i - L3start) * PAGE_SIZE;
197                pde[i % NPDPG] = (pa & PG_FRAME) | PG_V | PG_KW;
198        }
199
200        /* Link L3 into L4 */
201        for (i = 0; i < nL4e; i++) {
202                pa = L3page + i * PAGE_SIZE;
203                L4_BASE[L4start + i] = (pa & PG_FRAME) | PG_V | PG_KW;
204        }
205}
206
207void hal_gpt_init(paddr_t firstpa)
208{
209        paddr_t kimg_min_pa = 0;
210
211        /* Initialize global values */
212        pa_avail = firstpa;
213        va_avail = CLUSTER_MIN_VA(0) + KERNEL_VA_SIZE;
214        kimg_size = ((uint64_t)&__kernel_end - KERNBASE);
215        XASSERT(kimg_size % PAGE_SIZE == 0);
216        kimg_size = kimg_size / PAGE_SIZE;
217
218        /* Create cluster0's heap entry. */
219        hal_gpt_maptree_area(CLUSTER_MIN_VA(0), CLUSTER_MAX_VA(0));
220
221        /* Manually enter cluster0's kimg */
222        hal_gpt_enter_range(CLUSTER_MIN_VA(0), kimg_min_pa, kimg_size);
223}
224
225/* -------------------------------------------------------------------------- */
226
227/****************************************************************************************
228 * These global variables defines the masks for the Generic Page Table Entry attributes,
229 * and must be defined in all GPT implementation.
230 ***************************************************************************************/
231
232uint32_t  GPT_MAPPED;
233uint32_t  GPT_SMALL;
234uint32_t  GPT_READABLE;
235uint32_t  GPT_WRITABLE; 
236uint32_t  GPT_EXECUTABLE;
237uint32_t  GPT_CACHABLE; 
238uint32_t  GPT_USER; 
239uint32_t  GPT_DIRTY;
240uint32_t  GPT_ACCESSED;
241uint32_t  GPT_GLOBAL;
242uint32_t  GPT_COW;
243uint32_t  GPT_SWAP;
244uint32_t  GPT_LOCKED;
245
246error_t hal_gpt_create( gpt_t * gpt )
247{
248        return 0;
249}
250
251void hal_gpt_destroy( gpt_t * gpt )
252{
253
254}
255
256void hal_gpt_print( gpt_t * gpt )
257{
258
259}
260
261error_t hal_gpt_set_pte( gpt_t   * gpt,
262                         vpn_t     vpn,
263                         ppn_t     ppn,
264                         uint32_t  attr )
265{
266        return 0;
267}
268
269void hal_gpt_get_pte( gpt_t    * gpt,
270                      vpn_t      vpn,
271                      uint32_t * attr,
272                      ppn_t    * ppn )
273{
274
275}
276
277void hal_gpt_reset_pte( gpt_t * gpt,
278                        vpn_t   vpn )
279{
280
281}
282
283error_t hal_gpt_lock_pte( gpt_t * gpt,
284                          vpn_t   vpn )
285{
286        return 0;
287}
288
289error_t hal_gpt_unlock_pte( gpt_t * gpt,
290                            vpn_t   vpn )
291{
292        return 0;
293}
294
295error_t hal_gpt_copy( gpt_t  * dst_gpt,
296                      gpt_t  * src_gpt,
297                      bool_t   cow )
298{
299    return 0;
300}
301
Note: See TracBrowser for help on using the repository browser.