4a63af41a6bf90386c8435fcf3199daefed32011
[barrelfish] / usr / init / mem_alloc.c
1 /**
2  * \file
3  * \brief Local memory allocator for init till mem_serv is ready to use
4  */
5
6 /*
7  * Copyright (c) 2007, 2008, 2009, 2011, ETH Zurich.
8  * All rights reserved.
9  *
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.
13  */
14
15 #include "init.h"
16 #include <mm/mm.h>
17
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
26
27 // Number of slots placed in smallcn of mem_serv
28 #define MEM_SERV_SMALLCN_SLOTS 10
29
30 /// MM allocator instance data
31 static struct mm mymm;
32
33 static errval_t mymm_alloc(struct capref *ret, uint8_t bits, uint64_t minbase,
34                            uint64_t maxlimit)
35 {
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);
41     return err;
42 }
43
44 /**
45  * \brief Setups a local memory allocator for init to use till the memory server
46  * is ready to be used.
47  */
48 errval_t initialize_ram_alloc(void)
49 {
50     errval_t err;
51
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_super,
58         .slot = 0,
59     };
60
61     assert(bi != NULL);
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)) {
68                 mem_region = i;
69                 mem_cap.slot = mem_slot;
70                 if (bi->regions[i].mr_bits == MM_REQUIREDBITS) {
71                     break;
72                 }
73             }
74             mem_slot++;
75         }
76     }
77     if (mem_region < 0) {
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;
81     }
82     bi->regions[mem_region].mr_consumed = true;
83
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);
89     }
90
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);
98     }
99
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));
103
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);
109     }
110
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);
115     }
116
117     return SYS_ERR_OK;
118 }