net: Use NULL to signal lack of promisc/multicast
[akaros.git] / kern / arch / riscv / cboot.c
index fce5190..cd6717b 100644 (file)
@@ -7,94 +7,64 @@
 #include <stdio.h>
 #include <pmap.h>
 
-static void
-build_multiboot_info(multiboot_info_t* mbi)
-{
-       long memsize_kb = mfpcr(PCR_MEMSIZE)*(PGSIZE/1024);
-       long basemem_kb = EXTPHYSMEM/1024;
+#define MAX_KERNBASE_SIZE (KERN_VMAP_TOP - KERNBASE)
 
-       memset(mbi, 0, sizeof(mbi));
+uint32_t num_cores = 1;   // this must not be in BSS
 
-       mbi->flags = 0x00000001;
-       mbi->mem_lower = basemem_kb;
-       mbi->mem_upper = memsize_kb - basemem_kb;
+static uint64_t
+mem_size(uint64_t sz_mb)
+{
+       uint64_t sz = (uint64_t)sz_mb * 1024 * 1024;
+       return MIN(sz,  MIN(MAX_KERNBASE_SIZE, (uint64_t)L1PGSIZE * NPTENTRIES));
 }
 
-#define KERNSIZE ((uintptr_t)(-KERNBASE))
-
-pte_t l1pt_boot[NPTENTRIES]
-      __attribute__((section(".data"))) __attribute__((aligned(PGSIZE)));
-pte_t l1pt[NPTENTRIES]
-      __attribute__((section(".data"))) __attribute__((aligned(PGSIZE)));
-#ifdef __riscv64
-pte_t l2pt[NPTENTRIES]
-      __attribute__((section(".data"))) __attribute__((aligned(PGSIZE)));
-#endif
-
-#ifdef __riscv64
-void pagetable_init(pte_t* l1pt_phys, pte_t* l1pt_boot_phys, pte_t* l2pt_phys)
-#else
-void pagetable_init(pte_t* l1pt_phys, pte_t* l1pt_boot_phys)
-#endif
+void pagetable_init(uint32_t memsize_mb, pte_t* l1pt, pte_t* l1pt_boot,
+                    pte_t* l2pt)
 {
-       // The boot L1 PT retains the identity mapping [0,KERNSIZE-1],
+       static_assert(KERNBASE % L1PGSIZE == 0);
+       // The boot L1 PT retains the identity mapping [0,memsize-1],
        // whereas the post-boot L1 PT does not.
-       for(uintptr_t va = 0; va < KERNSIZE+L1PGSIZE-1; va += L1PGSIZE)
-               l1pt_boot_phys[L1X(va)] = PTE(LA2PPN(va), PTE_KERN_RW | PTE_E);
-
-       #ifdef __riscv64
-       // for rv64, we need to create an L1 and an L2 PT.
-       
-       // kernel can be mapped by a single L1 page and several L2 pages
-       static_assert(KERNSIZE <= L1PGSIZE);
-       static_assert(KERNBASE % L2PGSIZE == 0);
-
-       // highest L1 page contains KERNBASE mapping
-       l1pt_phys[L1X(KERNBASE)] = l1pt_boot_phys[L1X(KERNBASE)] = PTD(l2pt_phys);
+       uint64_t memsize = mem_size(memsize_mb);
+       for(uint64_t pa = 0; pa < memsize+L1PGSIZE-1; pa += L1PGSIZE)
+       {
+               pte_t pte = build_pte(pa, PTE_KERN_RW | PTE_E);
 
-       // KERNBASE mapping with 1GB pages
-       for(uintptr_t va = KERNBASE; va < LOAD_ADDR; va += L2PGSIZE)
-               l2pt_phys[L2X(va)] = PTE(LA2PPN(va-KERNBASE), PTE_KERN_RW | PTE_E);
+               l1pt_boot[L1X(pa)] = pte; // identity mapping
+               l1pt_boot[L1X(KERNBASE+pa)] = pte; // KERNBASE mapping
+               l1pt[L1X(KERNBASE+pa)] = pte; // KERNBASE mapping
+       }
 
+#ifdef __riscv64
        // The kernel code and static data actually are usually not accessed
-       // via the KERNBASE mapping, but rather by an aliased mapping in the
-       // upper 2GB (0xFFFFFFFF80000000 and up).
+       // via the KERNBASE mapping, but rather by an aliased "load" mapping in
+       // the upper 2GB (0xFFFFFFFF80000000 and up).
        // This simplifies the linking model by making all static addresses
        // representable in 32 bits.
-       // In RISC-V, this allows static addresses to be loaded with a two
-       // instruction sequence, rather than 8 instructions worst-case.
-       static_assert(LOAD_ADDR % L2PGSIZE == 0);
-       for(uintptr_t va = LOAD_ADDR; va != 0; va += L2PGSIZE)
-               l2pt_phys[L2X(va)] = PTE(LA2PPN(va-LOAD_ADDR), PTE_KERN_RW|PTE_E);
-       #else
-       // for rv32, just create the L1 page table.
-       static_assert(KERNBASE % L1PGSIZE == 0);
+       static_assert(L1X(KERN_LOAD_ADDR) > L1X(KERNBASE));
+       static_assert(KERN_LOAD_ADDR % L2PGSIZE == 0);
+       static_assert((uintptr_t)(-KERN_LOAD_ADDR) <= L1PGSIZE);
 
-       // KERNBASE mapping
-       for(uintptr_t pa = 0; pa < KERNSIZE; pa += L1PGSIZE)
-       {
-               pte_t pte = PTE(LA2PPN(pa), PTE_KERN_RW|PTE_E);
-               l1pt_phys[L1X(KERNBASE+pa)] = pte;
-               l1pt_boot_phys[L1X(KERNBASE+pa)] = pte;
-       }
-       #endif
-}
+       l1pt[L1X(KERN_LOAD_ADDR)] = PTD(l2pt);
+       l1pt_boot[L1X(KERN_LOAD_ADDR)] = PTD(l2pt);
 
-void
-mmu_init(pte_t* l1pt_boot_phys)
-{
-       // load in the boot page table
-       lcr3((uintptr_t)l1pt_boot_phys);
-       mtpcr(PCR_SR, mfpcr(PCR_SR) | SR_VM);
+       for (uintptr_t pa = 0; pa < (uintptr_t)(-KERN_LOAD_ADDR); pa += L2PGSIZE)
+               l2pt[L2X(KERN_LOAD_ADDR+pa)] = build_pte(pa, PTE_KERN_RW | PTE_E);
+#else
+       (void) l2pt; // don't need this for rv32
+#endif
 }
 
 void
-cmain()
+cmain(uint32_t memsize_mb, uint32_t nc)
 {
        multiboot_info_t mbi;
-       build_multiboot_info(&mbi);
+       memset(&mbi, 0, sizeof(mbi));
+       mbi.flags = 0x00000001;
+       mbi.mem_lower = mem_size(memsize_mb) / 1024;
+
+       num_cores = nc;
 
        extern void kernel_init(multiboot_info_t *mboot_info);
        // kernel_init expects a pre-relocation mbi address
-       kernel_init((multiboot_info_t*)((uint8_t*)&mbi - LOAD_ADDR));
+       kernel_init((multiboot_info_t*)PADDR(&mbi));
 }