// 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 <lib/counters.h>
#include <trace.h>
#include <zircon/syscalls-next.h>

#include <kernel/thread.h>
#include <object/pager_dispatcher.h>
#include <object/pager_proxy.h>
#include <object/thread_dispatcher.h>

#define LOCAL_TRACE 0

KCOUNTER(dispatcher_pager_create_count, "dispatcher.pager.create")
KCOUNTER(dispatcher_pager_destroy_count, "dispatcher.pager.destroy")

zx_status_t PagerDispatcher::Create(KernelHandle<PagerDispatcher>* handle, zx_rights_t* rights) {
  fbl::AllocChecker ac;
  KernelHandle new_handle(fbl::AdoptRef(new (&ac) PagerDispatcher()));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  *rights = default_rights();
  *handle = ktl::move(new_handle);
  return ZX_OK;
}

PagerDispatcher::PagerDispatcher() : SoloDispatcher() {
  kcounter_add(dispatcher_pager_create_count, 1);
}

PagerDispatcher::~PagerDispatcher() {
  DEBUG_ASSERT(proxies_.is_empty());
  kcounter_add(dispatcher_pager_destroy_count, 1);
}

zx_status_t PagerDispatcher::CreateSource(fbl::RefPtr<PortDispatcher> port, uint64_t key,
                                          uint32_t options, fbl::RefPtr<PageSource>* src_out) {
  Guard<Mutex> guard{&lock_};
  // Make sure on_zero_handles has not been called. This could happen if a call to pager_create_vmo
  // races with closing the last handle, as pager_create_vmo does not hold the handle table lock
  // over this operation.
  if (triggered_zero_handles_) {
    return ZX_ERR_BAD_STATE;
  }

  // Process any options relevant to creation of the PagerProxy.
  uint32_t proxy_options = 0;
  if (options & ZX_VMO_TRAP_DIRTY) {
    proxy_options = PagerProxy::kTrapDirty;
    options &= ~ZX_VMO_TRAP_DIRTY;
  }
  if (options) {
    return ZX_ERR_INVALID_ARGS;
  }

  // We are going to setup two objects that both need to point to each other. As such one of the
  // pointers must be bound 'late' and not in the constructor.
  fbl::AllocChecker ac;
  auto proxy =
      fbl::MakeRefCountedChecked<PagerProxy>(&ac, this, ktl::move(port), key, proxy_options);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  auto src = fbl::MakeRefCountedChecked<PageSource>(&ac, proxy);

  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  // Now that PageSource has been created and has a reference to proxy we must setup expected
  // backlink in proxy. As such there must never be an early return added between here and
  // SetPagerSourceUnchecked.

  // Setting this creates a RefPtr cycle between the PagerProxy and PageSource, however we guarantee
  // we will call proxy->OnDispatcherClose at some point to break the cycle.
  proxy->SetPageSourceUnchecked(src);

  proxies_.push_front(ktl::move(proxy));
  *src_out = ktl::move(src);
  return ZX_OK;
}

fbl::RefPtr<PagerProxy> PagerDispatcher::ReleaseProxy(PagerProxy* proxy) {
  Guard<Mutex> guard{&lock_};
  // proxy might not be in the container since we could be racing with a call to on_zero_handles,
  // but that should only happen if we have triggered_zero_handles_. Note that it is possible for
  // the proxy to still be in the container even if triggered_zero_handles_ is true, as we drop the
  // lock between OnDispatcherClose calls for each proxy in the list, so we might not have gotten to
  // this proxy yet.
  DEBUG_ASSERT_MSG(proxy->InContainer() || triggered_zero_handles_,
                   "triggered_zero_handles_ is %d and proxy is %sin container\n",
                   triggered_zero_handles_, proxy->InContainer() ? "" : "not ");
  return proxy->InContainer() ? proxies_.erase(*proxy) : nullptr;
}

void PagerDispatcher::on_zero_handles() {
  Guard<Mutex> guard{&lock_};
  DEBUG_ASSERT(!triggered_zero_handles_);
  // Set triggered_zero_handles_ to true before starting to release proxies, so that a racy call to
  // PagerDispatcher::ReleaseProxy knows it's not incorrect to not find the proxy in the list.
  triggered_zero_handles_ = true;
  while (!proxies_.is_empty()) {
    fbl::RefPtr<PagerProxy> proxy = proxies_.pop_front();

    // Call unlocked to prevent a double-lock if PagerDispatcher::ReleaseProxy is called,
    // and to preserve the lock order that PagerProxy locks are acquired before the
    // list lock.
    guard.CallUnlocked([proxy = ktl::move(proxy)]() mutable { proxy->OnDispatcherClose(); });
  }
}

zx_status_t PagerDispatcher::RangeOp(uint32_t op, fbl::RefPtr<VmObject> vmo, uint64_t offset,
                                     uint64_t length, uint64_t data) {
  switch (op) {
    case ZX_PAGER_OP_FAIL: {
      auto signed_data = static_cast<int64_t>(data);
      if (signed_data < INT32_MIN || signed_data > INT32_MAX) {
        return ZX_ERR_INVALID_ARGS;
      }
      auto error_status = static_cast<zx_status_t>(data);
      if (!PageSource::IsValidExternalFailureCode(error_status)) {
        return ZX_ERR_INVALID_ARGS;
      }
      return vmo->FailPageRequests(offset, length, error_status);
    }
    case ZX_PAGER_OP_DIRTY: {
      if (data != 0) {
        return ZX_ERR_INVALID_ARGS;
      }
      return vmo->DirtyPages(offset, length);
    }
    case ZX_PAGER_OP_WRITEBACK_BEGIN: {
      if (data != 0 && data != ZX_VMO_DIRTY_RANGE_IS_ZERO) {
        return ZX_ERR_INVALID_ARGS;
      }
      return vmo->WritebackBegin(offset, length, data == ZX_VMO_DIRTY_RANGE_IS_ZERO);
    }
    case ZX_PAGER_OP_WRITEBACK_END: {
      if (data != 0) {
        return ZX_ERR_INVALID_ARGS;
      }
      return vmo->WritebackEnd(offset, length);
    }
    default:
      return ZX_ERR_NOT_SUPPORTED;
  }
}

zx_status_t PagerDispatcher::QueryDirtyRanges(fbl::RefPtr<VmObject> vmo, uint64_t offset,
                                              uint64_t length, user_out_ptr<void> buffer,
                                              size_t buffer_size, user_out_ptr<size_t> actual,
                                              user_out_ptr<size_t> avail) {
  // State captured by |copy_to_buffer| below.
  struct CopyToBufferInfo {
    // Index into |buffer|, used to populate its entries.
    size_t index = 0;
    // Total number of dirty ranges discovered.
    size_t total = 0;
    // Whether the total number of ranges need to be computed, depending on whether |avail| is
    // supplied.
    bool compute_total = false;
    // The range that enumeration runs over. Might get updated when enumeration ends early due to a
    // page fault.
    uint64_t offset = 0;
    uint64_t length = 0;
    // The buffer to copy out ranges to.
    user_out_ptr<zx_vmo_dirty_range_t> buffer = user_out_ptr<zx_vmo_dirty_range_t>(nullptr);
    size_t buffer_size = 0;
    // State that will get populated if the user copy in the DirtyRangeEnumerateFunction encounters
    // a page fault.
    vaddr_t pf_va = 0;
    uint pf_flags = 0;
    bool captured_fault_info = false;
  };
  CopyToBufferInfo info = {};
  info.offset = offset;
  info.length = length;
  info.buffer = buffer.reinterpret<zx_vmo_dirty_range_t>();
  info.buffer_size = buffer_size;
  if (avail) {
    info.compute_total = true;
  }

  // Enumeration function that will be invoked on each dirty range found.
  VmObject::DirtyRangeEnumerateFunction copy_to_buffer =
      [&info](uint64_t range_offset, uint64_t range_len, bool range_is_zero) {
        auto buffer_full = [&info]() {
          return (info.index + 1) * sizeof(zx_vmo_dirty_range_t) > info.buffer_size;
        };
        // No more space in the buffer.
        if (buffer_full()) {
          // If we were not asked to compute the total, we can end termination early as there is
          // nothing more to copy out. Although we would have terminated at the bottom of this loop
          // if out of space, this could be our first iteration and so this check is still needed.
          if (!info.compute_total) {
            DEBUG_ASSERT(info.index == 0);
            return ZX_ERR_STOP;
          }
          // As there is no more space in the |buffer|, only update the total without trying to copy
          // out any more ranges.
          ++info.total;
          return ZX_ERR_NEXT;
        }

        zx_vmo_dirty_range_t dirty_range;
        memset(&dirty_range, 0, sizeof(dirty_range));
        dirty_range.offset = range_offset;
        dirty_range.length = range_len;
        dirty_range.options = range_is_zero ? ZX_VMO_DIRTY_RANGE_IS_ZERO : 0u;

        UserCopyCaptureFaultsResult copy_result =
            info.buffer.element_offset(info.index).copy_to_user_capture_faults(dirty_range);
        // Stash fault information if a fault is encountered. Return early from enumeration with
        // ZX_ERR_SHOULD_WAIT so that the page fault can be resolved.
        if (copy_result.status != ZX_OK) {
          DEBUG_ASSERT(copy_result.fault_info.has_value());
          info.captured_fault_info = true;
          info.pf_va = copy_result.fault_info->pf_va;
          info.pf_flags = copy_result.fault_info->pf_flags;

          // Update the offset and length to skip over the range that we've already processed dirty
          // ranges for, to allow forward progress of the syscall.
          uint64_t processed = range_offset - info.offset;
          info.offset += processed;
          info.length -= processed;

          return ZX_ERR_SHOULD_WAIT;
        }
        // We were able to successfully copy out this dirty range. Advance the index and continue
        // with the enumeration if we need to consider more ranges.
        ++info.index;
        ++info.total;
        if (!info.compute_total && buffer_full()) {
          // No need to compute the total and the buffer is full, so can cease considering
          // additional ranges. This is equivalent to the start the loop, but by doing it here we
          // save the need to calculate the next range before noticing the buffer is full and
          // terminating.
          return ZX_ERR_STOP;
        }
        return ZX_ERR_NEXT;
      };

  // Enumerate dirty ranges with |copy_to_buffer|. If page faults are captured, resolve them and
  // retry enumeration.
  zx_status_t status = ZX_OK;
  do {
    status = vmo->EnumerateDirtyRanges(info.offset, info.length, ktl::move(copy_to_buffer));
    // Per |copy_to_buffer|, enumeration will terminate early with ZX_ERR_SHOULD_WAIT if a fault is
    // captured. Resolve the fault and then attempt the enumeration again.
    if (status == ZX_ERR_SHOULD_WAIT) {
      DEBUG_ASSERT(info.captured_fault_info);
      zx_status_t fault_status = Thread::Current::SoftFault(info.pf_va, info.pf_flags);
      if (fault_status != ZX_OK) {
        return ZX_ERR_INVALID_ARGS;
      }
      // Reset |captured_fault_info| so that a future page fault can set it again.
      info.captured_fault_info = false;
    } else if (status != ZX_OK) {
      // Another error was encountered. Return.
      return status;
    }
  } while (status == ZX_ERR_SHOULD_WAIT);

  DEBUG_ASSERT(status == ZX_OK);

  // Now try to copy out the total and actual number of ranges we populated in |buffer|. We don't
  // need to use copy_to_user_capture_faults() here; we don't hold any locks that need to be dropped
  // before handling a fault.
  if (actual) {
    status = actual.copy_to_user(info.index);
    if (status != ZX_OK) {
      return status;
    }
  }
  if (avail) {
    DEBUG_ASSERT(info.total >= info.index);
    status = avail.copy_to_user(info.total);
  }
  return status;
}

zx_status_t PagerDispatcher::QueryPagerVmoStats(fbl::RefPtr<VmObject> vmo, uint32_t options,
                                                user_out_ptr<void> buffer, size_t buffer_size) {
  if (buffer_size < sizeof(zx_pager_vmo_stats_t)) {
    return ZX_ERR_BUFFER_TOO_SMALL;
  }

  bool reset = options & ZX_PAGER_RESET_VMO_STATS;
  options &= ~ZX_PAGER_RESET_VMO_STATS;
  if (options) {
    return ZX_ERR_INVALID_ARGS;
  }

  zx_pager_vmo_stats_t stats;
  zx_status_t status = vmo->QueryPagerVmoStats(reset, &stats);
  if (status != ZX_OK) {
    return status;
  }

  do {
    UserCopyCaptureFaultsResult copy_result =
        buffer.reinterpret<zx_pager_vmo_stats_t>().copy_to_user_capture_faults(stats);
    if (copy_result.status == ZX_OK) {
      break;
    }
    DEBUG_ASSERT(copy_result.fault_info.has_value());
    zx_status_t fault_status =
        Thread::Current::SoftFault(copy_result.fault_info->pf_va, copy_result.fault_info->pf_flags);
    if (fault_status != ZX_OK) {
      return ZX_ERR_INVALID_ARGS;
    }
  } while (true);

  return ZX_OK;
}
