blob: 35ee02b7b0db78a61e638ac4de022514c4a0235d [file] [log] [blame]
/*
* Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <autoconf.h>
#include <sel4/types.h>
#include <allocman/cspace/cspace.h>
#include <allocman/cspace/single_level.h>
struct cspace_two_level_config {
/* A cptr to the first level cnode that we are managing slots in */
seL4_CPtr cnode;
/* Size in bits of the cnode */
size_t cnode_size_bits;
/* Guard depth added to this cspace. */
size_t cnode_guard_bits;
/* First valid slot (as an index) */
size_t first_slot;
/* Last valid slot + 1 (as an index) */
size_t end_slot;
/* Size of the second level nodes
cnode_size_bits + cnode_guard_bits + level_two_bits <= 32 */
size_t level_two_bits;
/* if any of the second level cnodes are already created we can describe them here.
* up to the user to have put the cspace together in a way that is compatible with
* this allocator. The slot range is usual 'valid slot' to 'valid slot +1', with
* the cptr range describing a used cap range which can start and stop partially in
* any of the level 2 cnodes */
size_t start_existing_index;
size_t end_existing_index;
seL4_CPtr start_existing_slot;
seL4_CPtr end_existing_slot;
};
struct cspace_two_level_node {
/* We count how many things we have allocated in each level two cnode.
This allows us to quickly know whether it is already full, or of it is
empty and we can free it */
size_t count;
/* The cspace representing the second level */
cspace_single_level_t second_level;
/* Cookie representing the untyped object used to create the cnode for this
second level. This is only valid if we allocated this node, it may have
been given to us in bootstrapping */
seL4_Word cookie;
int cookie_valid;
};
typedef struct cspace_two_level {
/* Remember the config */
struct cspace_two_level_config config;
/* First level of cspace */
cspace_single_level_t first_level;
/* Our second level cspaces */
struct cspace_two_level_node **second_levels;
/* Remember which second level we last tried to allocate a slot from */
size_t last_second_level;
} cspace_two_level_t;
int cspace_two_level_create(struct allocman *alloc, cspace_two_level_t *cspace, struct cspace_two_level_config config);
void cspace_two_level_destroy(struct allocman *alloc, cspace_two_level_t *cspace);
seL4_CPtr _cspace_two_level_boot_alloc(struct allocman *alloc, void *_cspace, int *error);
int _cspace_two_level_alloc(struct allocman *alloc, void *_cspace, cspacepath_t *slot);
void _cspace_two_level_free(struct allocman *alloc, void *_cspace, const cspacepath_t *slot);
int _cspace_two_level_alloc_at(struct allocman *alloc, void *_cspace, seL4_CPtr slot);
cspacepath_t _cspace_two_level_make_path(void *_cspace, seL4_CPtr slot);
static inline cspace_interface_t cspace_two_level_make_interface(cspace_two_level_t *cspace) {
return (cspace_interface_t) {
.alloc = _cspace_two_level_alloc,
.free = _cspace_two_level_free,
.make_path = _cspace_two_level_make_path,
/* We do not want to handle recursion, as it shouldn't happen */
.properties = ALLOCMAN_DEFAULT_PROPERTIES,
.cspace = cspace
};
}