kconfig: use pkg-config for ncurses detection
[akaros.git] / kern / arch / riscv / cboot.c
1 #include <arch/arch.h>
2 #include <arch/mmu.h>
3 #include <assert.h>
4 #include <multiboot.h>
5 #include <pmap.h>
6 #include <ros/memlayout.h>
7 #include <stdio.h>
8 #include <string.h>
9
10 #define MAX_KERNBASE_SIZE (KERN_VMAP_TOP - KERNBASE)
11
12 uint32_t num_cores = 1; // this must not be in BSS
13
14 static uint64_t mem_size(uint64_t sz_mb)
15 {
16         uint64_t sz = (uint64_t)sz_mb * 1024 * 1024;
17
18         return MIN(sz, MIN(MAX_KERNBASE_SIZE, (uint64_t)L1PGSIZE * NPTENTRIES));
19 }
20
21 void pagetable_init(uint32_t memsize_mb, pte_t *l1pt, pte_t *l1pt_boot,
22                     pte_t *l2pt)
23 {
24         static_assert(KERNBASE % L1PGSIZE == 0);
25         // The boot L1 PT retains the identity mapping [0,memsize-1],
26         // whereas the post-boot L1 PT does not.
27         uint64_t memsize = mem_size(memsize_mb);
28
29         for (uint64_t pa = 0; pa < memsize + L1PGSIZE - 1; pa += L1PGSIZE) {
30                 pte_t pte = build_pte(pa, PTE_KERN_RW | PTE_E);
31
32                 l1pt_boot[L1X(pa)] = pte;            // identity mapping
33                 l1pt_boot[L1X(KERNBASE + pa)] = pte; // KERNBASE mapping
34                 l1pt[L1X(KERNBASE + pa)] = pte;      // KERNBASE mapping
35         }
36
37 #ifdef __riscv64
38         // The kernel code and static data actually are usually not accessed
39         // via the KERNBASE mapping, but rather by an aliased "load" mapping in
40         // the upper 2GB (0xFFFFFFFF80000000 and up).
41         // This simplifies the linking model by making all static addresses
42         // representable in 32 bits.
43         static_assert(L1X(KERN_LOAD_ADDR) > L1X(KERNBASE));
44         static_assert(KERN_LOAD_ADDR % L2PGSIZE == 0);
45         static_assert((uintptr_t)(-KERN_LOAD_ADDR) <= L1PGSIZE);
46
47         l1pt[L1X(KERN_LOAD_ADDR)] = PTD(l2pt);
48         l1pt_boot[L1X(KERN_LOAD_ADDR)] = PTD(l2pt);
49
50         for (uintptr_t pa = 0; pa < (uintptr_t)(-KERN_LOAD_ADDR);
51              pa += L2PGSIZE)
52                 l2pt[L2X(KERN_LOAD_ADDR + pa)] =
53                     build_pte(pa, PTE_KERN_RW | PTE_E);
54 #else
55         (void)l2pt; // don't need this for rv32
56 #endif
57 }
58
59 void cmain(uint32_t memsize_mb, uint32_t nc)
60 {
61         multiboot_info_t mbi;
62         memset(&mbi, 0, sizeof(mbi));
63         mbi.flags = 0x00000001;
64         mbi.mem_lower = mem_size(memsize_mb) / 1024;
65
66         num_cores = nc;
67
68         extern void kernel_init(multiboot_info_t * mboot_info);
69
70         // kernel_init expects a pre-relocation mbi address
71         kernel_init((multiboot_info_t *)PADDR(&mbi));
72 }