// 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

#ifndef ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_BUS_TRANSACTION_INITIATOR_DISPATCHER_H_
#define ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_BUS_TRANSACTION_INITIATOR_DISPATCHER_H_

#include <sys/types.h>

#include <dev/iommu.h>
#include <kernel/lockdep.h>
#include <object/dispatcher.h>
#include <object/handle.h>
#include <object/pinned_memory_token_dispatcher.h>

class Iommu;

class BusTransactionInitiatorDispatcher final
    : public SoloDispatcher<BusTransactionInitiatorDispatcher, ZX_DEFAULT_BTI_RIGHTS> {
 public:
  static zx_status_t Create(fbl::RefPtr<Iommu> iommu, uint64_t bti_id,
                            KernelHandle<BusTransactionInitiatorDispatcher>* handle,
                            zx_rights_t* rights);

  ~BusTransactionInitiatorDispatcher() final;
  zx_obj_type_t get_type() const final { return ZX_OBJ_TYPE_BTI; }

  // Pins the given VMO range and returns an PinnedMemoryTokenDispatcher
  // representing the pinned range.
  //
  // |mapped_addrs_count| must be either
  // 1) If |compress_results|, |size|/|minimum_contiguity()|, rounded up, in which
  // case each returned address represents a run of |minimum_contiguity()| bytes (with
  // the exception of the last which may be short)
  // 2) Otherwise, |size|/|PAGE_SIZE|, in which case each returned address represents a
  // single page.
  //
  // Returns ZX_ERR_INVALID_ARGS if |offset| or |size| are not PAGE_SIZE aligned.
  // Returns ZX_ERR_INVALID_ARGS if |perms| is not suitable to pass to the Iommu::Map() interface.
  // Returns ZX_ERR_INVALID_ARGS if |mapped_addrs_count| is not exactly the
  //   value described above.
  zx_status_t Pin(fbl::RefPtr<VmObject> vmo, uint64_t offset, uint64_t size, uint32_t perms,
                  KernelHandle<PinnedMemoryTokenDispatcher>* handle, zx_rights_t* rights);

  // Releases all quarantined PMTs.  The memory pins are released and the VMO
  // references are dropped, so the underlying VMOs may be immediately destroyed, and the
  // underlying physical memory may be reallocated.
  void ReleaseQuarantine();

  void on_zero_handles() final;
  zx_status_t set_name(const char* name, size_t len) final __NONNULL((2));
  void get_name(char out_name[ZX_MAX_NAME_LEN]) const final __NONNULL((2));

  fbl::RefPtr<Iommu> iommu() const { return iommu_; }
  uint64_t bti_id() const { return bti_id_; }

  // Pin will always be able to return addresses that are contiguous for at
  // least this many bytes.  E.g. if this returns 1MB, then a call to Pin()
  // with a size of 2MB will return at most two physically-contiguous runs.  If the size
  // were 2.5MB, it will return at most three physically-contiguous runs.
  uint64_t minimum_contiguity() const { return iommu_->minimum_contiguity(bti_id_); }

  // The number of bytes in the address space (UINT64_MAX if 2^64).
  uint64_t aspace_size() const { return iommu_->aspace_size(bti_id_); }

  // The count of the pinned memory object tokens.
  uint64_t pmo_count() const;

  // The count of the quarantined pinned memory object tokens.
  uint64_t quarantine_count() const;

 protected:
  friend PinnedMemoryTokenDispatcher;

  // Used to register a PMT pointer during PMT construction
  void AddPmoLocked(PinnedMemoryTokenDispatcher* pmt) TA_REQ(get_lock());
  // Used to unregister a PMT pointer during PMT destruction
  void RemovePmo(PinnedMemoryTokenDispatcher* pmt);

  // Append |pmt| to the quarantine_ list. |pmt| is not removed from pinned_memory_.
  // This will prevent its underlying VMO from being unpinned until the
  // quarantine is cleared.
  void Quarantine(fbl::RefPtr<PinnedMemoryTokenDispatcher> pmt) TA_EXCL(get_lock());

 private:
  enum class BtiPageLeakReason {
    BtiClose,
    PmtClose,
  };

  BusTransactionInitiatorDispatcher(fbl::RefPtr<Iommu> iommu, uint64_t bti_id);
  void PrintQuarantineWarningLocked(BtiPageLeakReason reason) TA_REQ(get_lock());

  const fbl::RefPtr<Iommu> iommu_;
  const uint64_t bti_id_;

  using PmoList = fbl::TaggedDoublyLinkedList<PinnedMemoryTokenDispatcher*, PmtListTag>;
  using QuarantineList =
      fbl::TaggedDoublyLinkedList<fbl::RefPtr<PinnedMemoryTokenDispatcher>, PmtQuarantineListTag>;

  PmoList pinned_memory_ TA_GUARDED(get_lock());
  QuarantineList quarantine_ TA_GUARDED(get_lock());

  bool zero_handles_ TA_GUARDED(get_lock());

  // The user-friendly BTI name. For debug purposes only.
  fbl::Name<ZX_MAX_NAME_LEN> name_;
};

#endif  // ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_BUS_TRANSACTION_INITIATOR_DISPATCHER_H_
