source: trunk/hal/x86_64/core/hal_init.c @ 321

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

Add a --no-smp option.

File size: 16.4 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_apic.h>
28#include <hal_kentry.h>
29#include <hal_internal.h>
30#include <hal_register.h>
31
32#include <hal_remote.h>
33#include <hal_irqmask.h>
34
35#include <memcpy.h>
36#include <thread.h>
37#include <string.h>
38#include <process.h>
39#include <printk.h>
40#include <vmm.h>
41#include <core.h>
42#include <cluster.h>
43#include <chdev.h>
44
45#include <boot_info.h>
46
47void kernel_init(boot_info_t *info);
48
49static void gdt_create();
50static void idt_create();
51void cpu_tls_init(size_t lid);
52void cpu_identify();
53void cpu_attach(size_t lid);
54
55size_t mytest __in_kdata = 0;
56
57struct multiboot_info mb_info __in_kdata;
58char mb_loader_name[PAGE_SIZE] __in_kdata;
59uint8_t mb_mmap[PAGE_SIZE] __in_kdata;
60char mb_cmdline[PAGE_SIZE] __in_kdata;
61
62bool_t has_smp __in_kdata = true;
63size_t ncpu __in_kdata = 0;
64static boot_info_t btinfo __in_kdata;
65
66/* x86-specific per-cluster structures */
67uint8_t gdtstore[PAGE_SIZE] __in_kdata;
68uint8_t idtstore[PAGE_SIZE] __in_kdata;
69
70/* x86-specific per-cpu structures */
71typedef struct {
72        bool_t valid;
73        struct tss tss;
74        struct tls tls;
75        uint8_t boot_stack[STKSIZE];
76        uint8_t intr_stack[STKSIZE];
77        uint8_t dbfl_stack[STKSIZE];
78        uint8_t nmfl_stack[STKSIZE];
79} percpu_archdata_t;
80percpu_archdata_t cpudata[CONFIG_MAX_LOCAL_CORES] __in_kdata;
81
82/* -------------------------------------------------------------------------- */
83
84/* XXX XXX XXX libk */
85char *
86strstr(char *s, const char *find)
87{
88        char c, sc;
89        size_t len;
90
91        if ((c = *find++) != 0) {
92                len = strlen(find);
93                do {
94                        do {
95                                if ((sc = *s++) == 0)
96                                        return (NULL);
97                        } while (sc != c);
98                } while (strncmp(s, find, len) != 0);
99                s--;
100        }
101        return s;
102}
103
104static void
105dump_memmap()
106{
107        size_t mmap_length = mb_info.mi_mmap_length;
108        uint8_t *mmap_addr = (uint8_t *)&mb_mmap;
109        size_t i;
110
111        if (!(mb_info.mi_flags & MULTIBOOT_INFO_HAS_MMAP))
112                x86_panic("No mmap");
113
114        i = 0;
115        while (i < mmap_length) {
116                struct multiboot_mmap *mm;
117
118                mm = (struct multiboot_mmap *)(mmap_addr + i);
119
120                x86_printf("-> [%Z, %Z] %s\n", mm->mm_base_addr,
121                    mm->mm_base_addr + mm->mm_length,
122                    (mm->mm_type == 1) ? "ram" : "rsv" );
123
124                i += mm->mm_size + 4;
125        }
126
127        if (mb_info.mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) {
128                mb_cmdline[PAGE_SIZE-1] = '\0';
129                if (strstr(mb_cmdline, "--no-smp")) {
130                        has_smp = false;
131                        x86_printf("[+] SMP disabled\n");
132                }
133        }
134}
135
136/* -------------------------------------------------------------------------- */
137
138static size_t init_bootinfo_pages_nr()
139{
140        size_t mmap_length = mb_info.mi_mmap_length;
141        uint8_t *mmap_addr = (uint8_t *)&mb_mmap;
142        paddr_t maxpa, pa;
143        size_t i;
144
145        i = 0;
146        maxpa = 0;
147        while (i < mmap_length) {
148                struct multiboot_mmap *mm;
149
150                mm = (struct multiboot_mmap *)(mmap_addr + i);
151
152                if (mm->mm_type == 1) {
153                        pa = mm->mm_base_addr + mm->mm_length;
154                        if (pa > maxpa)
155                                maxpa = pa;
156                }
157
158                i += mm->mm_size + 4;
159        }
160
161        return (maxpa / PAGE_SIZE);
162}
163
164static size_t init_bootinfo_rsvd(boot_rsvd_t *rsvd)
165{
166        size_t mmap_length = mb_info.mi_mmap_length;
167        uint8_t *mmap_addr = (uint8_t *)&mb_mmap;
168        size_t i, rsvd_nr;
169
170        memset(rsvd, 0, sizeof(boot_rsvd_t) * CONFIG_PPM_MAX_RSVD);
171
172        i = 0, rsvd_nr = 0;
173        while (i < mmap_length) {
174                struct multiboot_mmap *mm;
175
176                mm = (struct multiboot_mmap *)(mmap_addr + i);
177
178                if (mm->mm_type != 1) {
179                        rsvd[rsvd_nr].first_page =
180                            rounddown(mm->mm_base_addr, PAGE_SIZE) / PAGE_SIZE;
181                        rsvd[rsvd_nr].npages =
182                            roundup(mm->mm_length, PAGE_SIZE) / PAGE_SIZE;
183                        rsvd_nr++;
184                        if (rsvd_nr == CONFIG_PPM_MAX_RSVD)
185                                x86_panic("too many memory holes");
186                }
187
188                i += mm->mm_size + 4;
189        }
190
191        return rsvd_nr;
192}
193
194static void init_bootinfo_core(boot_core_t *core, size_t n)
195{
196        size_t i;
197
198        // XXX: not necessarily contiguous
199        for (i = 0; i < n; i++) {
200                memset(&core[i], 0, sizeof(boot_core_t));
201
202                core[i].gid = i;
203                core[i].lid = i;
204                core[i].cxy = 0;
205        }
206}
207
208static void init_bootinfo_ioc(boot_device_t *dev)
209{
210        memset(dev, 0, sizeof(boot_device_t));
211
212        dev->base = 0;
213        dev->type = (DEV_FUNC_IOC << 16) | IMPL_IOC_BDV;
214        dev->channels = 1;
215}
216
217static void init_bootinfo_pic(boot_device_t *dev)
218{
219        memset(dev, 0, sizeof(boot_device_t));
220
221        dev->base = 0;
222        dev->type = (DEV_FUNC_PIC << 16) | IMPL_PIC_I86;
223        dev->channels = 1;
224        dev->param0 = 0;
225        dev->param1 = 0;
226        dev->param2 = 0;
227        dev->param3 = 0;
228
229        dev->irqs = 16;
230
231        /* ATA */
232        dev->irq[IRQ_ATA0].dev_type = (DEV_FUNC_IOC << 16) | IMPL_IOC_BDV;
233        dev->irq[IRQ_ATA0].channel = 0;
234        dev->irq[IRQ_ATA0].is_rx = 0;
235        dev->irq[IRQ_ATA0].valid = 1;
236}
237
238static void init_bootinfo_txt(boot_device_t *dev)
239{
240        memset(dev, 0, sizeof(boot_device_t));
241
242        dev->base = 0;
243        dev->type = (DEV_FUNC_TXT << 16) | IMPL_TXT_RS2;
244        dev->channels = 4;
245        dev->param0 = 0;
246        dev->param1 = 0;
247        dev->param2 = 0;
248        dev->param3 = 0;
249}
250
251static void init_bootinfo(boot_info_t *info)
252{
253        size_t offset;
254
255        memset(info, 0, sizeof(boot_info_t));
256
257        info->signature = 0;
258
259        info->paddr_width = 0;
260        info->x_width = 1;
261        info->y_width = 1;
262        info->x_size = 1;
263        info->y_size = 1;
264        info->io_cxy = 0;
265
266        info->ext_dev_nr = 3;
267        init_bootinfo_txt(&info->ext_dev[0]);
268        init_bootinfo_pic(&info->ext_dev[1]);
269        init_bootinfo_ioc(&info->ext_dev[2]);
270
271        info->cxy = 0;
272        if (has_smp) {
273                info->cores_nr = ncpu;
274        } else {
275                info->cores_nr = 1;
276        }
277        init_bootinfo_core((boot_core_t *)&info->core, info->cores_nr);
278
279        info->rsvd_nr = init_bootinfo_rsvd((boot_rsvd_t *)&info->rsvd);
280
281        /* TODO: dev_mmc */
282        /* TODO: dev_dma */
283
284        offset = hal_gpt_bootstrap_uniformize();
285        info->pages_offset = offset / PAGE_SIZE;
286        info->pages_nr = init_bootinfo_pages_nr();
287}
288
289/* -------------------------------------------------------------------------- */
290
291static uint32_t cpuN_booted __in_kdata;
292
293void start_secondary_cpus()
294{
295        pt_entry_t flags = PG_V | PG_KW;
296        extern vaddr_t cpuN_boot_trampoline;
297        extern vaddr_t cpuN_boot_trampoline_end;
298        extern paddr_t smp_L4pa;
299        extern vaddr_t smp_stkva;
300        extern paddr_t L4paddr;
301        size_t i, sz;
302
303        smp_L4pa = L4paddr;
304
305        /* map the SMP trampoline (identity) */
306        vaddr_t trampva = (vaddr_t)SMP_TRAMPOLINE_PA;
307        hal_gpt_maptree_area(trampva, trampva + PAGE_SIZE);
308        hal_gpt_enter(trampva, SMP_TRAMPOLINE_PA, flags);
309
310        /* copy it */
311        sz = (size_t)&cpuN_boot_trampoline_end - (size_t)&cpuN_boot_trampoline;
312        memcpy((void *)trampva, (void *)&cpuN_boot_trampoline, sz);
313
314        for (i = 0; i < CONFIG_MAX_LOCAL_CORES; i++) {
315                if (i == 0 || !cpudata[i].valid) {
316                        continue;
317                }
318
319                smp_stkva = ((vaddr_t)&cpudata[i].boot_stack + STKSIZE) & ~0xF;
320
321                cpuN_booted = 0;
322                boot_cpuN(i, SMP_TRAMPOLINE_PA);
323                while (!hal_atomic_cas(&cpuN_booted, 1, 0)) {
324                        pause();
325                }
326        }
327
328        // XXX: unmap the trampoline
329}
330
331void init_x86_64_cpuN()
332{
333        lid_t lid;
334
335        cli();
336
337        lid = hal_lapic_gid();
338
339        cpu_attach(lid);
340        x86_printf("[cpu%z] cpu_attach called\n", (uint64_t)lid);
341
342        cpu_tls_init(lid);
343        x86_printf("[cpu%z] cput_tls_init called\n", (uint64_t)lid);
344
345        cpu_lapic_init();
346        x86_printf("[cpu%z] cpu_lapic_init called\n", (uint64_t)lid);
347
348        cpuN_booted = 1;
349
350        if (lid == 1) {
351                hal_ioapic_disable_irq(IRQ_KEYBOARD);
352                hal_ioapic_bind_irq(IRQ_KEYBOARD, IOAPIC_KEYBOARD_VECTOR, 1);
353                hal_ioapic_enable_irq(IRQ_KEYBOARD);
354        }
355
356        kernel_init(&btinfo);
357
358        reg_t dummy;
359        hal_enable_irq(&dummy);
360
361        while (1);
362}
363
364/* -------------------------------------------------------------------------- */
365
366static void apic_map()
367{
368        extern vaddr_t lapic_va, ioapic_va;
369        extern paddr_t lapic_pa, ioapic_pa;
370
371        lapic_va = hal_gpt_bootstrap_valloc(1); // XXX: should be shared
372        hal_gpt_enter(lapic_va, lapic_pa, PG_V|PG_KW|PG_NX|PG_N);
373
374        ioapic_va = hal_gpt_bootstrap_valloc(1); // XXX: should be shared
375        hal_gpt_enter(ioapic_va, ioapic_pa, PG_V|PG_KW|PG_NX|PG_N);
376}
377
378void init_x86_64(paddr_t firstpa)
379{
380        cli();
381
382        /* Initialize the serial port */
383        hal_com_init_early();
384
385        x86_printf("[+] init_x86_64 called\n");
386
387        /* Create the global structures */
388        gdt_create();
389        idt_create();
390
391        /* Identify the features of the cpu */
392        cpu_identify();
393
394        /* Attach cpu0 */
395        cpu_attach(0);
396        x86_printf("[+] cpu_attach called\n");
397
398        x86_printf("[+] bootloader: '%s'\n", mb_loader_name);
399
400        dump_memmap();
401        x86_printf("[+] dump finished\n");
402
403        hal_gpt_init(firstpa);
404        x86_printf("[+] hal_gpt_init called\n");
405
406        hal_acpi_init();
407        x86_printf("[+] hal_acpi_init called\n");
408
409        hal_gpt_bootstrap_reset();
410        x86_printf("[+] hal_gpt_bootstrap_reset called\n");
411
412        apic_map();
413        x86_printf("[+] apic_map called\n");
414
415        hal_apic_init();
416        cpu_lapic_init();
417        x86_printf("[+] hal_apic_init called\n");
418
419        cpu_tls_init(0);
420        x86_printf("[+] cput_tls_init called\n");
421
422        mytest = 0;
423        x86_printf("-> mytest = %z\n", mytest);
424        void *hoho = &init_x86_64;
425        xptr_t myptr = XPTR(0, &mytest);
426
427        hal_remote_spt(myptr, hoho);
428        x86_printf("-> mytest = %Z\n", hal_remote_lpt(myptr));
429
430        init_bootinfo(&btinfo);
431
432        if (has_smp) {
433                start_secondary_cpus();
434        }
435
436        kernel_init(&btinfo);
437
438        x86_printf("[+] kernel_init called\n");
439
440        reg_t dummy;
441        hal_enable_irq(&dummy);
442
443        while (1);
444
445/*
446        void *ptr;
447
448        khm_t *khm = &LOCAL_CLUSTER->khm;
449        ptr = khm_alloc(khm, 10);
450        memset(ptr, 0, 10);
451        khm_free(ptr);
452
453
454        kcm_t *kcm = &LOCAL_CLUSTER->kcm;
455        ptr = kcm_alloc(kcm);
456        memset(ptr, 0, 1);
457        kcm_free(ptr);
458
459        ptr = ppm_alloc_pages(1);
460        ppm_free_pages(ptr);
461*/
462
463
464//      void x86_stop();
465//      x86_stop();
466}
467
468/* -------------------------------------------------------------------------- */
469
470void cpu_activate(uint32_t gid)
471{
472        cpudata[gid].valid = true;
473}
474
475static void
476setregion(struct region_descriptor *rd, void *base, uint16_t limit)
477{
478        rd->rd_limit = limit;
479        rd->rd_base = (uint64_t)base;
480}
481
482/* -------------------------------------------------------------------------- */
483
484static void
485gdt_set_memseg(struct gdt_memseg *sd, void *base, size_t limit,
486        int type, int dpl, int gran, bool_t is64)
487{
488        sd->sd_lolimit = (unsigned)limit;
489        sd->sd_lobase = (unsigned long)base;
490        sd->sd_type = type;
491        sd->sd_dpl = dpl;
492        sd->sd_p = 1;
493        sd->sd_hilimit = (unsigned)limit >> 16;
494        sd->sd_avl = 0;
495        sd->sd_long = is64;
496        sd->sd_def32 = !is64;
497        sd->sd_gran = gran;
498        sd->sd_hibase = (unsigned long)base >> 24;
499}
500
501static void
502gdt_set_sysseg(struct gdt_sysseg *sd, void *base, size_t limit,
503        int type, int dpl, int gran)
504{
505        memset(sd, 0, sizeof *sd);
506        sd->sd_lolimit = (unsigned)limit;
507        sd->sd_lobase = (uint64_t)base;
508        sd->sd_type = type;
509        sd->sd_dpl = dpl;
510        sd->sd_p = 1;
511        sd->sd_hilimit = (unsigned)limit >> 16;
512        sd->sd_gran = gran;
513        sd->sd_hibase = (uint64_t)base >> 24;
514}
515
516static void gdt_create()
517{
518        memset(&gdtstore, 0, PAGE_SIZE);
519
520        /* Flat segments */
521        gdt_set_memseg(GDT_ADDR_MEM(gdtstore, GDT_KCODE_SEL), 0,
522            0xfffff, SDT_MEMERA, SEL_KPL, 1, true);
523        gdt_set_memseg(GDT_ADDR_MEM(gdtstore, GDT_KDATA_SEL), 0,
524            0xfffff, SDT_MEMRWA, SEL_KPL, 1, true);
525        gdt_set_memseg(GDT_ADDR_MEM(gdtstore, GDT_UCODE32_SEL), 0,
526            0xfffff, SDT_MEMERA, SEL_UPL, 1, false);
527        gdt_set_memseg(GDT_ADDR_MEM(gdtstore, GDT_UCODE_SEL), 0,
528            0xfffff, SDT_MEMERA, SEL_UPL, 1, true);
529        gdt_set_memseg(GDT_ADDR_MEM(gdtstore, GDT_UDATA_SEL), 0,
530            0xfffff, SDT_MEMRWA, SEL_UPL, 1, true);
531}
532
533void cpu_load_gdt()
534{
535        struct region_descriptor region;
536        setregion(&region, &gdtstore, PAGE_SIZE - 1);
537        lgdt(&region);
538}
539
540/* -------------------------------------------------------------------------- */
541
542struct {
543        bool_t busy[256];
544} idt_bitmap __in_kdata;
545
546int idt_slot_alloc()
547{
548        size_t i;
549
550        for (i = 0; i < 256; i++) {
551                if (!idt_bitmap.busy[i])
552                        break;
553        }
554        if (i == 256) {
555                return -1;
556        }
557
558        idt_bitmap.busy[i] = true;
559        return (int)i;
560}
561
562void idt_slot_free(int slot)
563{
564        idt_bitmap.busy[slot] = false;
565}
566
567static void
568idt_set_seg(struct idt_seg *seg, void *func, int ist, int type, int dpl, int sel)
569{
570        seg->gd_looffset = (uint64_t)func & 0xffff;
571        seg->gd_selector = sel;
572        seg->gd_ist = ist;
573        seg->gd_type = type;
574        seg->gd_dpl = dpl;
575        seg->gd_p = 1;
576        seg->gd_hioffset = (uint64_t)func >> 16;
577        seg->gd_zero = 0;
578        seg->gd_xx1 = 0;
579        seg->gd_xx2 = 0;
580        seg->gd_xx3 = 0;
581}
582
583static void idt_create()
584{
585        extern uint64_t x86_traps[], x86_intrs[], x86_rsvd;
586        struct idt_seg *idt;
587        size_t i;
588        int ist;
589
590        memset(&idt_bitmap, 0, sizeof(idt_bitmap));
591        idt = (struct idt_seg *)&idtstore;
592
593        /* First, put a dead entry */
594        for (i = 0; i < NIDT; i++) {
595                idt_set_seg(&idt[i], (void *)&x86_rsvd, 0,
596                    SDT_SYS386IGT, SEL_KPL, GDT_FIXED_SEL(GDT_KCODE_SEL, SEL_KPL));
597        }
598
599        /* General exceptions */
600        for (i = CPUVEC_MIN; i < CPUVEC_MAX; i++) {
601                if (i == 2) { /* NMI */
602                        ist = 3;
603                } else if (i == 8) { /* Double Fault */
604                        ist = 2;
605                } else {
606                        ist = 0;
607                }
608                idt_set_seg(&idt[i], (void *)x86_traps[i - CPUVEC_MIN], ist,
609                    SDT_SYS386IGT, SEL_KPL, GDT_FIXED_SEL(GDT_KCODE_SEL, SEL_KPL));
610                idt_bitmap.busy[i] = true;
611        }
612
613        /* Dynamically configured interrupts */
614        for (i = DYNVEC_MIN; i < DYNVEC_MAX; i++) {
615                idt_set_seg(&idt[i], (void *)x86_intrs[i - DYNVEC_MIN], 0,
616                    SDT_SYS386IGT, SEL_KPL, GDT_FIXED_SEL(GDT_KCODE_SEL, SEL_KPL));
617                idt_bitmap.busy[i] = true;
618        }
619}
620
621void cpu_load_idt()
622{
623        struct region_descriptor region;
624        setregion(&region, &idtstore, PAGE_SIZE - 1);
625        lidt(&region);
626}
627
628/* -------------------------------------------------------------------------- */
629
630int tss_alloc(struct tss *tss, size_t lid)
631{
632        int slot;
633
634        slot = GDT_CPUTSS_SEL + lid;
635
636        gdt_set_sysseg(GDT_ADDR_SYS(gdtstore, slot), tss,
637            sizeof(*tss) - 1, SDT_SYS386TSS, SEL_KPL, 0);
638
639        return GDT_DYNAM_SEL(slot, SEL_KPL);
640}
641
642void cpu_create_tss(size_t lid)
643{
644        percpu_archdata_t *data = &cpudata[lid];
645        struct tss *tss = &data->tss;
646        int sel;
647
648        /* Create the tss */
649        memset(tss, 0, sizeof(*tss));
650
651        /* tss->tss_rsp0 */
652        tss->tss_ist[0] = ((uint64_t)&data->intr_stack + STKSIZE) & ~0xF;
653        tss->tss_ist[1] = ((uint64_t)&data->dbfl_stack + STKSIZE) & ~0xF;
654        tss->tss_ist[2] = ((uint64_t)&data->nmfl_stack + STKSIZE) & ~0xF;
655        tss->tss_iobase = IOMAP_INVALOFF << 16;
656        sel = tss_alloc(tss, lid);
657
658        /* Load it */
659        ltr(sel);
660}
661
662/* -------------------------------------------------------------------------- */
663
664void cpu_tls_init(size_t lid)
665{
666        extern uint64_t x86_syscall;
667        extern uint64_t x86_syscall32;
668
669        percpu_archdata_t *data = &cpudata[lid];
670        tls_t *cputls = &data->tls;
671
672        memset(cputls, 0, sizeof(tls_t));
673
674        cputls->tls_self = cputls;
675        cputls->tls_gid = hal_lapic_gid();
676        cputls->tls_lid = lid;
677        cputls->tls_intr = INTRS_DISABLED;
678
679        /* syscall */
680        wrmsr(MSR_STAR,
681            ((uint64_t)GDT_FIXED_SEL(GDT_KCODE_SEL, SEL_KPL) << 32) |
682            ((uint64_t)GDT_FIXED_SEL(GDT_UCODE32_SEL, SEL_UPL) << 48));
683        wrmsr(MSR_LSTAR, (uint64_t)&x86_syscall);
684        wrmsr(MSR_CSTAR, (uint64_t)&x86_syscall32);
685        wrmsr(MSR_SFMASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D);
686
687        /* TLS */
688        wrmsr(MSR_FSBASE, 0);
689        wrmsr(MSR_GSBASE, (uint64_t)cputls);
690        wrmsr(MSR_KERNELGSBASE, 0);
691}
692
693/* -------------------------------------------------------------------------- */
694
695uint64_t cpu_features[4] __in_kdata;
696
697void cpu_identify()
698{
699        /*
700         * desc[0] = eax
701         * desc[1] = ebx
702         * desc[2] = ecx
703         * desc[3] = edx
704         */
705        uint32_t desc[4];
706        char vendor[13];
707        size_t lvl;
708
709        /*
710         * Get information from the standard cpuid leafs
711         */
712        cpuid(0, 0, (uint32_t *)&desc);
713
714        lvl = (uint64_t)desc[0];
715        x86_printf("-> cpuid standard level: %z\n", lvl);
716
717        memcpy(vendor + 0, &desc[1], sizeof(uint32_t));
718        memcpy(vendor + 8, &desc[2], sizeof(uint32_t));
719        memcpy(vendor + 4, &desc[3], sizeof(uint32_t));
720        vendor[12] = '\0';
721        x86_printf("-> CPU vendor: '%s'\n", vendor);
722
723        if (lvl >= 1) {
724                cpuid(1, 0, (uint32_t *)&desc);
725                cpu_features[0] = desc[3];
726                cpu_features[1] = desc[2];
727        }
728
729        /*
730         * Get information from the extended cpuid leafs
731         */
732        cpuid(0x80000000, 0, desc);
733
734        lvl = (uint64_t)desc[0];
735        x86_printf("-> cpuid extended level: %Z\n", lvl);
736}
737
738/* -------------------------------------------------------------------------- */
739
740void cpu_attach(size_t lid)
741{
742        /* Per-cluster structures */
743        cpu_load_gdt();
744        cpu_load_idt();
745
746        /* Per-cpu structures */
747        cpu_create_tss(lid);
748
749        if (cpu_features[0] & CPUID_PSE) {
750                lcr4(rcr4() | CR4_PSE);
751                tlbflushg();
752        } else {
753                /*
754                 * amd64 supports PSE by default, if it's not here we have a
755                 * problem
756                 */
757                x86_panic("PSE not supported");
758        }
759}
760
Note: See TracBrowser for help on using the repository browser.