blob: ddac42461ea010d7cd1b68674547b7c9cc24db23 [file] [log] [blame]
// Copyright 2018 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.
#include "zircon_platform_bus_mapper.h"
#include "platform_trace.h"
#include <ddk/driver.h>
#include <lib/zx/process.h>
namespace magma {
ZirconPlatformBusMapper::BusMapping::~BusMapping()
{
zx_status_t status = pmt_.unpin();
if (status != ZX_OK) {
DLOG("zx_pmt_unpin failed: %d\n", status);
}
}
std::unique_ptr<PlatformBusMapper::BusMapping>
ZirconPlatformBusMapper::MapPageRangeBus(magma::PlatformBuffer* buffer, uint32_t start_page_index,
uint32_t page_count)
{
TRACE_DURATION("magma", "MapPageRangeBus");
static_assert(sizeof(zx_paddr_t) == sizeof(uint64_t), "unexpected sizeof(zx_paddr_t)");
if ((page_count == 0) || (start_page_index + page_count) * PAGE_SIZE > buffer->size())
return DRETP(nullptr, "Invalid range: %d, %d\n", start_page_index, page_count);
std::vector<uint64_t> page_addr(page_count);
zx::pmt pmt;
zx_status_t status;
{
auto size = page_count * PAGE_SIZE;
TRACE_DURATION("magma", "bti pin", "size", size);
status = zx_bti_pin(bus_transaction_initiator_->get(),
ZX_BTI_PERM_READ | ZX_BTI_PERM_WRITE | ZX_BTI_PERM_EXECUTE,
static_cast<ZirconPlatformBuffer*>(buffer)->handle(),
start_page_index * PAGE_SIZE, size, page_addr.data(),
page_count, pmt.reset_and_get_address());
}
if (status != ZX_OK) {
zx_info_kmem_stats_t kmem_stats;
zx_object_get_info(get_root_resource(), ZX_INFO_KMEM_STATS, &kmem_stats, sizeof(kmem_stats),
nullptr, nullptr);
zx_info_task_stats_t task_stats = {};
zx::process::self()->get_info(ZX_INFO_TASK_STATS, &task_stats, sizeof(task_stats), nullptr,
nullptr);
magma::log(magma::LOG_WARNING,
"Failed to pin 0x%x pages (0x%lx bytes) with status %d. Out of Memory?\n"
"mem_mapped_bytes: 0x%lx mem_private_bytes: 0x%lx mem_shared_bytes: 0x%lx\n"
"total_bytes: 0x%lx free_bytes 0x%lx: wired_bytes: 0x%lx vmo_bytes: 0x%lx\n"
"mmu_overhead_bytes: 0x%lx other_bytes: 0x%lx\n",
page_count, static_cast<uint64_t>(page_count) * PAGE_SIZE, status,
task_stats.mem_mapped_bytes, task_stats.mem_private_bytes,
task_stats.mem_shared_bytes, kmem_stats.total_bytes, kmem_stats.free_bytes,
kmem_stats.wired_bytes, kmem_stats.vmo_bytes, kmem_stats.mmu_overhead_bytes,
kmem_stats.other_bytes);
return nullptr;
}
auto mapping =
std::make_unique<BusMapping>(start_page_index, std::move(page_addr), std::move(pmt));
return mapping;
}
std::unique_ptr<PlatformBusMapper>
PlatformBusMapper::Create(std::shared_ptr<PlatformHandle> bus_transaction_initiator)
{
return std::make_unique<ZirconPlatformBusMapper>(
std::static_pointer_cast<ZirconPlatformHandle>(bus_transaction_initiator));
}
} // namespace magma