blob: b39caba6d3e519b2ad9e77876e7e9cd665c9f840 [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 <vm/vmalloc.h>
#include <trace.h>
#include <vm/vm_aspace.h>
#include <vm/vm_object_paged.h>
#define LOCAL_TRACE 0
static const uint kArchRwFlags = ARCH_MMU_FLAG_PERM_READ | ARCH_MMU_FLAG_PERM_WRITE;
static fbl::RefPtr<VmAddressRegion> vmalloc_vmar;
// the power of 2 size of the vmar used for vmalloc mappings
static const size_t vmalloc_vmar_shift = 30; // 1GB
void* vmalloc(size_t len, const char* _name) {
const char* name = _name ? _name : "vmalloc";
// Create a VMO for our allocation
fbl::RefPtr<VmObject> vmo;
zx_status_t status = VmObjectPaged::Create(
PMM_ALLOC_FLAG_ANY, 0u, len, &vmo);
if (status != ZX_OK) {
TRACEF("vmalloc: failed to allocate vmo of size %zu\n", len);
return nullptr;
}
vmo->set_name(name, strlen(name));
auto vmo_size = vmo->size();
// create a mapping with random placement into the vmalloc region
fbl::RefPtr<VmMapping> mapping;
status = vmalloc_vmar->CreateVmMapping(0, vmo_size, 0,
0,
fbl::move(vmo), 0,
kArchRwFlags,
name,
&mapping);
if (status != ZX_OK)
return nullptr;
// fault in all the pages so we dont demand fault in the allocation
status = mapping->MapRange(0, vmo_size, true);
if (status != ZX_OK) {
mapping->Destroy();
return nullptr;
}
void* ptr = reinterpret_cast<void*>(mapping->base());
LTRACEF("returning %p for size %zu\n", ptr, len);
return ptr;
}
void vmfree(void* ptr) {
LTRACEF("ptr %p\n", ptr);
vaddr_t va = reinterpret_cast<vaddr_t>(ptr);
DEBUG_ASSERT(is_kernel_address(va));
zx_status_t status = VmAspace::kernel_aspace()->FreeRegion(va);
if (status != ZX_OK) {
TRACEF("warning: vmfree at %p failed\n", ptr);
}
}
void vmalloc_init() {
auto root_vmar = VmAspace::kernel_aspace()->RootVmar()->as_vm_address_region();
zx_status_t status = root_vmar->CreateSubVmar(0,
(1ULL << vmalloc_vmar_shift), vmalloc_vmar_shift,
VMAR_FLAG_CAN_MAP_READ | VMAR_FLAG_CAN_MAP_WRITE,
"vmalloc vmar", &vmalloc_vmar);
ASSERT(status == ZX_OK);
}