// 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 <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
#include <hypervisor/ktrace.h>
#include <hypervisor/trap_map.h>
#include <lib/ktrace.h>
#include <zircon/syscalls/hypervisor.h>
#include <zircon/types.h>

static constexpr size_t kMaxPacketsPerRange = 256;

namespace hypervisor {

BlockingPortAllocator::BlockingPortAllocator() : semaphore_(kMaxPacketsPerRange) {}

zx_status_t BlockingPortAllocator::Init() {
  return arena_.Init("hypervisor-packets", kMaxPacketsPerRange);
}

PortPacket* BlockingPortAllocator::AllocBlocking() {
  ktrace_vcpu(TAG_VCPU_BLOCK, VCPU_PORT);
  zx_status_t status = semaphore_.Wait(Deadline::infinite());
  ktrace_vcpu(TAG_VCPU_UNBLOCK, VCPU_PORT);
  if (status != ZX_OK) {
    return nullptr;
  }
  return Alloc();
}

PortPacket* BlockingPortAllocator::Alloc() {
  return arena_.New(this /* handle */, this /* allocator */);
}

void BlockingPortAllocator::Free(PortPacket* port_packet) {
  arena_.Delete(port_packet);
  semaphore_.Post();
}

Trap::Trap(uint32_t kind, zx_gpaddr_t addr, size_t len, fbl::RefPtr<PortDispatcher> port,
           uint64_t key)
    : kind_(kind), addr_(addr), len_(len), port_(ktl::move(port)), key_(key) {}

Trap::~Trap() {
  if (port_ == nullptr) {
    return;
  }
  port_->CancelQueued(&port_allocator_ /* handle */, key_);
}

zx_status_t Trap::Init() { return port_allocator_.Init(); }

zx_status_t Trap::Queue(const zx_port_packet_t& packet, StateInvalidator* invalidator) {
  if (invalidator != nullptr) {
    invalidator->Invalidate();
  }
  if (port_ == nullptr) {
    return ZX_ERR_NOT_FOUND;
  }
  PortPacket* port_packet = port_allocator_.AllocBlocking();
  if (port_packet == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }
  port_packet->packet = packet;
  zx_status_t status = port_->Queue(port_packet, ZX_SIGNAL_NONE, 0);
  if (status != ZX_OK) {
    port_allocator_.Free(port_packet);
  }
  return status;
}

zx_status_t TrapMap::InsertTrap(uint32_t kind, zx_gpaddr_t addr, size_t len,
                                fbl::RefPtr<PortDispatcher> port, uint64_t key) {
  TrapTree* traps = TreeOf(kind);
  if (traps == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }
  auto iter = traps->find(addr);
  if (iter.IsValid()) {
    dprintf(INFO,
            "Trap for kind %u (addr %#lx len %lu key %lu) already exists "
            "(addr %#lx len %lu key %lu)\n",
            kind, addr, len, key, iter->addr(), iter->len(), iter->key());
    return ZX_ERR_ALREADY_EXISTS;
  }
  fbl::AllocChecker ac;
  ktl::unique_ptr<Trap> range(new (&ac) Trap(kind, addr, len, ktl::move(port), key));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  zx_status_t status = range->Init();
  if (status != ZX_OK) {
    return status;
  }
  {
    Guard<SpinLock, IrqSave> guard{&lock_};
    traps->insert(ktl::move(range));
  }
  return ZX_OK;
}

zx_status_t TrapMap::FindTrap(uint32_t kind, zx_gpaddr_t addr, Trap** trap) {
  TrapTree* traps = TreeOf(kind);
  if (traps == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }
  TrapTree::iterator iter;
  {
    Guard<SpinLock, IrqSave> guard{&lock_};
    iter = traps->upper_bound(addr);
  }
  --iter;
  if (!iter.IsValid() || !iter->Contains(addr)) {
    return ZX_ERR_NOT_FOUND;
  }
  *trap = const_cast<Trap*>(&*iter);
  return ZX_OK;
}

TrapMap::TrapTree* TrapMap::TreeOf(uint32_t kind) {
  switch (kind) {
    case ZX_GUEST_TRAP_BELL:
    case ZX_GUEST_TRAP_MEM:
      return &mem_traps_;
#ifdef ARCH_X86
    case ZX_GUEST_TRAP_IO:
      return &io_traps_;
#endif  // ARCH_X86
    default:
      return nullptr;
  }
}

}  // namespace hypervisor
