blob: b0466e3ad80a172374c79fdc579f1142a182848a [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/unittest/user_memory.h>
#include <fbl/auto_call.h>
#include <lib/unittest/unittest.h>
namespace testing {
UserMemory::~UserMemory() {
zx_status_t status = mapping_->Unmap(mapping_->base(), mapping_->size());
DEBUG_ASSERT(status == ZX_OK);
}
// static
ktl::unique_ptr<UserMemory> UserMemory::Create(size_t size) {
size = ROUNDUP_PAGE_SIZE(size);
fbl::RefPtr<VmObject> vmo;
zx_status_t status = VmObjectPaged::Create(PMM_ALLOC_FLAG_ANY, 0u, size, &vmo);
if (status != ZX_OK) {
unittest_printf("VmObjectPaged::Create failed: %d\n", status);
return nullptr;
}
fbl::RefPtr<VmAspace> aspace = fbl::WrapRefPtr(vmm_aspace_to_obj(get_current_thread()->aspace));
DEBUG_ASSERT(aspace);
DEBUG_ASSERT(aspace->is_user());
fbl::RefPtr<VmAddressRegion> root_vmar = aspace->RootVmar();
constexpr uint32_t vmar_flags = VMAR_FLAG_CAN_MAP_READ |
VMAR_FLAG_CAN_MAP_WRITE |
VMAR_FLAG_CAN_MAP_EXECUTE;
fbl::RefPtr<VmMapping> mapping;
constexpr uint arch_mmu_flags = ARCH_MMU_FLAG_PERM_READ |
ARCH_MMU_FLAG_PERM_WRITE;
status = root_vmar->CreateVmMapping(/* offset= */ 0, size, /* align_pow2= */ 0, vmar_flags,
vmo, 0, arch_mmu_flags, "unittest", &mapping);
if (status != ZX_OK) {
unittest_printf("CreateVmMapping failed: %d\n", status);
return nullptr;
}
auto unmap = fbl::MakeAutoCall([&]() {
if (mapping) {
zx_status_t status = mapping->Unmap(mapping->base(), mapping->size());
DEBUG_ASSERT(status == ZX_OK);
}
});
fbl::AllocChecker ac;
ktl::unique_ptr<UserMemory> mem(new (&ac) UserMemory(mapping));
if (!ac.check()) {
unittest_printf("failed to allocate from heap\n");
return nullptr;
}
// Unmapping is now UserMemory's responsibility.
unmap.cancel();
return mem;
}
} // namespace testing