3 * \brief Local memory allocator for init till mem_serv is ready to use
7 * Copyright (c) 2007, 2008, 2009, 2011, ETH Zurich.
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
18 /* parameters for local memory allocator used until we spawn mem_serv */
19 #define MM_REQUIREDBITS 24 ///< Required size of memory to boot (16MB)
20 #define MM_MAXSIZEBITS (MM_REQUIREDBITS + 2) ///< Max size of memory in allocator
21 #define MM_MINSIZEBITS BASE_PAGE_BITS ///< Min size of allocation
22 #define MM_MAXCHILDBITS 1 ///< Max branching factor of BTree nodes
23 #define MM_MAXDEPTH (MM_MAXSIZEBITS - MM_MINSIZEBITS + 1) ///< BTree depth
24 #define MM_NNODES ((1UL << MM_MAXDEPTH) + MM_MINSIZEBITS - OBJBITS_DISPATCHER) ///< Max BTree nodes
25 #define MM_NCNODES DIVIDE_ROUND_UP(MM_NNODES, 1UL << DEFAULT_CNODE_BITS) //CNodes
27 // Number of slots placed in smallcn of mem_serv
28 #define MEM_SERV_SMALLCN_SLOTS 10
30 /// MM allocator instance data
31 static struct mm mymm;
33 static errval_t mymm_alloc(struct capref *ret, uint8_t bits, uint64_t minbase,
36 /* XXX: although we have calculated the space requirements for
37 * MM_MINSIZEBITS, we only ever allocate a single dispatcher from this
38 * allocator, so this should be safe */
39 assert(bits >= OBJBITS_DISPATCHER);
40 errval_t err = mm_alloc(&mymm, bits, ret, NULL);
45 * \brief Setups a local memory allocator for init to use till the memory server
46 * is ready to be used.
48 errval_t initialize_ram_alloc(void)
52 /* walk bootinfo looking for suitable RAM cap to use
53 * we pick the first cap equal to MM_REQUIREDBITS,
54 * or else the next closest less than MM_MAXSIZEBITS */
55 int mem_region = -1, mem_slot = 0;
56 struct capref mem_cap = {
57 .cnode = cnode_super0,
62 for (int i = 0; i < bi->regions_length; i++) {
63 assert(!bi->regions[i].mr_consumed);
64 if (bi->regions[i].mr_type == RegionType_Empty) {
65 if (bi->regions[i].mr_bits >= MM_REQUIREDBITS
66 && bi->regions[i].mr_bits <= MM_MAXSIZEBITS && (mem_region == -1
67 || bi->regions[i].mr_bits < bi->regions[mem_region].mr_bits)) {
69 mem_cap.slot = mem_slot;
70 if (bi->regions[i].mr_bits == MM_REQUIREDBITS) {
78 printf("Error: no RAM capability found in the size range "
79 "2^%d to 2^%d bytes\n", MM_REQUIREDBITS, MM_MAXSIZEBITS);
80 return INIT_ERR_NO_MATCHING_RAM_CAP;
82 bi->regions[mem_region].mr_consumed = true;
84 /* init slot allocator */
85 static struct slot_alloc_basecn init_slot_alloc;
86 err = slot_alloc_basecn_init(&init_slot_alloc);
87 if (err_is_fail(err)) {
88 return err_push(err, MM_ERR_SLOT_ALLOC_INIT);
91 /* init MM allocator */
92 assert(bi->regions[mem_region].mr_type != RegionType_Module);
93 err = mm_init(&mymm, ObjType_RAM, bi->regions[mem_region].mr_base,
94 bi->regions[mem_region].mr_bits, MM_MAXCHILDBITS, NULL,
95 slot_alloc_basecn, &init_slot_alloc, true);
96 if (err_is_fail(err)) {
97 return err_push(err, MM_ERR_MM_INIT);
100 /* give MM allocator enough static storage for its node allocator */
101 static char nodebuf[SLAB_STATIC_SIZE(MM_NNODES, MM_NODE_SIZE(MM_MAXCHILDBITS))];
102 slab_grow(&mymm.slabs, nodebuf, sizeof(nodebuf));
104 /* add single RAM cap to allocator */
105 err = mm_add(&mymm, mem_cap, bi->regions[mem_region].mr_bits,
106 bi->regions[mem_region].mr_base);
107 if (err_is_fail(err)) {
108 return err_push(err, MM_ERR_MM_ADD);
111 // initialise generic RAM allocator to use local allocator
112 err = ram_alloc_set(mymm_alloc);
113 if (err_is_fail(err)) {
114 return err_push(err, LIB_ERR_RAM_ALLOC_SET);