akaros/kern/arch/riscv/cboot.c
<<
>>
Prefs
   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
  12uint32_t num_cores = 1; // this must not be in BSS
  13
  14static 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
  21void 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
  59void 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}
  73