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