// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/fzl/resizeable-vmo-mapper.h>
#include <string.h>

#include <utility>

namespace fzl {

fbl::unique_ptr<ResizeableVmoMapper> ResizeableVmoMapper::Create(
        uint64_t size,
        const char* name,
        uint32_t map_options,
        fbl::RefPtr<VmarManager> vmar_manager,
        uint32_t cache_policy) {
    fbl::AllocChecker ac;
    auto ret = fbl::make_unique_checked<ResizeableVmoMapper>(&ac);
    if (!ac.check()) {
        return nullptr;
    }

    zx_status_t res = ret->CreateAndMap(size, name, map_options, vmar_manager, cache_policy);
    if (res != ZX_OK) {
        return nullptr;
    }

    return ret;
}

zx_status_t ResizeableVmoMapper::CreateAndMap(uint64_t size,
                                              const char* name,
                                              zx_vm_option_t map_options,
                                              fbl::RefPtr<VmarManager> vmar_manager,
                                              uint32_t cache_policy) {
    zx::vmo temp;
    zx_status_t res = OwnedVmoMapper::CreateAndMap(size, name, map_options, std::move(vmar_manager),
                                                   cache_policy, ZX_VMO_RESIZABLE);
    if (res == ZX_OK) {
        map_options_ = map_options;
    }

    return res;
}

zx_status_t ResizeableVmoMapper::Map(zx::vmo vmo,
                                     uint64_t size,
                                     zx_vm_option_t map_options,
                                     fbl::RefPtr<VmarManager> vmar_manager) {
    zx_status_t res = OwnedVmoMapper::Map(std::move(vmo), size, map_options,
                                          std::move(vmar_manager));
    if (res == ZX_OK) {
        map_options_ = map_options;
    }

    return res;
}

zx_status_t ResizeableVmoMapper::Shrink(size_t size) {
    if (!vmo().is_valid()) {
        return ZX_ERR_BAD_STATE;
    } else if (size == 0 || size > size_) {
        return ZX_ERR_INVALID_ARGS;
    } else if (size == size_) {
        return ZX_OK;
    }

    zx_status_t status;
    zx_handle_t vmar_handle = vmar_manager_ ? vmar_manager_->vmar().get() : zx_vmar_root_self();

    // Unmap everything after the offset
    if ((status = zx_vmar_unmap(vmar_handle, start_ + size, size_ - size)) != ZX_OK) {
        return status;
    }
    size_ = size;

    if ((status = vmo().op_range(ZX_VMO_OP_DECOMMIT, size, size_ - size,
                                nullptr, 0)) != ZX_OK) {
        // We can tolerate this error; from a client's perspective, the VMO
        // still should appear smaller.
        fprintf(stderr, "ResizeableVmoMapper::Shrink: VMO Decommit failed: %d\n", status);
    }

    return ZX_OK;
}

zx_status_t ResizeableVmoMapper::Grow(size_t size) {
    if (!vmo().is_valid()) {
        return ZX_ERR_BAD_STATE;
    } else if (size < size_) {
        return ZX_ERR_INVALID_ARGS;
    }

    size = fbl::round_up<size_t>(size, ZX_PAGE_SIZE);
    zx_status_t status;

    zx_info_vmar_t vmar_info;
    zx_handle_t vmar_handle = vmar_manager_ ? vmar_manager_->vmar().get() : zx_vmar_root_self();
    if ((status = zx_object_get_info(vmar_handle, ZX_INFO_VMAR,
                                     &vmar_info, sizeof(vmar_info), NULL, NULL)) != ZX_OK) {
        return status;
    }

    if ((status = vmo().set_size(size)) != ZX_OK) {
        return status;
    }

    // Try to extend mapping
    uintptr_t new_start;
    if ((status = zx_vmar_map(vmar_handle,
                              map_options_ | ZX_VM_FLAG_SPECIFIC,
                              start_ + size_ - vmar_info.base,
                              vmo().get(),
                              size_,
                              size - size_,
                              &new_start)) != ZX_OK) {
        // If extension fails, create entirely new mapping and unmap the old one
        if ((status = zx_vmar_map(vmar_handle, map_options_, 0,
                                  vmo().get(), 0, size, &new_start)) != ZX_OK) {

            // If we could not extend the old mapping, and we cannot create a
            // new mapping, then we are done.  Attempt to shrink the VMO back to
            // its original size.  This operation should *never* fail.  If it
            // does, something has gone very wrong and it is time to terminate
            // this process.
            zx_status_t stat2 = vmo().set_size(size_);
            ZX_ASSERT_MSG(stat2 == ZX_OK,
                          "Failed to shrink to original size (0x%zx -> 0x%lx : res %d)\n",
                          size, this->size(), stat2);
            return status;
        }

        // Now that we have a new mapping, unmap our original mapping.  Once
        // again, this should *never* fail.  Hard assert that this is the case.
        status = zx_vmar_unmap(vmar_handle, start_, size_);
        ZX_ASSERT_MSG(status == ZX_OK,
                      "Failed to destroy original mapping ([%p, len 0x%lx] : res %d\n",
                      start(), this->size(), status);

        start_ = new_start;
    }

    size_ = size;
    return ZX_OK;
}

} // namespace fzl
