// Copyright 2017 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 "object/bus_transaction_initiator_dispatcher.h"

#include <err.h>
#include <lib/counters.h>
#include <zircon/rights.h>

#include <new>

#include <dev/iommu.h>
#include <vm/pinned_vm_object.h>
#include <vm/vm_object.h>

KCOUNTER(dispatcher_bti_create_count, "dispatcher.bti.create")
KCOUNTER(dispatcher_bti_destroy_count, "dispatcher.bti.destroy")

zx_status_t BusTransactionInitiatorDispatcher::Create(
    fbl::RefPtr<Iommu> iommu, uint64_t bti_id,
    KernelHandle<BusTransactionInitiatorDispatcher>* handle, zx_rights_t* rights) {
  if (!iommu->IsValidBusTxnId(bti_id)) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::AllocChecker ac;
  KernelHandle new_handle(
      fbl::AdoptRef(new (&ac) BusTransactionInitiatorDispatcher(ktl::move(iommu), bti_id)));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

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

BusTransactionInitiatorDispatcher::BusTransactionInitiatorDispatcher(fbl::RefPtr<Iommu> iommu,
                                                                     uint64_t bti_id)
    : iommu_(ktl::move(iommu)), bti_id_(bti_id), zero_handles_(false) {
  kcounter_add(dispatcher_bti_create_count, 1);
}

BusTransactionInitiatorDispatcher::~BusTransactionInitiatorDispatcher() {
  DEBUG_ASSERT(pinned_memory_.is_empty());
  kcounter_add(dispatcher_bti_destroy_count, 1);
}

zx_status_t BusTransactionInitiatorDispatcher::Pin(
    fbl::RefPtr<VmObject> vmo, uint64_t offset, uint64_t size, uint32_t perms,
    KernelHandle<PinnedMemoryTokenDispatcher>* pmt_handle, zx_rights_t* pmt_rights) {
  DEBUG_ASSERT(IS_PAGE_ALIGNED(offset));
  DEBUG_ASSERT(IS_PAGE_ALIGNED(size));

  if (size == 0) {
    return ZX_ERR_INVALID_ARGS;
  }

  PinnedVmObject pinned_vmo;
  zx_status_t status = PinnedVmObject::Create(vmo, offset, size, &pinned_vmo);
  if (status != ZX_OK) {
    return status;
  }

  Guard<fbl::Mutex> guard{get_lock()};
  if (zero_handles_) {
    return ZX_ERR_BAD_STATE;
  }

  return PinnedMemoryTokenDispatcher::Create(fbl::WrapRefPtr(this), ktl::move(pinned_vmo), perms,
                                             pmt_handle, pmt_rights);
}

void BusTransactionInitiatorDispatcher::ReleaseQuarantine() {
  QuarantineList tmp;

  // The PMT dtor will call RemovePmo, which will reacquire this BTI's lock.
  // To avoid deadlock, drop the lock before letting the quarantined PMTs go.
  {
    Guard<fbl::Mutex> guard{get_lock()};
    quarantine_.swap(tmp);
  }
}

void BusTransactionInitiatorDispatcher::on_zero_handles() {
  Guard<fbl::Mutex> guard{get_lock()};
  // Prevent new pinning from happening.  The Dispatcher will stick around
  // until all of the PMTs are closed.
  zero_handles_ = true;

  // Do not clear out the quarantine list.  PMTs hold a reference to the BTI
  // and the BTI holds a reference to each quarantined PMT.  We intentionally
  // leak the BTI, all quarantined PMTs, and their underlying VMOs.  We could
  // get away with freeing the BTI and the PMTs, but for safety we must leak
  // at least the pinned parts of the VMOs, since we have no assurance that
  // hardware is not still reading/writing to it.
  if (!quarantine_.is_empty()) {
    PrintQuarantineWarningLocked();
  }
}

void BusTransactionInitiatorDispatcher::AddPmoLocked(PinnedMemoryTokenDispatcher* pmt) {
  DEBUG_ASSERT(!pmt->dll_pmt_.InContainer());
  pinned_memory_.push_back(pmt);
}

void BusTransactionInitiatorDispatcher::RemovePmo(PinnedMemoryTokenDispatcher* pmt) {
  Guard<fbl::Mutex> guard{get_lock()};
  DEBUG_ASSERT(pmt->dll_pmt_.InContainer());
  pinned_memory_.erase(*pmt);
}

void BusTransactionInitiatorDispatcher::Quarantine(fbl::RefPtr<PinnedMemoryTokenDispatcher> pmt) {
  Guard<fbl::Mutex> guard{get_lock()};

  DEBUG_ASSERT(pmt->dll_pmt_.InContainer());
  quarantine_.push_back(ktl::move(pmt));

  if (zero_handles_) {
    // If we quarantine when at zero handles, this PMT will be leaked.  See
    // the comment in on_zero_handles().
    PrintQuarantineWarningLocked();
  }
}

void BusTransactionInitiatorDispatcher::PrintQuarantineWarningLocked() {
  uint64_t leaked_pages = 0;
  size_t num_entries = 0;
  for (const auto& pmt : quarantine_) {
    leaked_pages += pmt.size() / PAGE_SIZE;
    num_entries++;
  }
  printf("Bus Transaction Initiator 0x%lx has leaked %" PRIu64 " pages in %zu VMOs\n", bti_id_,
         leaked_pages, num_entries);
}
