Fix incorrect test for whether multiboot info has a memory map.
[akaros.git] / kern / src / multiboot.c
index f6e937f..0ededc9 100644 (file)
+/* Copyright (c) 2009,13 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * Kevin Klues <klueska@cs.berkeley.edu>
+ * See LICENSE for details. 
+ *
+ * Multiboot parsing and helper functions. */
+
 #include <multiboot.h>
-#include <arch/types.h>
+#include <ros/common.h>
 #include <arch/mmu.h>
 #include <arch/arch.h>
 #include <ros/memlayout.h>
 #include <stdio.h>
+#include <pmap.h>
 
-#ifdef __i386__
+#ifdef CONFIG_X86
 #include <arch/apic.h>
 #endif
 
-// These variables are set by i386_detect_memory()
-physaddr_t maxpa;      // Maximum physical address in the system
-physaddr_t maxaddrpa;  // Maximum addressable physical address
-void *SNT maxaddrpa_ptr;
-size_t npages;         // Total number of physical memory pages
-size_t naddrpages;       // Number of addressable physical memory pages
-
-static size_t basemem;  // Amount of base memory (in bytes)
-static size_t extmem;   // Amount of extended memory (in bytes)
-
-void
-multiboot_detect_memory(multiboot_info_t *mbi)
+/* Misc dead code to read from mboot.  We'll need to do this to run a legit
+ * initrd from grub (module /initramfs.cpio, or whatever). */
+static void mboot_parsing(struct multiboot_info *mbi)
 {
-       // Tells us how many kilobytes there are
-       basemem = ROUNDDOWN(mbi->mem_lower*1024, PGSIZE);
-       extmem = ROUNDDOWN(mbi->mem_upper*1024, PGSIZE);
-
-       // Calculate the maximum physical address based on whether
-       // or not there is any extended memory.  See comment in <inc/memlayout.h>
-       if (extmem)
-               maxpa = EXTPHYSMEM + extmem;
-       else
-               maxpa = basemem;
-
-       npages = maxpa / PGSIZE;
-
-       // IOAPIC - KERNBASE is the max amount of virtual addresses we can use
-       // for the physical memory mapping (aka - the KERNBASE mapping)
-       maxaddrpa = MIN(maxpa, IOAPIC_BASE - KERNBASE);
-       maxaddrpa_ptr = (void *SNT)maxaddrpa;
-
-       naddrpages = maxaddrpa / PGSIZE;
-
-       cprintf("Physical memory: %dK available, ", (int)(maxpa/1024));
-       cprintf("base = %dK, extended = %dK\n", (int)(basemem/1024), (int)(extmem/1024));
-       printk("Maximum directly addressable physical memory: %dK\n", (int)(maxaddrpa/1024));
+       if (mbi->flags & MULTIBOOT_INFO_BOOTDEV)
+               printk("MBI: boot_device = 0x%08x\n", mbi->boot_device);
+       if (mbi->flags & MULTIBOOT_INFO_CMDLINE)
+               printk("MBI: command line: %s\n",
+                      (char*)((physaddr_t)mbi->cmdline + KERNBASE));
+       if (mbi->flags & MULTIBOOT_INFO_MODS) {
+               printk("MBI: nr mods, %d: mods addr %p\n", mbi->mods_count,
+                      mbi->mods_addr);
+       }
 }
 
-void
-multiboot_print_memory_map(multiboot_info_t *mbi) {
-       const char *NTS memory_type[] = {"", "FREE", "RESERVED", "UNDEFINED", "UNDEFINED4"};
-
+bool mboot_has_mmaps(struct multiboot_info *mbi)
+{
+       return mbi->flags & MULTIBOOT_INFO_MEM_MAP;
+}
 
-       if(CHECK_FLAG(mbi->flags, 6)) {
-               memory_map_t *SNT mmap_b =
-                       (memory_map_t *SNT)(mbi->mmap_addr + KERNBASE);
-               memory_map_t *SNT mmap_e =
-                       (memory_map_t *SNT)(mbi->mmap_addr + KERNBASE + mbi->mmap_length);
-               memory_map_t *BND(mmap_b, mmap_e) mmap = TC(mmap_b);
+/* This only notices bios detectable memory - there's a lot more in the higher
+ * paddrs. */
+void mboot_detect_memory(struct multiboot_info *mbi)
+{
+       physaddr_t max_bios_mem;
+       physaddr_t max_bios_addr;
+       size_t basemem;
+       size_t extmem;
+       if (!(mbi->flags & MULTIBOOT_INFO_MEMORY)) {
+               printk("No BIOS memory info from multiboot, crash impending!\n");
+               return;
+       }
+       /* mem_lower and upper are measured in KB.  They are 32 bit values, so we're
+        * limited to 4TB total. */
+       basemem = ROUNDDOWN((size_t)mbi->mem_lower * 1024, PGSIZE);
+       /* On 32 bit, This shift << 10 could cause us to lose some memory, but we
+        * weren't going to access it anyways (won't go beyond ~1GB) */
+       extmem = ROUNDDOWN((size_t)mbi->mem_upper * 1024, PGSIZE);
+       /* Calculate the maximum physical address based on whether or not there is
+        * any extended memory. */
+       if (extmem) {
+               max_bios_mem = EXTPHYSMEM + extmem;
+               /* On 32 bit, if we had enough RAM that adding a little wrapped us
+                * around, we'll back off a little and run with just extmem amount (in
+                * essence, subtracing 1MB). */
+               if (max_bios_mem < extmem)
+                       max_bios_mem = extmem;
+       } else {
+               max_bios_mem = basemem;
+       }
+       max_bios_addr = MIN(max_bios_mem, KERN_VMAP_TOP - KERNBASE);
+       printk("Base memory: %luK, Extended memory: %luK\n", basemem / 1024,
+              extmem / 1024);
+       printk("Maximum directly addressable base and extended memory: %luK\n",
+              max_bios_addr / 1024);
+       /* Take a first stab at the max pmem, in case there are no memory mappings
+        * (like in riscv) */
+       max_pmem = max_bios_mem;
+}
 
-               cprintf ("mmap_addr = 0x%x, mmap_length = 0x%x\n", (unsigned long)mbi->mmap_addr,
-                          (unsigned long)mbi->mmap_length);
+void mboot_foreach_mmap(struct multiboot_info *mbi, mboot_foreach_t func,
+                        void *data)
+{
+       struct multiboot_mmap_entry *mmap_b, *mmap_e, *mmap_i;
+       if (!mboot_has_mmaps(mbi)) {
+               printd("No memory mapping info from multiboot\n");
+               return;
+       }
+       mmap_b = (struct multiboot_mmap_entry*)((size_t)mbi->mmap_addr + KERNBASE);
+       mmap_e = (struct multiboot_mmap_entry*)((size_t)mbi->mmap_addr + KERNBASE
+                                          + mbi->mmap_length);
+       printd("mmap_addr = %p, mmap_length = %p\n", mbi->mmap_addr,
+              mbi->mmap_length);
+       /* Note when we incremement mmap_i, we add in the value of size... */
+       for (mmap_i = mmap_b;
+            mmap_i < mmap_e;
+            mmap_i = (struct multiboot_mmap_entry*)((void*)mmap_i + mmap_i->size
+                                                    + sizeof(mmap_i->size))) {
+               func(mmap_i, data);
+       }
+}
 
-               while(mmap < mmap_e) {
-                       cprintf ("base = 0x%08x%08x, length = 0x%08x%08x, type = %s\n",
-                               (unsigned) mmap->base_addr_high,
-                               (unsigned) mmap->base_addr_low,
-                               (unsigned) mmap->length_high,
-                               (unsigned) mmap->length_low,
-                               (unsigned) memory_type[mmap->type]);
-                       mmap = (memory_map_t *BND(mmap_b,mmap_e))((char *BND(mmap_b,mmap_e))mmap + mmap->size + sizeof(mmap->size));
-               }
+void mboot_print_mmap(struct multiboot_info *mbi)
+{
+       void print_entry(struct multiboot_mmap_entry *entry, void *data)
+       {
+               printk("Base = 0x%016llx, Length = 0x%016llx : %s\n",
+                      entry->addr, entry->len,
+                      entry->type == MULTIBOOT_MEMORY_AVAILABLE ? "FREE" :
+                                                                  "RESERVED");
        }
+       mboot_foreach_mmap(mbi, print_entry, 0);
 }
 
+/* Given a range of memory, will tell us if multiboot is using anything we care
+ * about in that range.  It usually uses memory below 1MB, so boot_alloc is
+ * fine.  This is pre, so MBI is still a paddr. */
+bool mboot_region_collides(struct multiboot_info *mbi, uintptr_t base,
+                           uintptr_t end)
+{
+       if (regions_collide_unsafe((uintptr_t)mbi,
+                                  (uintptr_t)mbi + sizeof(struct multiboot_info),
+                                  base, end))
+               return TRUE;
+       if ((mbi->flags & MULTIBOOT_INFO_ELF_SHDR)) {
+               if (regions_collide_unsafe((uintptr_t)mbi->mmap_addr + KERNBASE,
+                                          (uintptr_t)mbi->mmap_addr + KERNBASE
+                                                                    + mbi->mmap_length,
+                                          base, end))
+                       return TRUE;
+       }
+       return FALSE;
+}