blob: cdac599a48cde43b8d1e7d7bad7027b934953920 [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_MEDIA_LIB_INTERNAL_BUFFER_INTERNAL_BUFFER_H_
#define SRC_MEDIA_LIB_INTERNAL_BUFFER_INTERNAL_BUFFER_H_
#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/fit/function.h>
#include <threads.h>
#include <zircon/types.h>
// Helper class to allocate a physically contiguous buffer. Allocated via sysmem in
// fuchsia::sysmem::HeapType::SYSTEM_RAM or fuchsia::sysmem::HeapType::AMLOGIC_SECURE memory,
// depending on whether is_secure.
class InternalBuffer {
public:
using ErrorHandler = fit::callback<void(zx_status_t status)>;
// |name| is borrowed during the call - not retained. Copied into ZX_PROP_NAME of the allocated
// vmo.
//
// |sysmem| is borrowed during the call - not retained.
//
// |bti| is borrowed during the call - not retained.
//
// |size| of the requested buffer. This must be % ZX_PAGE_SIZE == 0.
//
// |is_secure| is whether to allocate secure buffers or non-secure buffers. All buffers are
// allocated via sysmem and are physically contiguous.
//
// |is_writable| the buffer must be writable, else read-only.
//
// |is_mapping_needed| if a mapping to the allocated buffer is needed. This must be false if
// is_secure.
static fit::result<InternalBuffer, zx_status_t> Create(const char* name,
fuchsia::sysmem::AllocatorSyncPtr* sysmem,
const zx::unowned_bti& bti, size_t size,
bool is_secure, bool is_writable,
bool is_mapping_needed);
// Same as above, but alignment is the byte multiple to align the buffer to.
static fit::result<InternalBuffer, zx_status_t> CreateAligned(
const char* name, fuchsia::sysmem::AllocatorSyncPtr* sysmem, const zx::unowned_bti& bti,
size_t size, size_t alignment, bool is_secure, bool is_writable, bool is_mapping_needed);
~InternalBuffer();
// move-only; delete copy just for clarity
InternalBuffer(InternalBuffer&& other);
InternalBuffer& operator=(InternalBuffer&& other);
InternalBuffer(const InternalBuffer& other) = delete;
InternalBuffer& operator=(const InternalBuffer& other) = delete;
// This will assert in debug if !is_mapping_needed.
uint8_t* virt_base();
zx_paddr_t phys_base();
size_t size();
const zx::vmo& vmo();
// If is_secure, ignored. If !is_secure, flushes cache, or panics if the flush doesn't work.
//
// offset - start of range to flush
// length - length of range to flush
void CacheFlush(size_t offset, size_t length);
void CacheFlushInvalidate(size_t offset, size_t length);
private:
InternalBuffer(size_t size, bool is_secure, bool is_writable, bool is_mapping_needed);
InternalBuffer(size_t size);
zx_status_t Init(const char* name, fuchsia::sysmem::AllocatorSyncPtr* sysmem, size_t alignment,
const zx::unowned_bti& bti);
void DeInit();
void CacheFlushPossibleInvalidate(size_t offset, size_t length, bool invalidate);
size_t size_{};
bool is_secure_{};
bool is_writable_{};
bool is_mapping_needed_{};
uint8_t* virt_base_{};
// Include size for alignment.
size_t real_size_{};
uint8_t* real_virt_base_{};
uintptr_t alignment_offset_{};
zx::pmt pin_;
zx_paddr_t phys_base_{};
fidl::InterfaceHandle<fuchsia::sysmem::BufferCollection> buffer_collection_;
zx::vmo vmo_;
bool is_moved_out_ = false;
};
#endif // SRC_MEDIA_LIB_INTERNAL_BUFFER_INTERNAL_BUFFER_H_