blob: a5738e083fcc5af822ca6c437123ce7e4fbcb06b [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.
#include "memory_range.h"
#include <lib/zx/status.h>
#include <lib/zx/vmar.h>
#include <lib/zx/vmo.h>
#include <stdio.h>
#include <zircon/assert.h>
#include <zircon/status.h>
#include <zircon/types.h>
namespace hwstress {
zx::status<std::unique_ptr<MemoryRange>> MemoryRange::Create(uint64_t size, CacheMode mode) {
ZX_ASSERT(size % zx_system_get_page_size() == 0);
// Create the VMO.
zx::vmo vmo;
zx_status_t status = zx::vmo::create(size, /*options=*/0, &vmo);
if (status != ZX_OK) {
return zx::error(status);
}
// Set memory mode of the uncached VMO.
if (mode == CacheMode::kUncached) {
status = vmo.set_cache_policy(ZX_CACHE_POLICY_UNCACHED);
if (status != ZX_OK) {
return zx::error(status);
}
}
// Map the VMOs into memory.
zx_vaddr_t addr;
status = zx::vmar::root_self()->map(
/*options=*/(ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_MAP_RANGE),
/*vmar_offset=*/0, vmo, /*vmo_offset=*/0, /*len=*/size, &addr);
if (status != ZX_OK) {
return zx::error(status);
}
return zx::ok(
std::make_unique<MemoryRange>(std::move(vmo), reinterpret_cast<uint8_t*>(addr), size, mode));
}
MemoryRange::MemoryRange(zx::vmo vmo, uint8_t* addr, uint64_t size, CacheMode mode)
: vmo_(std::move(vmo)), addr_(addr), size_(size), cache_mode_(mode) {
ZX_ASSERT(reinterpret_cast<uintptr_t>(addr) % zx_system_get_page_size() == 0);
ZX_ASSERT(size % zx_system_get_page_size() == 0);
}
void MemoryRange::DoCacheOp(uint32_t operation) {
ZX_ASSERT(vmo_.op_range(operation, /*offset=*/0, /*size=*/size_,
/*buffer=*/nullptr,
/*buffer_size=*/0) == ZX_OK);
}
void MemoryRange::CleanCache() { DoCacheOp(ZX_VMO_OP_CACHE_CLEAN); }
void MemoryRange::CleanInvalidateCache() { DoCacheOp(ZX_VMO_OP_CACHE_CLEAN_INVALIDATE); }
MemoryRange::~MemoryRange() {
ZX_ASSERT(zx::vmar::root_self()->unmap(reinterpret_cast<zx_vaddr_t>(addr_), size_) == ZX_OK);
}
} // namespace hwstress