// 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 <hypervisor/trap_map.h>

#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
#include <hypervisor/ktrace.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(nullptr, this);
}

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) {
    (void) key_;
}

Trap::~Trap() {
    if (port_ == nullptr) {
        return;
    }
    port_->CancelQueued(nullptr /* 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
