| /* | 
 |  * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) | 
 |  * | 
 |  * SPDX-License-Identifier: BSD-2-Clause | 
 |  */ | 
 |  | 
 | #include <autoconf.h> | 
 | #include <sel4/types.h> | 
 | #include <sel4/sel4.h> | 
 | #include <stdio.h> | 
 | #include <allocman/allocman.h> | 
 | #include <allocman/cspace/simple1level.h> | 
 | #include <allocman/mspace/fixed_pool.h> | 
 | #include <allocman/utspace/twinkle.h> | 
 | #include <allocman/cspace/two_level.h> | 
 | #include <allocman/mspace/virtual_pool.h> | 
 | #include <allocman/utspace/trickle.h> | 
 | #include <allocman/bootstrap.h> | 
 | #include <allocman/cspaceops.h> | 
 | #include <string.h> | 
 | #include <sel4utils/vspace.h> | 
 | #include <allocman/vka.h> | 
 |  | 
 | #define VIRTUAL_START 0xA0000000 | 
 |  | 
 | #define MEM_POOL_SIZE (1*1024*1024) | 
 |  | 
 | static char initial_mem_pool[MEM_POOL_SIZE]; | 
 |  | 
 | allocman_t *test_use_current_cspace_bootinfo() { | 
 |     int error; | 
 |     allocman_t *allocman; | 
 |     vspace_alloc_t vspace; | 
 |     vka_t *vka; | 
 |     allocman = bootstrap_use_bootinfo(seL4_GetBootInfo(), sizeof(initial_mem_pool), initial_mem_pool); | 
 |     assert(allocman); | 
 |     vka = allocman_mspace_alloc(allocman, sizeof(*vka), &error); | 
 |     assert(!error); | 
 |     allocman_make_vka(vka, allocman); | 
 |     sel4util_get_vspace_alloc_leaky(&vspace, seL4_CapInitThreadPD, vka, seL4_GetBootInfo()); | 
 |  | 
 |     reservation_t *reservation = vspace_reserve_range_at(&vspace, VIRTUAL_START, MEM_POOL_SIZE, seL4_AllRights, 1); | 
 |     assert(reservation); | 
 |  | 
 |     bootstrap_configure_virtual_pool(allocman, VIRTUAL_START, MEM_POOL_SIZE, seL4_CapInitThreadPD); | 
 |     error = allocman_fill_reserves(allocman); | 
 |     assert(!error); | 
 |     return allocman; | 
 | } | 
 |  | 
 | void test_use_current_1level_cspace() { | 
 |     int error; | 
 |     seL4_CPtr i; | 
 |     allocman_t *allocman; | 
 |     seL4_BootInfo *bi = seL4_GetBootInfo(); | 
 |     allocman = bootstrap_use_current_1level(seL4_CapInitThreadCNode, bi->initThreadCNodeSizeBits, bi->empty.start, bi->empty.end, sizeof(initial_mem_pool), initial_mem_pool); | 
 |     assert(allocman); | 
 |     /* have to add all our resources manually */ | 
 |     for (i = bi->untyped.start; i < bi->untyped.end; i++) { | 
 |         cspacepath_t slot = allocman_cspace_make_path(allocman, i); | 
 |         uint32_t size_bits = bi->untypedSizeBitsList[i - bi->untyped.start]; | 
 |         uint32_t paddr = bi->untypedPaddrList[i - bi->untyped.start]; | 
 |         error = allocman_utspace_add_uts(allocman, 1, &slot, &size_bits, &paddr); | 
 |         assert(!error); | 
 |     } | 
 |     error = allocman_fill_reserves(allocman); | 
 |     assert(!error); | 
 | } | 
 |  | 
 | void test_use_current_cspace() { | 
 |     int error; | 
 |     seL4_CPtr i; | 
 |     allocman_t *allocman; | 
 |     cspace_single_level_t *cspace; | 
 |     utspace_trickle_t *utspace; | 
 |     seL4_BootInfo *bi = seL4_GetBootInfo(); | 
 |     allocman = bootstrap_create_allocman(sizeof(initial_mem_pool), initial_mem_pool); | 
 |     assert(allocman); | 
 |     /* construct a description of our current cspace */ | 
 |     cspace = allocman_mspace_alloc(allocman, sizeof(*cspace), &error); | 
 |     assert(!error); | 
 |     error = cspace_single_level_create(allocman, cspace, (struct cspace_single_level_config) { | 
 |         .cnode = seL4_CapInitThreadCNode, | 
 |         .cnode_size_bits = bi->initThreadCNodeSizeBits, | 
 |         .cnode_guard_bits = seL4_WordBits - bi->initThreadCNodeSizeBits, | 
 |         .first_slot = bi->empty.start, | 
 |         .end_slot = bi->empty.end | 
 |     }); | 
 |     assert(!error); | 
 |  | 
 |     error = allocman_attach_cspace(allocman, cspace_single_level_make_interface(cspace)); | 
 |     assert(!error); | 
 |  | 
 |     utspace = allocman_mspace_alloc(allocman, sizeof(*utspace), &error); | 
 |     assert(!error); | 
 |     error = allocman_attach_utspace(allocman, utspace_trickle_make_interface(utspace)); | 
 |     assert(!error); | 
 |  | 
 |     /* have to add all our resources manually */ | 
 |     for (i = bi->untyped.start; i < bi->untyped.end; i++) { | 
 |         cspacepath_t slot = allocman_cspace_make_path(allocman, i); | 
 |         uint32_t size_bits = bi->untypedSizeBitsList[i - bi->untyped.start]; | 
 |         uint32_t paddr = bi->untypedPaddrList[i - bi->untyped.start]; | 
 |         error = allocman_utspace_add_uts(allocman, 1, &slot, &size_bits); | 
 |         assert(!error); | 
 |     } | 
 |     error = allocman_fill_reserves(allocman); | 
 |     assert(!error); | 
 | } | 
 |  | 
 | void test_new_1level_cspace_bootinfo() { | 
 |     int error; | 
 |     allocman_t *allocman; | 
 |     cspace_simple1level_t *boot_cspace; | 
 |     cspacepath_t new_path; | 
 |     allocman = bootstrap_new_1level_bootinfo(seL4_GetBootInfo(), 14, sizeof(initial_mem_pool), initial_mem_pool, &boot_cspace); | 
 |     assert(allocman); | 
 |     error = allocman_fill_reserves(allocman); | 
 |     assert(!error); | 
 |     /* test we can easily use our old cspace */ | 
 |     error = cspace_move_alloc_cptr(allocman, cspace_simple1level_make_interface(boot_cspace), seL4_CapInitThreadTCB, &new_path); | 
 |     assert(!error); | 
 |     /* drop our priority */ | 
 |     error = seL4_TCB_SetPriority(new_path.capPtr, new_path.capPtr, 100); | 
 |     assert(error == seL4_NoError); | 
 |     /* no longer need that boot cspace information */ | 
 |     allocman_mspace_free(allocman, boot_cspace, sizeof(*boot_cspace)); | 
 | } | 
 |  | 
 | void test_new_1level_cspace() { | 
 |     bootstrap_info_t *bootstrap; | 
 |     seL4_BootInfo *bi = seL4_GetBootInfo(); | 
 |     cspace_simple1level_t boot_cspace; | 
 |     allocman_t *allocman; | 
 |     cspacepath_t oldroot; | 
 |     cspacepath_t currentroot; | 
 |     cspacepath_t new_path; | 
 |     cspacepath_t tcb; | 
 |     cspacepath_t pd; | 
 |     seL4_CPtr i; | 
 |     int error; | 
 |     bootstrap = bootstrap_create_info(sizeof(initial_mem_pool), initial_mem_pool); | 
 |     assert(bootstrap); | 
 |     /* describe the current cspace */ | 
 |     cspace_simple1level_create(&boot_cspace, (struct cspace_simple1level_config){ | 
 |         .cnode = seL4_CapInitThreadCNode, | 
 |         .cnode_size_bits = bi->initThreadCNodeSizeBits, | 
 |         .cnode_guard_bits = seL4_WordBits - bi->initThreadCNodeSizeBits, | 
 |         .first_slot = bi->empty.start, | 
 |         .end_slot = bi->empty.end - 1 | 
 |     }); | 
 |     /* pass to the boot strapper */ | 
 |     currentroot = _cspace_simple1level_make_path(&boot_cspace, seL4_CapInitThreadCNode); | 
 |     bootstrap_set_boot_cspace(bootstrap, cspace_simple1level_make_interface(&boot_cspace), currentroot); | 
 |     /* give the untypeds to the bootstrapper */ | 
 |     for (i = bi->untyped.start; i < bi->untyped.end; i++) { | 
 |         cspacepath_t slot = _cspace_simple1level_make_path(&boot_cspace, i); | 
 |         uint32_t size_bits = bi->untypedSizeBitsList[i - bi->untyped.start]; | 
 |         uint32_t paddr = bi->untypedPaddrList[i - bi->untyped.start]; | 
 |         error = bootstrap_add_untypeds(bootstrap, 1, &slot, &size_bits, &paddr); | 
 |         assert(!error); | 
 |     } | 
 |     /* bootstrapper has enough information to create */ | 
 |     tcb = _cspace_simple1level_make_path(&boot_cspace, seL4_CapInitThreadTCB); | 
 |     pd = _cspace_simple1level_make_path(&boot_cspace, seL4_CapInitThreadPD); | 
 |     allocman = bootstrap_new_1level(bootstrap, 14, tcb, pd, &oldroot); | 
 |     assert(allocman); | 
 |     /* take advantage of knowledge of simple1level cspace and just shift its root :) */ | 
 |     assert(oldroot.capDepth == 32); | 
 |     boot_cspace.config.cnode = oldroot.capPtr; | 
 |     /* now test we can use it */ | 
 |     error = cspace_move_alloc_cptr(allocman, cspace_simple1level_make_interface(&boot_cspace), seL4_CapInitThreadTCB, &new_path); | 
 |     assert(!error); | 
 |     /* drop our priority */ | 
 |     error = seL4_TCB_SetPriority(new_path.capPtr, new_path.capPtr, 100); | 
 |     assert(error == seL4_NoError); | 
 | } | 
 |  | 
 | void test_new_2level_cspace_bootinfo() { | 
 |     int error; | 
 |     allocman_t *allocman; | 
 |     cspace_simple1level_t *boot_cspace; | 
 |     cspacepath_t new_path; | 
 |     allocman = bootstrap_new_2level_bootinfo(seL4_GetBootInfo(), 6,10, sizeof(initial_mem_pool), initial_mem_pool, &boot_cspace); | 
 |     assert(allocman); | 
 |     error = allocman_fill_reserves(allocman); | 
 |     assert(!error); | 
 |     /* test we can easily use our old cspace */ | 
 |     error = cspace_move_alloc_cptr(allocman, cspace_simple1level_make_interface(boot_cspace), seL4_CapInitThreadTCB, &new_path); | 
 |     assert(!error); | 
 |     /* drop our priority */ | 
 |     error = seL4_TCB_SetPriority(new_path.capPtr, new_path.capPtr, 100); | 
 |     assert(error == seL4_NoError); | 
 |     /* no longer need that boot cspace information */ | 
 |     allocman_mspace_free(allocman, boot_cspace, sizeof(*boot_cspace)); | 
 | } | 
 |  | 
 | void test_new_2level_cspace() { | 
 |     bootstrap_info_t *bootstrap; | 
 |     seL4_BootInfo *bi = seL4_GetBootInfo(); | 
 |     cspace_simple1level_t boot_cspace; | 
 |     allocman_t *allocman; | 
 |     cspacepath_t oldroot; | 
 |     cspacepath_t currentroot; | 
 |     cspacepath_t new_path; | 
 |     cspacepath_t tcb; | 
 |     cspacepath_t pd; | 
 |     seL4_CPtr i; | 
 |     int error; | 
 |     bootstrap = bootstrap_create_info(sizeof(initial_mem_pool), initial_mem_pool); | 
 |     assert(bootstrap); | 
 |     /* describe the current cspace */ | 
 |     cspace_simple1level_create(&boot_cspace, (struct cspace_simple1level_config){ | 
 |         .cnode = seL4_CapInitThreadCNode, | 
 |         .cnode_size_bits = bi->initThreadCNodeSizeBits, | 
 |         .cnode_guard_bits = seL4_WordBits - bi->initThreadCNodeSizeBits, | 
 |         .first_slot = bi->empty.start, | 
 |         .end_slot = bi->empty.end - 1 | 
 |     }); | 
 |     /* pass to the boot strapper */ | 
 |     currentroot = _cspace_simple1level_make_path(&boot_cspace, seL4_CapInitThreadCNode); | 
 |     bootstrap_set_boot_cspace(bootstrap, cspace_simple1level_make_interface(&boot_cspace), currentroot); | 
 |     /* give the untypeds to the bootstrapper */ | 
 |     for (i = bi->untyped.start; i < bi->untyped.end; i++) { | 
 |         cspacepath_t slot = _cspace_simple1level_make_path(&boot_cspace, i); | 
 |         uint32_t size_bits = bi->untypedSizeBitsList[i - bi->untyped.start]; | 
 |         uint32_t paddr = bi->untypedPaddrList[i - bi->untyped.start]; | 
 |         error = bootstrap_add_untypeds(bootstrap, 1, &slot, &size_bits, &paddr); | 
 |         assert(!error); | 
 |     } | 
 |     /* bootstrapper has enough information to create */ | 
 |     tcb = _cspace_simple1level_make_path(&boot_cspace, seL4_CapInitThreadTCB); | 
 |     pd = _cspace_simple1level_make_path(&boot_cspace, seL4_CapInitThreadPD); | 
 |     allocman = bootstrap_new_2level(bootstrap, 6, 10, tcb, pd, &oldroot); | 
 |     assert(allocman); | 
 |     /* take advantage of knowledge of simple1level cspace and just shift its root :) */ | 
 |     assert(oldroot.capDepth == 32); | 
 |     boot_cspace.config.cnode = oldroot.capPtr; | 
 |     /* now test we can use it */ | 
 |     error = cspace_move_alloc_cptr(allocman, cspace_simple1level_make_interface(&boot_cspace), seL4_CapInitThreadTCB, &new_path); | 
 |     assert(!error); | 
 |     /* drop our priority */ | 
 |     error = seL4_TCB_SetPriority(new_path.capPtr, new_path.capPtr, 100); | 
 |     assert(error == seL4_NoError); | 
 | } | 
 |  | 
 | int main(void) { | 
 |     allocman_t *alloc; | 
 |     alloc = test_use_current_cspace_bootinfo(); | 
 | //    test_use_current_1level_cspace(); | 
 | //    test_use_current_cspace(); | 
 | //    test_new_1level_cspace_bootinfo(); | 
 | //    test_new_1level_cspace(); | 
 | //    test_new_2level_cspace_bootinfo(); | 
 | //    test_new_2level_cspace(); | 
 |     printf("All is well in the universe.\n"); | 
 |     while(1); | 
 | } |