blob: c6af35496b9ad73e22969559c7f27fc8fe5f4347 [file] [log] [blame]
// Copyright 2019 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_DEVICES_SYSMEM_DRIVERS_SYSMEM_MEMORY_ALLOCATOR_H_
#define SRC_DEVICES_SYSMEM_DRIVERS_SYSMEM_MEMORY_ALLOCATOR_H_
#include <fidl/fuchsia.hardware.sysmem/cpp/fidl.h>
#include <fidl/fuchsia.sysmem/cpp/fidl.h>
#include <fidl/fuchsia.sysmem2/cpp/fidl.h>
#include <lib/fit/function.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/zx/bti.h>
#include <lib/zx/vmo.h>
#include <map>
#include "protected_ranges.h"
class SysmemMetrics;
namespace sysmem_driver {
class MemoryAllocator {
public:
// Some sub-classes take this interface as a constructor param, which
// enables a fake in tests where we don't have a real zx::bti etc.
class Owner {
public:
virtual inspect::Node* heap_node() = 0;
virtual const zx::bti& bti() = 0;
virtual zx_status_t CreatePhysicalVmo(uint64_t base, uint64_t size, zx::vmo* vmo_out) = 0;
// Should be called after every delete that makes the allocator empty.
virtual void CheckForUnbind() {}
virtual SysmemMetrics& metrics() = 0;
virtual protected_ranges::ProtectedRangesCoreControl& protected_ranges_core_control(
const fuchsia_sysmem2::Heap& heap) {
// Avoid requiring unrelated tests to implement.
ZX_PANIC("protected_ranges_core_control() not implemented by subclass");
}
virtual bool protected_ranges_disable_dynamic() const { return false; }
virtual void OnAllocationFailure() {}
};
explicit MemoryAllocator(fuchsia_hardware_sysmem::HeapProperties properties);
virtual ~MemoryAllocator();
// size - the needed size in bytes, rounded up to a page boundaryß
//
// settings - allocators may observe settings if needed, but are discouraged from looking at
// settings unless really needed; settings.buffer_settings.size_bytes is the logical size in bytes
// not rounded up to a page boundary, so most allocators will only care about `size` (first
// parameter).
//
// name - a name that can be useful for debugging
//
// buffer_collection_id + buffer_index - The buffer_collection_id and buffer_index are retrievable
// from a sysmem-provided VMO using GetVmoInfo(). Because the sysmem-provided VMO may be a child
// (or grandchild) of the allocated VMO, the koid of parent_vmo is not generally retrievable from
// a sysmem-provide VMO derived from parent_vmo. Allocators which don't need to correlate a
// sysmem-provided VMO to a parent_vmo can ignore buffer_collection_id and buffer_index.
//
// parent_vmo - return the allocated VMO
//
// returns zx_status_t - the error may be useful for debugging, but the error code indicated to
// sysmem clients will be sanitized to ZX_ERR_NO_MEMORY.
virtual zx_status_t Allocate(uint64_t size, const fuchsia_sysmem2::SingleBufferSettings& settings,
std::optional<std::string> name, uint64_t buffer_collection_id,
uint32_t buffer_index, zx::vmo* parent_vmo) = 0;
// This also should clean up any tracking of buffer_collection_id + buffer_index (the specific
// combination), as zero sysmem-provided VMOs exist at this point, so it's impossible for any
// sysmem-provided VMO to show up with the parent_vmo's buffer_collection_id + buffer_index.
//
// This call takes ownership of parent_vmo, and should close parent_vmo so that the memory used by
// parent_vmo can be freed/reclaimed/recycled.
virtual void Delete(zx::vmo parent_vmo) = 0;
virtual zx_status_t GetPhysicalMemoryInfo(uint64_t* base, uint64_t* size) {
return ZX_ERR_NOT_SUPPORTED;
}
const fuchsia_hardware_sysmem::HeapProperties& heap_properties() const {
return heap_properties_;
}
// These avoid the possibility of trying to use a sysmem-configured secure
// heap before the TEE has told the HW to make the physical range
// secure/protected. The default SetReady() implementation panics, and the
// default is_ready() just returns true.
virtual void set_ready();
virtual bool is_ready();
void AddDestroyCallback(intptr_t key, fit::callback<void()> callback);
void RemoveDestroyCallback(intptr_t key);
// Returns true if there are no outstanding allocations, or if the allocator only allocates fully
// independent VMOs that fully own their own memory separate from any tracking in sysmem.
// Allocators must be empty before they're deleted.
virtual bool is_empty() = 0;
uint64_t id() const { return id_; }
virtual bool is_already_cleared_on_allocate() { return false; }
public:
std::map<intptr_t, fit::callback<void()>> destroy_callbacks_;
private:
// This is a unique ID for the allocator on this system.
uint64_t id_{};
fuchsia_hardware_sysmem::HeapProperties heap_properties_;
};
} // namespace sysmem_driver
#endif // SRC_DEVICES_SYSMEM_DRIVERS_SYSMEM_MEMORY_ALLOCATOR_H_