blob: dce1252c21e97119e5514bca75b2d3c52e646c5a [file] [log] [blame]
/*
* Copyright 2017, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(DATA61_BSD)
*/
#include <allocman/allocman.h>
#include <allocman/util.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <sel4/sel4.h>
#include <allocman/vka.h>
#include <vka/object.h>
#include <allocman/cspace/vka.h>
#include <allocman/utspace/vka.h>
#include <allocman/mspace/malloc.h>
/**
* Allocate a slot in a cspace.
*
* @param data cookie for the underlying allocator
* @param res pointer to a cptr to store the allocated slot
* @return 0 on success
*/
static int am_vka_cspace_alloc(void *data, seL4_CPtr *res)
{
int error;
cspacepath_t path;
assert(data);
assert(res);
error = allocman_cspace_alloc((allocman_t *) data, &path);
if (!error) {
*res = path.capPtr;
}
return error;
}
/**
* Convert an allocated cptr to a cspacepath, for use in
* operations such as Untyped_Retype
*
* @param data cookie for the underlying allocator
* @param slot a cslot allocated by the cspace alloc function
* @param res pointer to a cspacepath struct to fill out
*/
static void am_vka_cspace_make_path (void *data, seL4_CPtr slot, cspacepath_t *res)
{
assert(data);
assert(res);
*res = allocman_cspace_make_path((allocman_t*) data, slot);
}
/**
* Free an allocated cslot
*
* @param data cookie for the underlying allocator
* @param slot a cslot allocated by the cspace alloc function
*/
static void am_vka_cspace_free (void *data, seL4_CPtr slot)
{
cspacepath_t path;
assert(data);
path = allocman_cspace_make_path((allocman_t*)data, slot);
allocman_cspace_free((allocman_t *) data, &path);
}
/**
* Allocate a portion of an untyped into an object
*
* @param data cookie for the underlying allocator
* @param dest path to an empty cslot to place the cap to the allocated object
* @param type the seL4 object type to allocate (as passed to Untyped_Retype)
* @param size_bits the size of the object to allocate (as passed to Untyped_Retype)
* @param can_use_dev whether the allocator can use device untyped instead of regular untyped
* @param res pointer to a location to store the cookie representing this allocation
* @return 0 on success
*/
static int am_vka_utspace_alloc_maybe_device (void *data, const cspacepath_t *dest,
seL4_Word type, seL4_Word size_bits, bool can_use_dev, seL4_Word *res)
{
int error;
assert(data);
assert(res);
assert(dest);
/* allocman uses the size in memory internally, where as vka expects size_bits
* as passed to Untyped_Retype, so do a conversion here */
size_bits = vka_get_object_size(type, size_bits);
*res = allocman_utspace_alloc((allocman_t *) data, size_bits, type, (cspacepath_t*)dest, can_use_dev, &error);
return error;
}
/**
* Allocate a portion of an untyped into an object
*
* @param data cookie for the underlying allocator
* @param dest path to an empty cslot to place the cap to the allocated object
* @param type the seL4 object type to allocate (as passed to Untyped_Retype)
* @param size_bits the size of the object to allocate (as passed to Untyped_Retype)
* @param res pointer to a location to store the cookie representing this allocation
* @return 0 on success
*/
static int am_vka_utspace_alloc (void *data, const cspacepath_t *dest, seL4_Word type, seL4_Word size_bits, seL4_Word *res)
{
return am_vka_utspace_alloc_maybe_device(data, dest, type, size_bits, false, res);
}
/**
* Allocate a portion of an untyped into an object
*
* @param data cookie for the underlying allocator
* @param dest path to an empty cslot to place the cap to the allocated object
* @param type the seL4 object type to allocate (as passed to Untyped_Retype)
* @param size_bits the size of the object to allocate (as passed to Untyped_Retype)
* @param paddr the desired physical address of the start of the allocated object
* @param res pointer to a location to store the cookie representing this allocation
* @return 0 on success
*/
static int am_vka_utspace_alloc_at (void *data, const cspacepath_t *dest, seL4_Word type, seL4_Word size_bits, uintptr_t paddr, seL4_Word *res)
{
int error;
assert(data);
assert(res);
assert(dest);
/* allocman uses the size in memory internally, where as vka expects size_bits
* as passed to Untyped_Retype, so do a conversion here */
size_bits = vka_get_object_size(type, size_bits);
*res = allocman_utspace_alloc_at((allocman_t *) data, size_bits, type, (cspacepath_t*)dest, paddr, true, &error);
return error;
}
/**
* Free a portion of an allocated untyped. Is the responsibility of the caller to
* have already deleted the object (by deleting all capabilities) first
*
* @param data cookie for the underlying allocator
* @param type the seL4 object type that was allocated (as passed to Untyped_Retype)
* @param size_bits the size of the object that was allocated (as passed to Untyped_Retype)
* @param target cookie to the allocation as given by the utspace alloc function
*/
static void am_vka_utspace_free (void *data, seL4_Word type, seL4_Word size_bits, seL4_Word target)
{
assert(data);
/* allocman uses the size in memory internally, where as vka expects size_bits
* as passed to Untyped_Retype, so do a conversion here */
size_bits = vka_get_object_size(type, size_bits);
allocman_utspace_free((allocman_t *)data, target, size_bits);
}
static uintptr_t am_vka_utspace_paddr (void *data, seL4_Word target, seL4_Word type, seL4_Word size_bits)
{
assert(data);
/* allocman uses the size in memory internally, where as vka expects size_bits
* as passed to Untyped_Retype, so do a conversion here */
size_bits = vka_get_object_size(type, size_bits);
return allocman_utspace_paddr((allocman_t *)data, target, size_bits);
}
/**
* Make a VKA object using this allocman
*
* @param structure for the vka interface object
* @param allocator to be used with this vka
*/
void allocman_make_vka(vka_t *vka, allocman_t *alloc)
{
assert(vka);
assert(alloc);
vka->data = alloc;
vka->cspace_alloc = &am_vka_cspace_alloc;
vka->cspace_make_path = &am_vka_cspace_make_path;
vka->utspace_alloc = &am_vka_utspace_alloc;
vka->utspace_alloc_maybe_device = &am_vka_utspace_alloc_maybe_device;
vka->utspace_alloc_at = &am_vka_utspace_alloc_at;
vka->cspace_free = &am_vka_cspace_free;
vka->utspace_free = &am_vka_utspace_free;
vka->utspace_paddr = &am_vka_utspace_paddr;
}
int allocman_make_from_vka(vka_t *vka, allocman_t *alloc)
{
int error;
assert(vka);
assert(alloc);
error = allocman_create(alloc, mspace_malloc_interface);
if (error) {
return error;
}
error = allocman_attach_utspace(alloc, utspace_vka_make_interface(vka));
assert(!error);
error = allocman_attach_cspace(alloc, cspace_vka_make_interface(vka));
assert(!error);
return 0;
}