167754Smsmith/*
267754Smsmith * Copyright 2017, Data61
367754Smsmith * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
467754Smsmith * ABN 41 687 119 230.
567754Smsmith *
667754Smsmith * This software may be distributed and modified according to the terms of
7217365Sjkim * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8298714Sjkim * See "LICENSE_BSD2.txt" for details.
970243Smsmith *
1067754Smsmith * @TAG(DATA61_BSD)
11217365Sjkim */
12217365Sjkim
13217365Sjkim#pragma once
14217365Sjkim
15217365Sjkim#include <autoconf.h>
16217365Sjkim#include <sel4/types.h>
17217365Sjkim#include <allocman/cspace/cspace.h>
18217365Sjkim#include <allocman/cspace/single_level.h>
19217365Sjkim
20217365Sjkimstruct cspace_two_level_config {
21217365Sjkim    /* A cptr to the first level cnode that we are managing slots in */
22217365Sjkim    seL4_CPtr cnode;
23217365Sjkim    /* Size in bits of the cnode */
24217365Sjkim    size_t cnode_size_bits;
2567754Smsmith    /* Guard depth added to this cspace. */
26217365Sjkim    size_t cnode_guard_bits;
27217365Sjkim    /* First valid slot (as an index) */
28217365Sjkim    size_t first_slot;
2967754Smsmith    /* Last valid slot + 1 (as an index) */
30217365Sjkim    size_t end_slot;
31217365Sjkim    /* Size of the second level nodes
32217365Sjkim       cnode_size_bits + cnode_guard_bits + level_two_bits <= 32 */
33217365Sjkim    size_t level_two_bits;
34217365Sjkim    /* if any of the second level cnodes are already created we can describe them here.
35217365Sjkim     * up to the user to have put the cspace together in a way that is compatible with
36217365Sjkim     * this allocator. The slot range is usual 'valid slot' to 'valid slot +1', with
37217365Sjkim     * the cptr range describing a used cap range which can start and stop partially in
38217365Sjkim     * any of the level 2 cnodes */
39217365Sjkim    size_t start_existing_index;
40217365Sjkim    size_t end_existing_index;
41217365Sjkim    seL4_CPtr start_existing_slot;
42217365Sjkim    seL4_CPtr end_existing_slot;
4367754Smsmith};
44193341Sjkim
45193341Sjkimstruct cspace_two_level_node {
46193341Sjkim    /* We count how many things we have allocated in each level two cnode.
47193341Sjkim       This allows us to quickly know whether it is already full, or of it is
4867754Smsmith       empty and we can free it */
4967754Smsmith    size_t count;
50102550Siwasaki    /* The cspace representing the second level */
5191116Smsmith    cspace_single_level_t second_level;
5267754Smsmith    /* Cookie representing the untyped object used to create the cnode for this
53287168Sjkim       second level. This is only valid if we allocated this node, it may have
54151937Sjkim       been given to us in bootstrapping */
55151937Sjkim    seL4_Word cookie;
56151937Sjkim    int cookie_valid;
57151937Sjkim};
58151937Sjkim
59151937Sjkimtypedef struct cspace_two_level {
60151937Sjkim    /* Remember the config */
61151937Sjkim    struct cspace_two_level_config config;
62151937Sjkim    /* First level of cspace */
63151937Sjkim    cspace_single_level_t first_level;
64151937Sjkim    /* Our second level cspaces */
65151937Sjkim    struct cspace_two_level_node **second_levels;
66151937Sjkim    /* Remember which second level we last tried to allocate a slot from */
67151937Sjkim    size_t last_second_level;
68151937Sjkim} cspace_two_level_t;
69151937Sjkim
70151937Sjkimint cspace_two_level_create(struct allocman *alloc, cspace_two_level_t *cspace, struct cspace_two_level_config config);
71167805Sjkimvoid cspace_two_level_destroy(struct allocman *alloc, cspace_two_level_t *cspace);
72151937Sjkim
73151937SjkimseL4_CPtr _cspace_two_level_boot_alloc(struct allocman *alloc, void *_cspace, int *error);
74151937Sjkimint _cspace_two_level_alloc(struct allocman *alloc, void *_cspace, cspacepath_t *slot);
75167805Sjkimvoid _cspace_two_level_free(struct allocman *alloc, void *_cspace, const cspacepath_t *slot);
76151937Sjkimint _cspace_two_level_alloc_at(struct allocman *alloc, void *_cspace, seL4_CPtr slot);
77151937Sjkim
7867754Smsmithcspacepath_t _cspace_two_level_make_path(void *_cspace, seL4_CPtr slot);
7967754Smsmith
8067754Smsmithstatic inline cspace_interface_t cspace_two_level_make_interface(cspace_two_level_t *cspace) {
81240716Sjkim    return (cspace_interface_t) {
8267754Smsmith        .alloc = _cspace_two_level_alloc,
8367754Smsmith        .free = _cspace_two_level_free,
8467754Smsmith        .make_path = _cspace_two_level_make_path,
8567754Smsmith        /* We do not want to handle recursion, as it shouldn't happen */
8667754Smsmith        .properties = ALLOCMAN_DEFAULT_PROPERTIES,
8767754Smsmith        .cspace = cspace
8867754Smsmith    };
8983174Smsmith}
9067754Smsmith
9167754Smsmith