// Copyright 2018 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <inttypes.h>
#include <sys/types.h>

#include <fbl/algorithm.h>
#include <fbl/function.h>
#include <trace.h>
#include <vm/bootreserve.h>
#include <vm/pmm.h>

#include "vm_priv.h"


#define LOCAL_TRACE MAX(VM_GLOBAL_TRACE, 0)

static const size_t NUM_RESERVES = 16;
static reserve_range_t res[NUM_RESERVES];
static size_t res_idx;

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) {
        panic("too many boot reservations\n");
    }

    // insert into the list, sorted
    paddr_t end = pa + len - 1;
    DEBUG_ASSERT(end > pa);
    for (size_t i = 0; i < res_idx; i++) {
        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);
        }

        if (res[i].pa > end) {
            // insert before this one
            memmove(&res[i + 1], &res[i], (res_idx - i) * sizeof(res[0]));
            res[i].pa = pa;
            res[i].len = len;
            res_idx++;
            return ZX_OK;
        }
    }

    // insert it at the end
    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() {
    static list_node reserved_page_list = LIST_INITIAL_VALUE(reserved_page_list);

    for (size_t i = 0; i < res_idx; i++) {
        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;
        zx_status_t status = pmm_alloc_range(res[i].pa, pages, &reserved_page_list);
        if (status != ZX_OK) {
            printf("PMM: unable to reserve reserved range [%#" PRIxPTR ", %#" PRIxPTR "]\n",
                   res[i].pa, res[i].pa + res[i].len - 1);
            continue; // this is probably fatal but go ahead and continue
        }
    }

    // mark all of the pages we allocated as WIRED
    vm_page_t* p;
    list_for_every_entry (&reserved_page_list, p, vm_page_t, queue_node) {
        p->set_state(VM_PAGE_STATE_WIRED);
    }
}

void boot_reserve_unwire_page(struct vm_page* page) {
    DEBUG_ASSERT(page->state() == VM_PAGE_STATE_WIRED);
    page->set_state(VM_PAGE_STATE_ALLOC);
    // Remove from the reserved page list.
    list_delete(&page->queue_node);
}

static paddr_t upper_align(paddr_t range_pa, size_t range_len, size_t len) {
    return (range_pa + range_len - len);
}

zx_status_t boot_reserve_range_search(paddr_t range_pa, size_t range_len, size_t alloc_len,
                                      reserve_range_t* alloc_range) {
    LTRACEF("range pa %#" PRIxPTR " len %#zx alloc_len %#zx\n", range_pa, range_len, alloc_len);

    paddr_t alloc_pa = upper_align(range_pa, range_len, alloc_len);

retry:
    // see if it intersects any reserved range
    LTRACEF("trying alloc range %#" PRIxPTR " len %#zx\n", alloc_pa, alloc_len);
    for (size_t i = 0; i < res_idx; i++) {
        if (Intersects(res[i].pa, res[i].len, alloc_pa, alloc_len)) {
            // it intersects this range, move the search spot back to just before it and try again
            LTRACEF("alloc range %#" PRIxPTR " len %zx intersects with reserve range\n", alloc_pa, alloc_len);
            alloc_pa = res[i].pa - alloc_len;

            LTRACEF("moving and retrying at %#" PRIxPTR "\n", alloc_pa);

            // make sure this still works with our input constraints
            if (alloc_pa < range_pa) {
                LTRACEF("failed to allocate\n");
                return ZX_ERR_NO_MEMORY;
            }

            goto retry;
        }
    }

    // fell off the list without retrying, must have succeeded
    LTRACEF("returning [%#" PRIxPTR ", %#" PRIxPTR "]\n",
            alloc_pa, alloc_pa + alloc_len - 1);

    *alloc_range = {alloc_pa, alloc_len};
    return ZX_OK;
}

// Returns false and exits early if the callback returns false, true otherwise.
bool boot_reserve_foreach(const fbl::Function<bool(const reserve_range_t)>& cb) {
    for (size_t i = 0; i < res_idx; i++) {
        if (!cb(res[i])) {
            return false;
        }
    }

    return true;
}
