// 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 <lib/fzl/owned-vmo-mapper.h>
#include <lib/fzl/resizeable-vmo-mapper.h>
#include <stdio.h>
#include <string.h>

#include <memory>
#include <utility>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>

namespace fzl {

std::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_system_get_page_size());
  zx_status_t status;
  zx_handle_t vmar_handle = vmar_manager_ ? vmar_manager_->vmar().get() : zx_vmar_root_self();

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

  uintptr_t new_start;
  // Create entirely new mapping.
  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
