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

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

Explicitly use configurable parameters

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