// 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_HYPERVISOR_INCLUDE_HYPERVISOR_TRAP_MAP_H_
#define ZIRCON_KERNEL_HYPERVISOR_INCLUDE_HYPERVISOR_TRAP_MAP_H_

#include <fbl/arena.h>
#include <fbl/intrusive_wavl_tree.h>
#include <fbl/ref_ptr.h>
#include <hypervisor/state_invalidator.h>
#include <kernel/semaphore.h>
#include <object/port_dispatcher.h>

namespace hypervisor {

// Blocks on allocation if the arena is empty.
class BlockingPortAllocator final : public PortAllocator {
 public:
  BlockingPortAllocator();

  zx_status_t Init() TA_NO_THREAD_SAFETY_ANALYSIS;
  PortPacket* AllocBlocking();
  virtual void Free(PortPacket* port_packet) override;

 private:
  Semaphore semaphore_;
  fbl::TypedArena<PortPacket, Mutex> arena_;

  PortPacket* Alloc() override;
};

// Describes a single trap within a guest.
class Trap : public fbl::WAVLTreeContainable<ktl::unique_ptr<Trap>> {
 public:
  Trap(uint32_t kind, zx_gpaddr_t addr, size_t len, fbl::RefPtr<PortDispatcher> port, uint64_t key);
  ~Trap();

  zx_status_t Init();
  zx_status_t Queue(const zx_port_packet_t& packet, StateInvalidator* invalidator);

  zx_gpaddr_t GetKey() const { return addr_; }
  bool Contains(zx_gpaddr_t val) const { return val >= addr_ && val < addr_ + len_; }
  bool HasPort() const { return !!port_; }

  uint32_t kind() const { return kind_; }
  zx_gpaddr_t addr() const { return addr_; }
  size_t len() const { return len_; }
  uint64_t key() const { return key_; }

 private:
  const uint32_t kind_;
  const zx_gpaddr_t addr_;
  const size_t len_;
  const fbl::RefPtr<PortDispatcher> port_;
  const uint64_t key_;  // Key for packets in this port range.
  BlockingPortAllocator port_allocator_;
};

// Contains all the traps within a guest.
class TrapMap {
 public:
  zx_status_t InsertTrap(uint32_t kind, zx_gpaddr_t addr, size_t len,
                         fbl::RefPtr<PortDispatcher> port, uint64_t key);
  zx_status_t FindTrap(uint32_t kind, zx_gpaddr_t addr, Trap** trap);

 private:
  using TrapTree = fbl::WAVLTree<zx_gpaddr_t, ktl::unique_ptr<Trap>>;

  DECLARE_SPINLOCK(TrapMap) lock_;
  TrapTree mem_traps_ TA_GUARDED(lock_);
#ifdef ARCH_X86
  TrapTree io_traps_ TA_GUARDED(lock_);
#endif  // ARCH_X86

  TrapTree* TreeOf(uint32_t kind);
};

}  // namespace hypervisor

#endif  // ZIRCON_KERNEL_HYPERVISOR_INCLUDE_HYPERVISOR_TRAP_MAP_H_
