source: trunk/hal/x86_64/hal_init.c @ 48

Last change on this file since 48 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: 6.8 KB
Line 
1/*
2 * hal_init.c - C initialization procedure for x86.
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>
24#include <hal_multiboot.h>
25#include <hal_segmentation.h>
26#include <hal_acpi.h>
27#include <hal_lapic.h>
28#include <hal_internal.h>
29
30#include <memcpy.h>
31#include <thread.h>
32#include <string.h>
33#include <process.h>
34#include <printk.h>
35#include <vmm.h>
36#include <core.h>
37#include <cluster.h>
38
39static void gdt_create();
40static void idt_create();
41void cpu_attach();
42
43size_t mytest __in_kdata = 0;
44
45struct multiboot_info mb_info __in_kdata;
46char mb_loader_name[PAGE_SIZE] __in_kdata;
47uint8_t mb_mmap[PAGE_SIZE] __in_kdata;
48
49/* -------------------------------------------------------------------------- */
50
51static void
52dump_memmap()
53{
54        size_t mmap_length = mb_info.mi_mmap_length;
55        uint8_t *mmap_addr = (uint8_t *)&mb_mmap;
56        size_t i;
57
58        if (!(mb_info.mi_flags & MULTIBOOT_INFO_HAS_MMAP))
59                x86_panic("No mmap");
60
61        i = 0;
62        while (i < mmap_length) {
63                struct multiboot_mmap *mm;
64
65                mm = (struct multiboot_mmap *)(mmap_addr + i);
66
67                x86_printf("-> [%Z, %Z] %s\n", mm->mm_base_addr,
68                    mm->mm_base_addr + mm->mm_length,
69                    (mm->mm_type == 1) ? "ram" : "rsv" );
70
71                i += mm->mm_size + 4;
72        }
73}
74
75void init_x86_64(paddr_t firstpa)
76{
77        x86_printf("[+] init_x86_64 called\n");
78
79        /* Create the global structures */
80        gdt_create();
81        x86_printf("[+] gdt_create called\n");
82
83        idt_create();
84        x86_printf("[+] idt_create called\n");
85
86        /* Attach cpu0 */
87        cpu_attach();
88        x86_printf("[+] cpu_attach called\n");
89
90        x86_printf("[+] bootloader: '%s'\n", mb_loader_name);
91
92        dump_memmap();
93        x86_printf("[+] dump finished\n");
94
95        hal_gpt_init(firstpa);
96        x86_printf("[+] hal_gpt_init called\n");
97
98        hal_acpi_init();
99        x86_printf("[+] hal_acpi_init called\n");
100
101        hal_gpt_bootstrap_reset();
102        x86_printf("[+] hal_gpt_bootstrap_reset called\n");
103
104        hal_lapic_init();
105        x86_printf("[+] hal_lapic_init called\n");
106
107        hal_tls_init_cpu0();
108        x86_printf("[+] hal_tls_init_cpu0 called\n");
109
110        x86_printf("-> mytest = %z\n", mytest);
111        size_t *myptr = CLUSTER_MIN_VA(0) + XPTR(0, &mytest);
112        *myptr = 1;
113        x86_printf("-> mytest = %z\n", mytest);
114
115        int m = 0;
116        int v = 1 / m;
117
118        char *buf = NULL;
119        *buf = (char)0x01;
120
121        x86_printf("ALIVE!\n");
122
123        while (1);
124}
125
126/* -------------------------------------------------------------------------- */
127
128uint8_t gdtstore[PAGE_SIZE] __in_kdata;
129uint8_t idtstore[PAGE_SIZE] __in_kdata;
130struct tss cpu0_tss __in_kdata;
131uint8_t cpu0_intr_stack[STKSIZE] __in_kdata;
132uint8_t cpu0_dbfl_stack[STKSIZE] __in_kdata;
133uint8_t cpu0_nmfl_stack[STKSIZE] __in_kdata;
134
135static void
136setregion(struct region_descriptor *rd, void *base, uint16_t limit)
137{
138        rd->rd_limit = limit;
139        rd->rd_base = (uint64_t)base;
140}
141
142/* -------------------------------------------------------------------------- */
143
144static void
145gdt_set_memseg(struct gdt_memseg *sd, void *base, size_t limit,
146        int type, int dpl, int gran, int is64)
147{
148        sd->sd_lolimit = (unsigned)limit;
149        sd->sd_lobase = (unsigned long)base;
150        sd->sd_type = type;
151        sd->sd_dpl = dpl;
152        sd->sd_p = 1;
153        sd->sd_hilimit = (unsigned)limit >> 16;
154        sd->sd_avl = 0;
155        sd->sd_long = is64;
156        sd->sd_def32 = 0;
157        sd->sd_gran = gran;
158        sd->sd_hibase = (unsigned long)base >> 24;
159}
160
161static void
162gdt_set_sysseg(struct gdt_sysseg *sd, void *base, size_t limit,
163        int type, int dpl, int gran)
164{
165        memset(sd, 0, sizeof *sd);
166        sd->sd_lolimit = (unsigned)limit;
167        sd->sd_lobase = (uint64_t)base;
168        sd->sd_type = type;
169        sd->sd_dpl = dpl;
170        sd->sd_p = 1;
171        sd->sd_hilimit = (unsigned)limit >> 16;
172        sd->sd_gran = gran;
173        sd->sd_hibase = (uint64_t)base >> 24;
174}
175
176static void gdt_create()
177{
178        memset(&gdtstore, 0, PAGE_SIZE);
179
180        /* Flat segments */
181        gdt_set_memseg(GDT_ADDR_MEM(gdtstore, GDT_KCODE_SEL), 0,
182            0xfffff, SDT_MEMERA, SEL_KPL, 1, 1);
183        gdt_set_memseg(GDT_ADDR_MEM(gdtstore, GDT_KDATA_SEL), 0,
184            0xfffff, SDT_MEMRWA, SEL_KPL, 1, 1);
185        gdt_set_memseg(GDT_ADDR_MEM(gdtstore, GDT_UCODE_SEL), 0,
186            0xfffff, SDT_MEMERA, SEL_UPL, 1, 1);
187        gdt_set_memseg(GDT_ADDR_MEM(gdtstore, GDT_UDATA_SEL), 0,
188            0xfffff, SDT_MEMRWA, SEL_UPL, 1, 1);
189}
190
191void cpu_load_gdt()
192{
193        struct region_descriptor region;
194        setregion(&region, &gdtstore, PAGE_SIZE - 1);
195        lgdt(&region);
196}
197
198/* -------------------------------------------------------------------------- */
199
200static void
201idt_set_seg(struct idt_seg *seg, void *func, int ist, int type, int dpl, int sel)
202{
203        seg->gd_looffset = (uint64_t)func & 0xffff;
204        seg->gd_selector = sel;
205        seg->gd_ist = ist;
206        seg->gd_type = type;
207        seg->gd_dpl = dpl;
208        seg->gd_p = 1;
209        seg->gd_hioffset = (uint64_t)func >> 16;
210        seg->gd_zero = 0;
211        seg->gd_xx1 = 0;
212        seg->gd_xx2 = 0;
213        seg->gd_xx3 = 0;
214}
215
216static void idt_create()
217{
218        extern uint64_t x86_traps[], x86_intrs[];
219        struct idt_seg *idt;
220        size_t i;
221
222        idt = (struct idt_seg *)&idtstore;
223
224        /* General exceptions */
225        for (i = CPUVEC_MIN; i < CPUVEC_MAX; i++) {
226                idt_set_seg(&idt[i], (void *)x86_traps[i - CPUVEC_MIN], 0,
227                    SDT_SYS386IGT, SEL_KPL, GDT_FIXED_SEL(GDT_KCODE_SEL, SEL_KPL));
228        }
229
230        /* LAPIC interrupts */
231        for (i = LAPICVEC_MIN; i < LAPICVEC_MAX; i++) {
232                idt_set_seg(&idt[i], (void *)x86_intrs[i - LAPICVEC_MIN], 0,
233                    SDT_SYS386IGT, SEL_KPL, GDT_FIXED_SEL(GDT_KCODE_SEL, SEL_KPL));
234        }
235}
236
237void cpu_load_idt()
238{
239        struct region_descriptor region;
240        setregion(&region, &idtstore, PAGE_SIZE - 1);
241        lidt(&region);
242}
243
244/* -------------------------------------------------------------------------- */
245
246/*
247 * The gdt bitmap must be per-cluster.
248 */
249int tss_alloc(struct tss *tss)
250{
251        int slot;
252
253        /* Once we have proper SMP support, we will change that */
254        slot = GDT_CPU0TSS_SEL;
255
256        gdt_set_sysseg(GDT_ADDR_SYS(gdtstore, slot), tss,
257            sizeof(*tss) - 1, SDT_SYS386TSS, SEL_KPL, 0);
258
259        return GDT_DYNAM_SEL(slot, SEL_KPL);
260}
261
262void cpu_create_tss()
263{
264        struct tss *tss = &cpu0_tss;
265        int sel;
266
267        /* Create the tss */
268        memset(tss, 0, sizeof(*tss));
269        tss->tss_iobase = IOMAP_INVALOFF << 16;
270        tss->tss_ist[0] = (uint64_t)cpu0_intr_stack + STKSIZE;
271        tss->tss_ist[1] = (uint64_t)cpu0_dbfl_stack + STKSIZE;
272        tss->tss_ist[2] = (uint64_t)cpu0_nmfl_stack + STKSIZE;
273        sel = tss_alloc(tss);
274
275        /* Load it */
276        ltr(sel);
277}
278
279/* -------------------------------------------------------------------------- */
280
281void cpu_attach()
282{
283        cpu_load_gdt();
284        cpu_load_idt();
285        cpu_create_tss();
286}
287
Note: See TracBrowser for help on using the repository browser.