WIP more boot reservation stuff

Change-Id: I500a237bbf509a5663789d1ce13298d6f0fa6ffd
diff --git a/kernel/platform/generic-arm/platform.cpp b/kernel/platform/generic-arm/platform.cpp
index 5fa9a2a..d3a5cd0 100644
--- a/kernel/platform/generic-arm/platform.cpp
+++ b/kernel/platform/generic-arm/platform.cpp
@@ -37,6 +37,7 @@
 #include <arch/mp.h>
 
 #include <vm/vm_aspace.h>
+#include <vm/bootreserve.h>
 
 #include <lib/console.h>
 #include <lib/memory_limit.h>
@@ -74,10 +75,6 @@
     uint64_t length;
 };
 
-// save a list of reserved bootloader regions
-const size_t MAX_BOOT_RESERVE_BANKS = 8;
-static mem_bank boot_reserve_banks[MAX_BOOT_RESERVE_BANKS];
-
 // save a list of peripheral memory banks
 const size_t MAX_PERIPH_BANKS = 4;
 static mem_bank periph_banks[MAX_PERIPH_BANKS];
@@ -209,28 +206,6 @@
     }
 }
 
-static void platform_preserve_ramdisk(void) {
-    if (!ramdisk_start_phys || !ramdisk_end_phys) {
-        return;
-    }
-
-    dprintf(INFO, "reserving ramdisk phys range [%#" PRIx64 ", %#" PRIx64 "]\n",
-            ramdisk_start_phys, ramdisk_end_phys - 1);
-
-    struct list_node list = LIST_INITIAL_VALUE(list);
-    size_t pages = (ramdisk_end_phys - ramdisk_start_phys + PAGE_SIZE - 1) / PAGE_SIZE;
-    size_t actual = pmm_alloc_range(ramdisk_start_phys, pages, &list);
-    if (actual != pages) {
-        panic("unable to reserve ramdisk memory range\n");
-    }
-
-    // mark all of the pages we allocated as WIRED
-    vm_page_t* p;
-    list_for_every_entry (&list, p, vm_page_t, free.node) {
-        p->state = VM_PAGE_STATE_WIRED;
-    }
-}
-
 void* platform_get_ramdisk(size_t* size) {
     if (ramdisk_base) {
         *size = ramdisk_size;
@@ -477,9 +452,8 @@
         process_mdi_banks(mem_map, [](const auto& b) {
             dprintf(INFO, "boot reserve mem range %zu: phys base %#" PRIx64 " virt base %#" PRIx64 " length %#" PRIx64 "\n",
                     b.num, b.base_phys, b.base_virt, b.length);
-            // only can handle so many reserve banks
-            ASSERT(b.num < fbl::count_of(boot_reserve_banks));
-            boot_reserve_banks[b.num] = b;
+
+            boot_reserve_add_range(b.base_phys, b.length);
         });
     }
     if (mdi_find_node(&root, MDI_PERIPH_MEM_MAP, &mem_map) == ZX_OK) {
@@ -562,6 +536,9 @@
         panic("no bootdata structure!\n");
     }
 
+    // initialize the boot memory reservation system
+    boot_reserve_init();
+
     // The previous environment passes us a boot structure. It may be a
     // device tree or a bootdata container. We attempt to detect the type of the
     // container and handle it appropriately.
@@ -591,6 +568,12 @@
         panic("no ramdisk!\n");
     }
 
+    // add the ramdisk to the boot reserve memory list
+    dprintf(INFO, "reserving ramdisk phys range [%#" PRIx64 ", %#" PRIx64 "]\n",
+            ramdisk_start_phys, ramdisk_end_phys - 1);
+
+    boot_reserve_add_range(ramdisk_start_phys, ramdisk_size);
+
     process_bootdata(reinterpret_cast<bootdata_t*>(ramdisk_base));
     // Read cmdline after processing bootdata, which may contain cmdline data.
     halt_on_panic = cmdline_get_bool("kernel.halt-on-panic", false);
@@ -622,17 +605,8 @@
         pmm_add_arena(&mem_arena);
     }
 
-    // Allocate memory regions reserved by bootloaders for other functions
-    for (const auto& b : boot_reserve_banks) {
-        if (b.length == 0)
-            break;
-
-        dprintf(INFO, "reserving phys range [%#" PRIx64 ", %#" PRIx64 "]\n",
-                b.base_phys, b.base_phys + b.length - 1);
-        pmm_alloc_range(b.base_phys, b.length / PAGE_SIZE, nullptr);
-    }
-
-    platform_preserve_ramdisk();
+    // tell the boot allocator to mark ranges we've reserved as off limits
+    boot_reserve_wire();
 }
 
 void platform_init(void) {
diff --git a/kernel/platform/pc/platform.cpp b/kernel/platform/pc/platform.cpp
index e3b0db4..7e0e36a 100644
--- a/kernel/platform/pc/platform.cpp
+++ b/kernel/platform/pc/platform.cpp
@@ -784,15 +784,12 @@
     platform_save_bootloader_data(true);
 #endif
 
+    /* initialize the boot memory reservation system */
+    boot_reserve_init();
+
     /* add the ramdisk to the boot reserve list */
     platform_preserve_ramdisk();
 
-    // XXX test case
-    //boot_reserve_add_range(0x17f000000UL, 0x1000);
-    //boot_reserve_add_range(0x17f004000UL, 0x1000);
-    //boot_reserve_add_range(0x17e008000UL, 0x4000);
-    //boot_reserve_add_range(0x100000000UL, 0x7e000000UL);
-
     /* initialize physical memory arenas */
     pc_mem_init();
 
diff --git a/kernel/vm/bootreserve.cpp b/kernel/vm/bootreserve.cpp
index d497366..eb80860 100644
--- a/kernel/vm/bootreserve.cpp
+++ b/kernel/vm/bootreserve.cpp
@@ -8,19 +8,23 @@
 
 #include "vm_priv.h"
 
-#include <lk/init.h>
 #include <sys/types.h>
-#include <vm/pmm.h>
 #include <trace.h>
+#include <vm/pmm.h>
 
-#define LOCAL_TRACE MAX(VM_GLOBAL_TRACE, 1)
+#define LOCAL_TRACE MAX(VM_GLOBAL_TRACE, 0)
 
 static const size_t NUM_RESERVES = 16;
 static reserve_range res[NUM_RESERVES];
 static size_t res_idx;
 static list_node reserved_page_list = LIST_INITIAL_VALUE(reserved_page_list);
 
-void boot_reserve_add_range(paddr_t pa, size_t len) {
+void boot_reserve_init() {
+    /* add the kernel to the boot reserve list */
+    boot_reserve_add_range(get_kernel_base_phys(), get_kernel_size());
+}
+
+zx_status_t boot_reserve_add_range(paddr_t pa, size_t len) {
     dprintf(INFO, "PMM: boot reserve add [%#" PRIxPTR ", %#" PRIxPTR "]\n", pa, pa + len - 1);
 
     if (res_idx == NUM_RESERVES) {
@@ -33,16 +37,16 @@
         if (Intersects(res[i].pa, res[i].len, pa, len)) {
             // we have a problem that we are not equipped to handle right now
             panic("boot_reserve_add_range: pa %#" PRIxPTR " len %zx intersects existing range\n",
-                   pa, len);
+                  pa, len);
         }
 
         if (res[i].pa > end) {
             // insert before this one
-            memmove(&res[i+1], &res[i], (res_idx - i) * sizeof(res[0]));
+            memmove(&res[i + 1], &res[i], (res_idx - i) * sizeof(res[0]));
             res[i].pa = pa;
             res[i].len = len;
             res_idx++;
-            return;
+            return ZX_OK;
         }
     }
 
@@ -50,19 +54,20 @@
     res[res_idx].pa = pa;
     res[res_idx].len = len;
     res_idx++;
+    return ZX_OK;
 }
 
 // iterate through the reserved ranges and mark them as WIRED in the pmm
 void boot_reserve_wire() {
     for (size_t i = 0; i < res_idx; i++) {
-        dprintf(INFO, "PMM: boot reserve reserving [%#" PRIxPTR ", %#" PRIxPTR "]\n",
+        dprintf(INFO, "PMM: boot reserve marking WIRED [%#" PRIxPTR ", %#" PRIxPTR "]\n",
                 res[i].pa, res[i].pa + res[i].len - 1);
 
         size_t pages = ROUNDUP_PAGE_SIZE(res[i].len) / PAGE_SIZE;
         size_t actual = pmm_alloc_range(res[i].pa, pages, &reserved_page_list);
         if (actual != pages) {
             printf("PMM: unable to reserve reserved range [%#" PRIxPTR ", %#" PRIxPTR "]\n",
-                res[i].pa, res[i].pa + res[i].len - 1);
+                   res[i].pa, res[i].pa + res[i].len - 1);
             continue; // this is probably fatal but go ahead and continue
         }
     }
@@ -107,16 +112,9 @@
     LTRACEF("returning [%#" PRIxPTR ", %#" PRIxPTR "]\n",
             alloc_pa, alloc_pa + alloc_len - 1);
 
-    return { alloc_pa, alloc_len };
+    return {alloc_pa, alloc_len};
 
 fail:
     LTRACEF("failed to allocate\n");
-    return { 0, 0 };
+    return {0, 0};
 }
-
-static void boot_reserve_init(uint level) {
-    /* add the kernel to the boot reserve list */
-    boot_reserve_add_range(get_kernel_base_phys(), get_kernel_size());
-}
-
-LK_INIT_HOOK(boot_reserve, boot_reserve_init, LK_INIT_LEVEL_PLATFORM_EARLY - 1);
diff --git a/kernel/vm/include/vm/bootreserve.h b/kernel/vm/include/vm/bootreserve.h
index 7effaef..8651e51 100644
--- a/kernel/vm/include/vm/bootreserve.h
+++ b/kernel/vm/include/vm/bootreserve.h
@@ -6,19 +6,32 @@
 
 #pragma once
 
-#include <zircon/compiler.h>
 #include <sys/types.h>
+#include <zircon/types.h>
 
-void boot_reserve_add_range(paddr_t pa, size_t len);
+// The boot memory reservation system is a one-use early boot mechanism for
+// a platform to mark certain ranges of physical space as occupied by something
+// prior to adding arenas to the PMM.
+//
+// boot_reserve_init() must be called before adding the first pmm arena and
+// boot_reserve_wire() should be called after the last arena is added to mark
+// pages the reserved ranges intersect as WIRED.
+//
+// As the PMM arenas are added, the boot reserved ranges are consulted to make
+// sure the pmm data structures do not overlap with any reserved ranges.
 
+void boot_reserve_init();
 void boot_reserve_wire();
 
-// given a range, find a non intersection region with any reserved area
-// returns upper aligned
+zx_status_t boot_reserve_add_range(paddr_t pa, size_t len);
+
 struct reserve_range {
     paddr_t pa;
     size_t len;
 };
 
+// Given a range, find a non intersection region with any reserved area
+// returns upper aligned.
+// On failure, return range.len == 0.
+// Used by the PMM arena initialization code to allocate memory for itself.
 reserve_range boot_reserve_range_search(paddr_t range_pa, size_t range_len, size_t alloc_len);
-