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

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

Update:

  • Introduce a basic VM manager in hal_gpt.c, to create the initial page tree for cluster0.
  • Locate the ACPI RSDP table, which involves entering the PA into cluster0's VA space.

The definitions are still a bit messy, but they will be reorganized later.

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