blob: ec327cbc68f465687e02ded56388ad147ae87016 [file] [log] [blame]
// 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_