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

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

Update. We need to use two separate arrays: one for the heap and one for
the kimg. The size of a heap entry is configurable, but that of the kimg
is not (fixed by mcmodel).

As a result, we also need to use two XPTRs: XPTR_HEAP and XPTR_KIMG. For
now we only declare XPTR_KIMG, and are not using it yet.

File size: 6.7 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
67void hal_gpt_enter(vaddr_t va, paddr_t pa)
68{
69        XASSERT((va % PAGE_SIZE == 0));
70        XASSERT((pa % PAGE_SIZE == 0));
71        PTE_BASE[pl1_i(va)] = (pa & PG_FRAME) | PG_V | PG_KW | PG_NX;
72}
73
74void hal_gpt_enter_range(vaddr_t va, paddr_t pa, size_t n)
75{
76        size_t i;
77        for (i = 0; i < n; i++) {
78                hal_gpt_enter(va + i * PAGE_SIZE, pa + i * PAGE_SIZE);
79                invlpg(va + i * PAGE_SIZE);
80        }
81}
82
83/*
84 * Create a page tree that can map va_start->va_end. The caller can then
85 * enter these addresses to physical locations.
86 *
87 * This functions is a bit complicated, and may need to be revisited.
88 */
89void hal_gpt_maptree_area(vaddr_t va_start, vaddr_t va_end)
90{
91        size_t L4start, L4end, nL4e;
92        size_t L3start, L3end, nL3e;
93        size_t L2start, L2end, nL2e;
94        paddr_t L3page, L2page, L1page;
95        paddr_t pa;
96        size_t i, npa;
97        pt_entry_t *pde;
98
99        /* Allocate L3 */
100        L4start = pl4_i(va_start);
101        L4end = pl4_i(va_end);
102        nL4e = (L4end - L4start + 1);
103        L3page = hal_gpt_bootstrap_palloc(nL4e);
104
105        /* Allocate L2 */
106        L3start = pl3_i(va_start);
107        L3end = pl3_i(va_end);
108        nL3e = (L3end - L3start + 1);
109        L2page = hal_gpt_bootstrap_palloc(nL3e);
110
111        /* Allocate L1 */
112        L2start = pl2_i(va_start);
113        L2end = pl2_i(va_end);
114        nL2e = (L2end - L2start + 1);
115        L1page = hal_gpt_bootstrap_palloc(nL2e);
116
117        /* Zero out L1 */
118        for (i = 0; i < nL2e; i++) {
119                pa = L1page + i * PAGE_SIZE;
120                hal_gpt_enter(tmpva, pa);
121                invlpg(tmpva);
122
123                memset((void *)tmpva, 0, PAGE_SIZE);
124        }
125
126        /* Zero out L2 */
127        for (i = 0; i < nL3e; i++) {
128                pa = L2page + i * PAGE_SIZE;
129                hal_gpt_enter(tmpva, pa);
130                invlpg(tmpva);
131
132                memset((void *)tmpva, 0, PAGE_SIZE);
133        }
134
135        /* Zero out L3 */
136        for (i = 0; i < nL4e; i++) {
137                pa = L3page + i * PAGE_SIZE;
138                hal_gpt_enter(tmpva, pa);
139                invlpg(tmpva);
140
141                memset((void *)tmpva, 0, PAGE_SIZE);
142        }
143
144        /* Create L2, linked to L1 */
145        npa = (L2start / NPDPG) * PAGE_SIZE;
146        for (i = L2start; i <= L2end; i++) {
147                pa = (paddr_t)&(((pt_entry_t *)L2page)[i]);
148                pa -= npa;      /* shift on the left */
149                pa &= PG_FRAME; /* rounddown to a page boundary */
150                hal_gpt_enter(tmpva, pa);
151                invlpg(tmpva);
152
153                pde = (pt_entry_t *)tmpva;
154                pa = L1page + (i - L2start) * PAGE_SIZE;
155                pde[i % NPDPG] = (pa & PG_FRAME) | PG_V | PG_KW;
156        }
157
158        /* Create L3, linked to L2 */
159        npa = (L3start / NPDPG) * PAGE_SIZE;
160        for (i = L3start; i <= L3end; i++) {
161                pa = (paddr_t)&(((pt_entry_t *)L3page)[i]);
162                pa -= npa;      /* shift on the left */
163                pa &= PG_FRAME; /* rounddown to a page boundary */
164                hal_gpt_enter(tmpva, pa);
165                invlpg(tmpva);
166
167                pde = (pt_entry_t *)tmpva;
168                pa = L2page + (i - L3start) * PAGE_SIZE;
169                pde[i % NPDPG] = (pa & PG_FRAME) | PG_V | PG_KW;
170        }
171
172        /* Link L3 into L4 */
173        for (i = 0; i < nL4e; i++) {
174                pa = L3page + i * PAGE_SIZE;
175                L4_BASE[L4start + i] = (pa & PG_FRAME) | PG_V | PG_KW;
176        }
177}
178
179void hal_gpt_init(paddr_t firstpa)
180{
181        paddr_t kimg_min_pa = 0;
182
183        /* Initialize global values */
184        pa_avail = firstpa;
185        va_avail = CLUSTER_HEAP_MIN_VA(0);
186        kimg_size = ((uint64_t)&__kernel_end - KERNBASE);
187        XASSERT(kimg_size % PAGE_SIZE == 0);
188        kimg_size = kimg_size / PAGE_SIZE;
189
190        /* Create cluster0's heap entry. */
191        hal_gpt_maptree_area(CLUSTER_HEAP_MIN_VA(0), CLUSTER_HEAP_MAX_VA(0));
192
193        /* Create cluster0's kimg entry. */
194        hal_gpt_maptree_area(CLUSTER_KIMG_MIN_VA(0), CLUSTER_KIMG_MAX_VA(0));
195
196        /* Manually enter cluster0's kimg */
197        hal_gpt_enter_range(CLUSTER_KIMG_MIN_VA(0), kimg_min_pa, kimg_size);
198}
199
200/* -------------------------------------------------------------------------- */
201
202/****************************************************************************************
203 * These global variables defines the masks for the Generic Page Table Entry attributes,
204 * and must be defined in all GPT implementation.
205 ***************************************************************************************/
206
207uint32_t  GPT_MAPPED;
208uint32_t  GPT_SMALL;
209uint32_t  GPT_READABLE;
210uint32_t  GPT_WRITABLE; 
211uint32_t  GPT_EXECUTABLE;
212uint32_t  GPT_CACHABLE; 
213uint32_t  GPT_USER; 
214uint32_t  GPT_DIRTY;
215uint32_t  GPT_ACCESSED;
216uint32_t  GPT_GLOBAL;
217uint32_t  GPT_COW;
218uint32_t  GPT_SWAP;
219uint32_t  GPT_LOCKED;
220
221error_t hal_gpt_create( gpt_t * gpt )
222{
223        return 0;
224}
225
226void hal_gpt_destroy( gpt_t * gpt )
227{
228
229}
230
231void hal_gpt_print( gpt_t * gpt )
232{
233
234}
235
236error_t hal_gpt_set_pte( gpt_t   * gpt,
237                         vpn_t     vpn,
238                         ppn_t     ppn,
239                         uint32_t  attr )
240{
241        return 0;
242}
243
244void hal_gpt_get_pte( gpt_t    * gpt,
245                      vpn_t      vpn,
246                      uint32_t * attr,
247                      ppn_t    * ppn )
248{
249
250}
251
252void hal_gpt_reset_pte( gpt_t * gpt,
253                        vpn_t   vpn )
254{
255
256}
257
258error_t hal_gpt_lock_pte( gpt_t * gpt,
259                          vpn_t   vpn )
260{
261        return 0;
262}
263
264error_t hal_gpt_unlock_pte( gpt_t * gpt,
265                            vpn_t   vpn )
266{
267        return 0;
268}
269
270error_t hal_gpt_copy( gpt_t  * dst_gpt,
271                      gpt_t  * src_gpt,
272                      bool_t   cow )
273{
274    return 0;
275}
276
Note: See TracBrowser for help on using the repository browser.