blob: ea516ff7cc6fd2706b74666745440957d84e5f39 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_GRAPHICS_DRIVERS_MISC_GOLDFISH_CONTROL_HOST_VISIBLE_HEAP_H_
#define SRC_GRAPHICS_DRIVERS_MISC_GOLDFISH_CONTROL_HOST_VISIBLE_HEAP_H_
#include <fidl/fuchsia.sysmem2/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/async/cpp/wait.h>
#include <lib/fidl/cpp/wire/server.h>
#include <lib/fit/function.h>
#include <lib/zx/pmt.h>
#include <functional>
#include <memory>
#include <unordered_map>
#include "src/graphics/drivers/misc/goldfish_control/heap.h"
namespace goldfish {
class Control;
// LLCPP synchronous server of a goldfish device-local Fuchsia sysmem Heap
// interface.
class HostVisibleHeap : public Heap {
public:
static std::unique_ptr<HostVisibleHeap> Create(Control* control);
~HostVisibleHeap() override;
// |fidl::WireServer<fuchsia_sysmem2::Heap>|
void AllocateVmo(AllocateVmoRequestView request, AllocateVmoCompleter::Sync& completer) override;
// |fidl::WireServer<fuchsia_sysmem2::Heap>|
void DeleteVmo(DeleteVmoRequestView request, DeleteVmoCompleter::Sync& completer) override;
// |Heap|
void Bind(zx::channel server_request) override;
private:
// This constructor is for internal use only. Use |HostVisibleHeap::Create()| instead.
explicit HostVisibleHeap(Control* control);
// Destroy VMO and deallocate address space blocks stored in |blocks_\.
// |buffer_key| is the unique ID of the logical buffer - i.e. the key of |blocks_|.
void DeallocateVmo(BufferKey buffer_key);
// Address space block information.
//
// The |Block| possesses the parent |vmo| acquired directly from goldfish
// address space, until all its children are destroyed and it receives a
// ZX_VMO_ZERO_CHILDREN signal.
//
// For this purpose, we also store an async Wait |wait_deallocate| waiting
// on that signal to invoke |deallocate_callback|, and dispatch it on
// the async |dispatcher|.
struct Block {
Block(zx::vmo vmo, uint64_t paddr, fit::function<void(Block&)> deallocate_callback,
async_dispatcher_t* dispatcher);
// The parent |vmo| acquired directly from goldfish address space.
// This is kept by |Block| to ensure that address space blocks are
// deallocated correctly when |vmo| is never referenced anymore.
zx::vmo vmo;
// Physical memory address of this memory block acquired from
// goldfish address space.
uint64_t paddr;
std::optional<DeleteVmoCompleter::Async> maybe_delete_completer;
// Since address space block is allocated at |AllocateVmo()| and it's
// possible that the VMO can be destroyed before |CreateResource()|,
// we should ensure that the block is deallocated in any case when
// the VMO is unused instead of relying on |DestroyResource()|.
//
// So we keep the parent VMO within Heap, and send child of the parent
// VMO as |AllocateVmo()| result. In this way, we can wait on Zircon
// VMO "zero children" signal on |vmo| to tear down VMO and its associated
// address space block properly. The async Wait serves this purpose by
// attach an async wait on that signal to the heap's dispatcher.
async::Wait wait_deallocate;
};
// Stores all the |Block|s allocated by the heap. Entries are created in
// |AllocateVmo()|, and retrieved in |CreateResource()|.
//
// Key: koid of |vmo| returned by AllocateVmo().
// Value: Address space block info.
using BlockMapType = std::unordered_map<BufferKey, Block, BufferKeyHash>;
BlockMapType blocks_;
};
} // namespace goldfish
#endif // SRC_GRAPHICS_DRIVERS_MISC_GOLDFISH_CONTROL_HOST_VISIBLE_HEAP_H_