Sanitize vcoreid from untrusted sources
[akaros.git] / kern / src / arena.c
1 /* Copyright (c) 2016 Google Inc
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Arena resource allocator, based on Bonwick and Adams's "Magazines and Vmem:
6  * Extending the Slab Allocator to Many CPUs and Arbitrary Resources".
7  *
8  * There are two major arenas (or arena types; see the NUMA discussion below):
9  * base_arena and kpages_arena.  The base_arena consists of all the virtual
10  * addresses of the KERNBASE mapping, and is entirely self-sufficient.  Some
11  * slab caches pull directly from this arena.  The kpages_arena pulls from the
12  * base_arena and adds a level of quantum/slab caching.  Most users will pull
13  * from kpages_arena.
14  *
15  * For jumbo pages, you'd think we'd want a larger page sizes to be the source
16  * for the smaller page size arenas.  E.g. 'base' is a PML3 allocator.  The
17  * problem with that is that a base allocator needs to be self-sufficient, which
18  * means it needs to allocate its own boundary tags.  We'd prefer to use a small
19  * page for that.  So instead, we can flip the hierarchy around.  A base
20  * allocator uses a PGSIZE quantum, and the jumbo allocators are source from
21  * the base arena using an aligned allocation helper for its afunc.  I think,
22  * without a lot of thought, that the fragmentation would be equivalent.
23  *
24  * In the future, we can set up N base_arenas, one for each NUMA domain, each of
25  * which is a source for other NUMA allocators, e.g. kpages_i_arena.  Higher
26  * level allocators (kmalloc()) will need to choose a NUMA domain and call into
27  * the correct allocator.  Each NUMA base arena is self-sufficient: they have no
28  * qcaches and their BTs come from their own free page list.  This just
29  * replicates the default memory allocator across each NUMA node, and at some
30  * point, some generic allocator software needs to pick which node to pull from.
31  * I tried to keep assumptions about a single base_arena to a minimum, but
32  * you'll see some places where the arena code needs to find some base arena for
33  * its BT allocations.  Also note that the base setup happens before we know
34  * about NUMA domains.  The plan is to do a small part of domain 0 during
35  * pmem_init(), then once we know the full memory layout, add in the rest of
36  * domain 0's memory and bootstrap the other domains.
37  *
38  * When it comes to importing spans, it's not clear whether or not we should
39  * import exactly the current allocation request or to bring in more.  If we
40  * don't bring in more, then a child arena will have a span for every allocation
41  * and will return that span to the source whenever the segment is freed.  We'll
42  * never get the Figure 4.4 from the Vmem paper.  Alternatively, we could either
43  * allow partial frees of segments or we could hang on to completely free spans
44  * for a *while*, and possibly require a reclaim callback.  In the meantime, I
45  * added a per-arena scaling factor where we can adjust how much we import.
46  *
47  * TODO:
48  * - Blocking.  We'll probably want to reserve some memory for emergencies to
49  *   help us get out of OOM.  So we might block when we're at low-mem, not at 0.
50  *   We probably should have a sorted list of desired amounts, and unblockers
51  *   poke the CV if the first waiter is likely to succeed.
52  * - Reclaim: have a ktask that sleeps on a rendez.  We poke it, even from IRQ
53  *   context.  It qlocks arenas_and_slabs_lock, then does the reclaim.
54  *
55  * FAQ:
56  * - Does allocating memory from an arena require it to take a btag?  Yes -
57  *   unless the allocation is for the exact size of an existing btag/segment.
58  * - Why does arena_free() need size?  Isn't it just for sanity checks?  No - it
59  *   is also used to determine which slab/qcache to return the segment to.
60  * - Why does a jumbo page arena use its own import function, instead of just
61  *   xallocing from kpages with alignment?  Because of fragmentation.  kpages
62  *   pulls directly from base, using a normal alloc for its import function
63  *   (afunc).  Because of this, its xalloc needs to request size + align, which
64  *   will fragment base.  It's better for jumbo to call xalloc directly on base,
65  *   in essence pushing the aligned alloc as far down the stack as possible.
66  * - Does the stuff in a qcache (allocated or free/available) count against the
67  *   arena's total/free amounts?  No, at least not the way I did it.  That's why
68  *   it's called amt_total_segs: segments, not free memory.  Those slab/qcaches
69  *   will have their own stats, and it'd be a minor pain to sync up with them
70  *   all the time.  Also, the important stat is when the base arena starts to
71  *   run out of memory, and base arenas don't have qcaches, so it's moot.
72  */
73
74 #include <arena.h>
75 #include <kmalloc.h>
76 #include <string.h>
77 #include <stdio.h>
78 #include <hash.h>
79 #include <slab.h>
80 #include <kthread.h>
81
82 struct arena_tailq all_arenas = TAILQ_HEAD_INITIALIZER(all_arenas);
83 qlock_t arenas_and_slabs_lock = QLOCK_INITIALIZER(arenas_and_slabs_lock);
84
85 struct arena *base_arena;
86 struct arena *kpages_arena;
87
88 /* Misc helpers and forward declarations */
89 static struct btag *__get_from_freelists(struct arena *arena, int list_idx);
90 static bool __account_alloc(struct arena *arena, struct btag *bt, size_t size,
91                             struct btag *new);
92 static void *__xalloc_nextfit(struct arena *arena, size_t size, size_t align,
93                               size_t phase, size_t nocross);
94 static void __try_hash_resize(struct arena *arena, int flags,
95                               void **to_free_addr, size_t *to_free_sz);
96 static void __arena_asserter(struct arena *arena);
97 void print_arena_stats(struct arena *arena, bool verbose);
98
99 /* For NUMA situations, where there are multiple base arenas, we'll need a way
100  * to find *some* base arena.  Ideally, it'll be in the same NUMA domain as
101  * arena. */
102 static struct arena *find_my_base(struct arena *arena)
103 {
104         /* TODO: could walk down sources until is_base is set.  But barring
105          * that, we'd still need a way to find a base arena for some other
106          * allocator that just wants a page.  arena may be NULL, so handle that.
107          * */
108         return base_arena;
109 }
110
111 static void setup_qcaches(struct arena *arena, size_t quantum,
112                           size_t qcache_max)
113 {
114         int nr_qcaches = qcache_max / quantum;
115         char kc_name[KMC_NAME_SZ];
116         size_t qc_size;
117
118         if (!nr_qcaches)
119                 return;
120
121         /* TODO: same as with hash tables, here and in slab.c, we ideally want
122          * the nearest kpages arena, but bootstrappers need to use base_alloc.
123          * */
124         arena->qcaches = base_alloc(arena,
125                                     nr_qcaches * sizeof(struct kmem_cache),
126                                     MEM_WAIT);
127         for (int i = 0; i < nr_qcaches; i++) {
128                 qc_size = (i + 1) * quantum;
129                 snprintf(kc_name, KMC_NAME_SZ, "%s_%d", arena->name, qc_size);
130                 __kmem_cache_create(&arena->qcaches[i], kc_name, qc_size,
131                                     quantum, KMC_NOTOUCH | KMC_QCACHE, arena,
132                                     NULL, NULL, NULL);
133         }
134 }
135
136 /* Helper to init.  Split out from create so we can bootstrap. */
137 static void arena_init(struct arena *arena, char *name, size_t quantum,
138                        void *(*afunc)(struct arena *, size_t, int),
139                        void (*ffunc)(struct arena *, void *, size_t),
140                        struct arena *source, size_t qcache_max)
141 {
142         static_assert((ARENA_ALLOC_STYLES & MEM_FLAGS) == 0);
143
144         spinlock_init_irqsave(&arena->lock);
145         arena->import_scale = 0;
146         arena->is_base = FALSE;
147         if (qcache_max % quantum)
148                 panic("Arena %s, qcache_max %p must be a multiple of quantum %p",
149                       name, qcache_max, quantum);
150         arena->quantum = quantum;
151         arena->qcache_max = qcache_max;
152         arena->afunc = afunc;
153         arena->ffunc = ffunc;
154         arena->source = source;
155         if (source)
156                 assert(afunc && ffunc);
157         arena->amt_total_segs = 0;
158         arena->amt_alloc_segs = 0;
159         arena->nr_allocs_ever = 0;
160
161         arena->all_segs = RB_ROOT;
162         BSD_LIST_INIT(&arena->unused_btags);
163         for (int i = 0; i < ARENA_NR_FREE_LISTS; i++)
164                 BSD_LIST_INIT(&arena->free_segs[i]);
165
166         arena->alloc_hash = arena->static_hash;
167         hash_init_hh(&arena->hh);
168         for (int i = 0; i < arena->hh.nr_hash_lists; i++)
169                 BSD_LIST_INIT(&arena->static_hash[i]);
170
171         TAILQ_INIT(&arena->__importing_arenas);
172         TAILQ_INIT(&arena->__importing_slabs);
173
174         strlcpy(arena->name, name, ARENA_NAME_SZ);
175         setup_qcaches(arena, quantum, qcache_max);
176
177         if (source)
178                 add_importing_arena(source, arena);
179         qlock(&arenas_and_slabs_lock);
180         TAILQ_INSERT_TAIL(&all_arenas, arena, next);
181         qunlock(&arenas_and_slabs_lock);
182 }
183
184 struct arena *arena_create(char *name, void *base, size_t size, size_t quantum,
185                            void *(*afunc)(struct arena *, size_t, int),
186                            void (*ffunc)(struct arena *, void *, size_t),
187                            struct arena *source, size_t qcache_max, int flags)
188 {
189         struct arena *arena;
190
191         /* See note in arena_add() */
192         if (source && base)
193                 panic("Arena can't have both a source and an initial span");
194         arena = kmalloc(sizeof(struct arena), flags);
195         if (!arena)
196                 return 0;
197         arena_init(arena, name, quantum, afunc, ffunc, source, qcache_max);
198         if (base) {
199                 if (!arena_add(arena, base, size, flags)) {
200                         warn("Failed to add base to arena %s, aborting!",
201                              arena->name);
202                         arena_destroy(arena);
203                         return 0;
204                 }
205         }
206         return arena;
207 }
208
209 void arena_destroy(struct arena *arena)
210 {
211         struct btag *bt_i, *temp;
212
213         qlock(&arenas_and_slabs_lock);
214         TAILQ_REMOVE(&all_arenas, arena, next);
215         qunlock(&arenas_and_slabs_lock);
216         if (arena->source)
217                 del_importing_arena(arena->source, arena);
218
219         for (int i = 0; i < arena->hh.nr_hash_lists; i++)
220                 assert(BSD_LIST_EMPTY(&arena->alloc_hash[i]));
221         if (arena->alloc_hash != arena->static_hash)
222                 kfree(arena->alloc_hash);
223         /* We shouldn't have any spans left.  We can tell we messed up if we had
224          * a source and still have some free segments.  Otherwise, just collect
225          * the free tags on the unused btag list. */
226         for (int i = 0; i < ARENA_NR_FREE_LISTS; i++) {
227                 if (arena->source)
228                         assert(BSD_LIST_EMPTY(&arena->free_segs[i]));
229                 BSD_LIST_FOREACH_SAFE(bt_i, &arena->free_segs[i], misc_link,
230                                       temp) {
231                         BSD_LIST_REMOVE(bt_i, misc_link);
232                         BSD_LIST_INSERT_HEAD(&arena->unused_btags, bt_i,
233                                              misc_link);
234                 }
235         }
236         /* To free our BTs, we need to give the page back to the base arena.
237          * The BTs that are page aligned are the ones we want.  We can just
238          * ignore the others (unlink from the list). */
239         BSD_LIST_FOREACH_SAFE(bt_i, &arena->unused_btags, misc_link, temp) {
240                 if (PGOFF(bt_i->start))
241                         BSD_LIST_REMOVE(bt_i, misc_link);
242         }
243         /* Now the remaining BTs are the first on their page. */
244         BSD_LIST_FOREACH_SAFE(bt_i, &arena->unused_btags, misc_link, temp)
245                 arena_free(find_my_base(arena), (void*)bt_i->start, PGSIZE);
246         kfree(arena);
247 }
248
249 static void __insert_btag(struct rb_root *root, struct btag *bt)
250 {
251         struct rb_node **new = &root->rb_node, *parent = NULL;
252         struct btag *node;
253
254         while (*new) {
255                 node = container_of(*new, struct btag, all_link);
256                 parent = *new;
257                 /* Span (BTAG_SPAN) nodes are ahead (less than) of regular
258                  * segment nodes (BTAG_FREE or BTAG_ALLOC) that have the same
259                  * start. */
260                 if (bt->start < node->start)
261                         new = &parent->rb_left;
262                 else if (bt->start > node->start)
263                         new = &parent->rb_right;
264                 else if (node->status == BTAG_SPAN)
265                         new = &parent->rb_right;
266                 else
267                         panic("BT %p already in tree %p!", bt, root);
268         }
269         rb_link_node(&bt->all_link, parent, new);
270         rb_insert_color(&bt->all_link, root);
271 }
272
273 /* Helper: tracks a seg pointed to by @bt as being allocated, assuming it is
274  * already off the free list (or was never on).  This doesn't do anything with
275  * all_segs; that's someone else's job (usually bt is already on it). */
276 static void __track_alloc_seg(struct arena *arena, struct btag *bt)
277 {
278         size_t hash_idx;
279
280         bt->status = BTAG_ALLOC;
281         hash_idx = hash_long(bt->start, arena->hh.nr_hash_bits);
282         BSD_LIST_INSERT_HEAD(&arena->alloc_hash[hash_idx], bt, misc_link);
283         arena->hh.nr_items++;
284 }
285
286 /* Helper: untracks a seg pointed to by @bt as being allocated.  Basically,
287  * removes it from the alloc_hash. */
288 static struct btag *__untrack_alloc_seg(struct arena *arena, uintptr_t start)
289 {
290         size_t hash_idx;
291         struct btag *bt_i;
292
293         hash_idx = hash_long(start, arena->hh.nr_hash_bits);
294         BSD_LIST_FOREACH(bt_i, &arena->alloc_hash[hash_idx], misc_link) {
295                 if (bt_i->start == start) {
296                         BSD_LIST_REMOVE(bt_i, misc_link);
297                         assert(bt_i->status == BTAG_ALLOC);
298                         arena->hh.nr_items--;
299                         return bt_i;
300                 }
301         }
302         return NULL;
303 }
304
305 /* Helper, tries to resize our hash table, if necessary.  Call with the lock
306  * held, but beware that this will unlock and relock - meaning, don't rely on
307  * the lock to protect invariants, but hold it as an optimization.
308  *
309  * A lot of the nastiness here is related to the allocation.  Critically, we
310  * might be the base arena, so it'd be nice to unlock before calling into
311  * ourselves (o/w deadlock).  Likewise, we'd like to be able to do a blocking
312  * allocation, if flags has MEM_WAIT.  We'd need to unlock for that too. */
313 static void __try_hash_resize(struct arena *arena, int flags,
314                               void **to_free_addr, size_t *to_free_sz)
315 {
316         struct btag_list *new_tbl, *old_tbl;
317         struct btag *bt_i;
318         unsigned int new_tbl_nr_lists, old_tbl_nr_lists;
319         size_t new_tbl_sz, old_tbl_sz;
320         size_t hash_idx;
321
322         if (!hash_needs_more(&arena->hh))
323                 return;
324         new_tbl_nr_lists = hash_next_nr_lists(&arena->hh);
325         /* We want future checkers to not think we need an increase, to avoid
326          * excessive hash resizers as well as base arena deadlocks (base_alloc
327          * must not call into base_alloc infinitely) */
328         hash_set_load_limit(&arena->hh, SIZE_MAX);
329         spin_unlock_irqsave(&arena->lock);
330         new_tbl_sz = new_tbl_nr_lists * sizeof(struct btag_list);
331         /* Regardless of the caller's style, we'll try and be quick with
332          * INSTANT. */
333         flags &= ~ARENA_ALLOC_STYLES;
334         flags |= ARENA_INSTANTFIT;
335         new_tbl = base_zalloc(arena, new_tbl_sz, flags);
336         spin_lock_irqsave(&arena->lock);
337         if (!new_tbl) {
338                 /* Need to reset so future callers will try to grow. */
339                 hash_reset_load_limit(&arena->hh);
340                 spin_unlock_irqsave(&arena->lock);
341                 return;
342         }
343         /* After relocking, we need to re-verify that we want to go ahead.  It's
344          * possible that another thread resized the hash already, which we can
345          * detect because our alloc size is wrong. */
346         if (new_tbl_nr_lists != hash_next_nr_lists(&arena->hh)) {
347                 spin_unlock_irqsave(&arena->lock);
348                 base_free(arena, new_tbl, new_tbl_sz);
349                 return;
350         }
351         old_tbl = arena->alloc_hash;
352         old_tbl_nr_lists = arena->hh.nr_hash_lists;
353         old_tbl_sz = old_tbl_nr_lists * sizeof(struct btag_list);
354         arena->alloc_hash = new_tbl;
355         hash_incr_nr_lists(&arena->hh);
356         for (int i = 0; i < old_tbl_nr_lists; i++) {
357                 while ((bt_i = BSD_LIST_FIRST(&old_tbl[i]))) {
358                         BSD_LIST_REMOVE(bt_i, misc_link);
359                         hash_idx = hash_long(bt_i->start,
360                                              arena->hh.nr_hash_bits);
361                         BSD_LIST_INSERT_HEAD(&arena->alloc_hash[hash_idx], bt_i,
362                                              misc_link);
363                 }
364         }
365         hash_reset_load_limit(&arena->hh);
366         if (old_tbl != arena->static_hash) {
367                 *to_free_addr = old_tbl;
368                 *to_free_sz = old_tbl_sz;
369         }
370 }
371
372 /* Typically this will be just checking for one or two BTs on the free list */
373 static bool __has_enough_btags(struct arena *arena, size_t nr_needed)
374 {
375         struct btag *bt_i;
376         size_t so_far = 0;
377
378         BSD_LIST_FOREACH(bt_i, &arena->unused_btags, misc_link) {
379                 so_far++;
380                 if (so_far == nr_needed)
381                         return TRUE;
382         }
383         return FALSE;
384 }
385
386 /* Allocs new boundary tags and puts them on the arena's free list.  Returns 0
387  * on failure, which could happen if MEM_ATOMIC is set).  Hold the lock when you
388  * call this, but note it will unlock and relock.
389  *
390  * The base arena is special in that it must be self-sufficient.  It will create
391  * get its free page from itself.  Other arena's just pull from base in the
392  * normal fashion.  We could pull from kpages_arena, but that would require a
393  * little more special casing.  Maybe in the future.
394  *
395  * Note that BTs are only freed when the arena is destroyed.  We use the fact
396  * that the first BT is at an aligned address to track the specific page it came
397  * from. */
398 static struct btag *__add_more_btags(struct arena *arena, int mem_flags)
399 {
400         struct btag *bt, *tags;
401         size_t nr_bts = PGSIZE / sizeof(struct btag);
402
403         if (arena->is_base) {
404                 bt = __get_from_freelists(arena, LOG2_UP(PGSIZE));
405                 if (!bt) {
406                         /* TODO: block / reclaim if not MEM_ATOMIC.  Remember,
407                          * we hold the lock!  We might need to rework this or
408                          * get a reserved page. */
409                         if (!(mem_flags & MEM_ATOMIC))
410                                 panic("Base failed to alloc its own btag, OOM");
411                         return 0;
412                 }
413                 /* __account_alloc() will often need a new BT; specifically when
414                  * we only need part of the segment tracked by the BT.  Since we
415                  * don't have any extra BTs, we'll use the first one on the page
416                  * we just allocated. */
417                 tags = (struct btag*)bt->start;
418                 if (__account_alloc(arena, bt, PGSIZE, &tags[0])) {
419                         /* We used the tag[0]; we'll have to skip over it now.*/
420                         tags++;
421                         nr_bts--;
422                 }
423         } else {
424                 /* Here's where we unlock and relock around a blocking call */
425                 spin_unlock_irqsave(&arena->lock);
426                 tags = arena_alloc(find_my_base(arena), PGSIZE,
427                                    mem_flags | ARENA_INSTANTFIT);
428                 spin_lock_irqsave(&arena->lock);
429                 if (!tags)
430                         return 0;
431         }
432         for (int i = 0; i < nr_bts; i++)
433                 BSD_LIST_INSERT_HEAD(&arena->unused_btags, &tags[i], misc_link);
434         return tags;
435 }
436
437 /* Helper, returns TRUE when we have enough BTs.  Hold the lock, but note this
438  * will unlock and relock, and will attempt to acquire more BTs.  Returns FALSE
439  * if an alloc failed (MEM_ATOMIC).
440  *
441  * This complexity is so that we never fail an arena operation due to lack of
442  * memory unless the caller has MEM_ATOMIC set.  Further, __get_btag() never
443  * fails, which makes other code easier.  Otherwise, functions that currently
444  * call __get_btag will need one or two BTs passed in from their callers, who
445  * allocate/remove from the list at a place where they can easily fail. */
446 static bool __get_enough_btags(struct arena *arena, size_t nr_needed,
447                                int mem_flags)
448 {
449         if (__has_enough_btags(arena, nr_needed))
450                 return TRUE;
451         /* This will unlock and relock, and maybe block. */
452         if (!__add_more_btags(arena, mem_flags)) {
453                 /* This is the only failure scenario */
454                 assert(mem_flags & MEM_ATOMIC);
455                 return FALSE;
456         }
457         /* Since the lock was held in __add_more_btags, no one should have been
458          * able to drain them.  If someone asked for more than a page worth of
459          * BTs, there's a problem somewhere else. */
460         assert(__has_enough_btags(arena, nr_needed));
461         return TRUE;
462 }
463
464 /* Helper: gets a btag.  All callpaths must have made sure the arena has enough
465  * tags before starting its operation, holding the lock throughout.  Thus, this
466  * cannot fail. */
467 static struct btag *__get_btag(struct arena *arena)
468 {
469         struct btag *ret;
470
471         ret = BSD_LIST_FIRST(&arena->unused_btags);
472         /* All code paths should have made sure that there were enough BTs
473          * before diving in. */
474         assert(ret);
475         BSD_LIST_REMOVE(ret, misc_link);
476         return ret;
477 }
478
479 static void __free_btag(struct arena *arena, struct btag *bt)
480 {
481         BSD_LIST_INSERT_HEAD(&arena->unused_btags, bt, misc_link);
482 }
483
484 /* Helper: adds seg pointed to by @bt to the appropriate free list of @arena. */
485 static void __track_free_seg(struct arena *arena, struct btag *bt)
486 {
487         int list_idx = LOG2_DOWN(bt->size);
488
489         bt->status = BTAG_FREE;
490         BSD_LIST_INSERT_HEAD(&arena->free_segs[list_idx], bt, misc_link);
491 }
492
493 /* Helper: removes seg pointed to by @bt from the appropriate free list of
494  * @arena. */
495 static void __untrack_free_seg(struct arena *arena, struct btag *bt)
496 {
497         BSD_LIST_REMOVE(bt, misc_link);
498 }
499
500 /* Helper: we decided we want to alloc part of @bt, which has been removed from
501  * its old list.  We need @size units.  The rest can go back to the arena.
502  *
503  * Takes @new, which we'll use if we need a new btag.  If @new is NULL, we'll
504  * allocate one.  If we used the caller's btag, we'll return TRUE.  This
505  * complexity is for a base arena's manual btag allocation. */
506 static bool __account_alloc(struct arena *arena, struct btag *bt,
507                             size_t size, struct btag *new)
508 {
509         bool ret = FALSE;
510
511         assert(bt->status == BTAG_FREE);
512         if (bt->size != size) {
513                 assert(bt->size > size);
514                 if (new)
515                         ret = TRUE;
516                 else
517                         new = __get_btag(arena);
518                 new->start = bt->start + size;
519                 new->size = bt->size - size;
520                 bt->size = size;
521                 __track_free_seg(arena, new);
522                 __insert_btag(&arena->all_segs, new);
523         }
524         __track_alloc_seg(arena, bt);
525         arena->amt_alloc_segs += size;
526         arena->nr_allocs_ever++;
527         return ret;
528 }
529
530 /* Helper: gets the first segment from the smallest, populated list. */
531 static struct btag *__get_from_freelists(struct arena *arena, int list_idx)
532 {
533         struct btag *ret = NULL;
534
535         for (int i = list_idx; i < ARENA_NR_FREE_LISTS; i++) {
536                 ret = BSD_LIST_FIRST(&arena->free_segs[i]);
537                 if (ret) {
538                         BSD_LIST_REMOVE(ret, misc_link);
539                         break;
540                 }
541         }
542         return ret;
543 }
544
545 /* Allocates using the 'best fit' policy.  Recall that each free_segs list holds
546  * segments of size [ 2^n, 2^(n+1) )  We try to find the smallest segment on
547  * that list that can satisfy the request.  Otherwise, any segment from a larger
548  * list will suffice. */
549 static void *__alloc_bestfit(struct arena *arena, size_t size)
550 {
551         int list_idx = LOG2_DOWN(size);
552         struct btag *bt_i, *best = NULL;
553
554         BSD_LIST_FOREACH(bt_i, &arena->free_segs[list_idx], misc_link) {
555                 if (bt_i->size >= size) {
556                         if (!best || (best->size > bt_i->size))
557                                 best = bt_i;
558                 }
559         }
560         if (best)
561                 BSD_LIST_REMOVE(best, misc_link);
562         else
563                 best = __get_from_freelists(arena, list_idx + 1);
564         if (!best)
565                 return NULL;
566         __account_alloc(arena, best, size, NULL);
567         return (void*)best->start;
568 }
569
570 static void *__alloc_nextfit(struct arena *arena, size_t size)
571 {
572         return __xalloc_nextfit(arena, size, arena->quantum, 0, 0);
573 }
574
575 /* Instant fit grabs the first segment guaranteed to be big enough.  Note that
576  * we round list_idx up, compared to bestfit's initial list.  That way, you're
577  * always sure you have a big enough segment. */
578 static void *__alloc_instantfit(struct arena *arena, size_t size)
579 {
580         struct btag *ret;
581
582         ret = __get_from_freelists(arena, LOG2_UP(size));
583         if (!ret)
584                 return NULL;
585         __account_alloc(arena, ret, size, NULL);
586         return (void*)ret->start;
587 }
588
589 /* Non-qcache allocation.  Hold the arena's lock.  Note that all allocations are
590  * done in multiples of the quantum. */
591 static void *alloc_from_arena(struct arena *arena, size_t size, int flags)
592 {
593         void *ret;
594         void *to_free_addr = 0;
595         size_t to_free_sz = 0;
596
597         spin_lock_irqsave(&arena->lock);
598         if (!__get_enough_btags(arena, 1, flags & MEM_FLAGS)) {
599                 spin_unlock_irqsave(&arena->lock);
600                 return NULL;
601         }
602         if (flags & ARENA_BESTFIT)
603                 ret = __alloc_bestfit(arena, size);
604         else if (flags & ARENA_NEXTFIT)
605                 ret = __alloc_nextfit(arena, size);
606         else
607                 ret = __alloc_instantfit(arena, size);
608         /* Careful, this will unlock and relock.  It's OK right before an
609          * unlock. */
610         __try_hash_resize(arena, flags, &to_free_addr, &to_free_sz);
611         spin_unlock_irqsave(&arena->lock);
612         if (to_free_addr)
613                 base_free(arena, to_free_addr, to_free_sz);
614         return ret;
615 }
616
617 /* It's probably a kernel bug if we're adding the wrong sized segments, whether
618  * via direct add, a source import, or creation. */
619 static void assert_quantum_alignment(struct arena *arena, void *base,
620                                      size_t size)
621 {
622         if (!ALIGNED(base, arena->quantum))
623                 panic("Unaligned base %p for arena %s, quantum %p, source %s",
624                       base, arena->name, arena->quantum,
625                       arena->source ? arena->source->name : "none");
626         if (!ALIGNED(size, arena->quantum))
627                 panic("Unaligned size %p for arena %s, quantum %p, source %s",
628                       size, arena->name, arena->quantum,
629                       arena->source ? arena->source->name : "none");
630 }
631
632 /* Adds segment [@base, @base + @size) to @arena.  We'll add a span tag if the
633  * arena had a source. */
634 static void *__arena_add(struct arena *arena, void *base, size_t size,
635                          int flags)
636 {
637         struct btag *bt, *span_bt;
638
639         /* These are just sanity checks.  Our client is the kernel, and it could
640          * mess with us in other ways, such as adding overlapping spans. */
641         assert_quantum_alignment(arena, base, size);
642         assert(base < base + size);
643         spin_lock_irqsave(&arena->lock);
644         /* Make sure there are two, bt and span. */
645         if (!__get_enough_btags(arena, 2, flags & MEM_FLAGS)) {
646                 spin_unlock_irqsave(&arena->lock);
647                 return NULL;
648         }
649         bt = __get_btag(arena);
650         if (arena->source) {
651                 span_bt = __get_btag(arena);
652                 span_bt->start = (uintptr_t)base;
653                 span_bt->size = size;
654                 span_bt->status = BTAG_SPAN;
655                 /* Note the btag span is not on any list, but it is in all_segs
656                  */
657                 __insert_btag(&arena->all_segs, span_bt);
658         }
659         bt->start = (uintptr_t)base;
660         bt->size = size;
661         arena->amt_total_segs += size;
662         __track_free_seg(arena, bt);
663         __insert_btag(&arena->all_segs, bt);
664         spin_unlock_irqsave(&arena->lock);
665         return base;
666 }
667
668 /* Adds segment [@base, @base + @size) to @arena. */
669 void *arena_add(struct arena *arena, void *base, size_t size, int flags)
670 {
671         /* This wasn't clear from the paper, but mixing source spans and
672          * manually added spans seems like a pain when coalescing BTs and
673          * freeing. */
674         if (arena->source)
675                 panic("Arenas with sources must not manually add resources.");
676         return __arena_add(arena, base, size, flags);
677 }
678
679 /* Attempt to get more resources, either from a source or by blocking.  Returns
680  * TRUE if we got something.  FALSE on failure (e.g. MEM_ATOMIC). */
681 static bool get_more_resources(struct arena *arena, size_t size, int flags)
682 {
683         void *span;
684         size_t import_size;
685
686         /* MAX check, in case size << scale overflows */
687         import_size = MAX(size, size << arena->import_scale);
688         if (arena->source) {
689                 span = arena->afunc(arena->source, import_size, flags);
690                 if (!span)
691                         return FALSE;
692                 if (!__arena_add(arena, span, import_size, flags)) {
693                         /* We could fail if MEM_ATOMIC and we couldn't get a BT
694                          */
695                         warn("Excessively rare failure, tell brho");
696                         arena->ffunc(arena->source, span, import_size);
697                         return FALSE;
698                 }
699         } else {
700                 /* TODO: allow blocking */
701                 if (!(flags & MEM_ATOMIC))
702                         panic("OOM!");
703                 return FALSE;
704         }
705         return TRUE;
706 }
707
708 /* Helper.  For a given size, return the applicable qcache. */
709 static struct kmem_cache *size_to_qcache(struct arena *arena, size_t size)
710 {
711         /* If we ever get grumpy about the costs of dividing (both here and in
712          * the ROUND ops, we could either insist that quantum is a power of two,
713          * or track whether or not it is and use other shifting ops. */
714         return &arena->qcaches[(size / arena->quantum) - 1];
715 }
716
717 void *arena_alloc(struct arena *arena, size_t size, int flags)
718 {
719         void *ret;
720
721         size = ROUNDUP(size, arena->quantum);
722         if (!size)
723                 panic("Arena %s, request for zero", arena->name);
724         if (size <= arena->qcache_max) {
725                 /* NEXTFIT is an error, since free won't know to skip the qcache
726                  * and then we'd be handing an item to the qcache that it didn't
727                  * alloc. */
728                 if (flags & ARENA_NEXTFIT)
729                         panic("Arena %s, NEXTFIT, but has qcaches. Use xalloc.",
730                               arena->name);
731                 return kmem_cache_alloc(size_to_qcache(arena, size), flags);
732         }
733         while (1) {
734                 ret = alloc_from_arena(arena, size, flags);
735                 if (ret)
736                         return ret;
737                 /* This is a little nasty.  We asked our source for enough, but
738                  * it may be a bestfit sized chunk, not an instant fit.  Since
739                  * we already failed once, we can just downgrade to BESTFIT,
740                  * which will likely find our recently-allocated span.  Even
741                  * worse, the source might only give us segments that are
742                  * BESTFIT, and if we only look at the INSTANTFIT, we'll keep
743                  * looping.  The invariant here is that if we
744                  * get_more_resources, then our allocation can succeed if no one
745                  * else grabs that memory first.
746                  *
747                  * We actually have two options here.  Either we downgrade to
748                  * BESTFIT or we round up our request to our source to the
749                  * nearest power of two.  Doing so brings some of the
750                  * fragmentation into our arena, but an instant fit is likely to
751                  * succeed.  Considering how the first item on the BESTFIT list
752                  * is likely ours, downgrading makes sense. */
753                 flags &= ~ARENA_ALLOC_STYLES;
754                 flags |= ARENA_BESTFIT;
755                 if (!get_more_resources(arena, size, flags))
756                         return NULL;
757         }
758 }
759
760 /* Helper: given a BT's start and size, return a starting address within the BT
761  * that satisfies the constraints.  Returns 0 on failure.
762  *
763  * The rough idea is to go from the start, round up to align, add the phase, and
764  * see if it's still within the BT.  The 'nocross' boundary (also an alignment)
765  * complicates things a little. */
766 static uintptr_t __find_sufficient(uintptr_t bt_start, size_t bt_size,
767                                    size_t size, size_t align,
768                                    size_t phase, size_t nocross)
769 {
770         uintptr_t try;
771         size_t try_size;
772
773         try = bt_start;
774         try = ROUNDUP(try, align);
775         try += phase;
776         /* Wraparound due to phase. */
777         if (try < bt_start)
778                 return 0;
779         /* Check wraparound */
780         if (try + size < try)
781                 return 0;
782         /* Too big for BT, no chance. */
783         if (try + size > bt_start + bt_size)
784                 return 0;
785         if (nocross == 0)
786                 return try;
787         /* Got to deal with nocross boundaries.  If we round up from our
788          * potential start and that is beyond our potential finish, we're OK. */
789         if (ROUNDUP(try, nocross) >= try + size)
790                 return try;
791         /* The segment still might have a chance.  Perhaps we started right
792          * before a nocross.  Let's try again, being careful of overflow.  The
793          * ROUNDUP shouldn't trigger a wraparound. */
794         try = ROUNDUP(bt_start, nocross);
795         try_size = bt_size - (try - bt_start);
796         /* Underflow of bt_size - large_number. */
797         if (try_size > bt_size)
798                 return 0;
799         /* The caller has some control over our next invocation's bt_start and
800          * bt_size.  Let's enforce sanity. */
801         if (try + try_size < try)
802                 return 0;
803         return __find_sufficient(try, try_size, size, align, phase, 0);
804 }
805
806 /* Helper: splits bt, which is not on any freelist, at @at, and puts the front
807  * part back on a free list. */
808 static void __split_bt_at(struct arena *arena, struct btag *bt, uintptr_t at)
809 {
810         struct btag *front = __get_btag(arena);
811
812         /* We're changing bt's start, which is its key for its position in the
813          * all_segs tree.  However, we don't need to remove and reinsert it,
814          * since although we increased its start, we know that no BT should be
815          * between its old start and its new start.  That's actually where the
816          * front BT will get inserted (so long as we insert after changing bt's
817          * start). */
818         front->status = BTAG_FREE;
819         front->start = bt->start;
820         front->size = at - bt->start;
821         bt->start += front->size;
822         bt->size -= front->size;
823         __track_free_seg(arena, front);
824         __insert_btag(&arena->all_segs, front);
825         /* At this point, bt's old space in all_segs is broken into: front:
826          * [old_start, try), bt: [try, old_end).  front is on the free list.  bt
827          * is not. */
828 }
829
830 /* Helper.  We want the first bt >= mindaddr, with prev < minaddr. */
831 static bool __found_least_upper_btag(struct btag *bt, uintptr_t minaddr)
832 {
833         struct rb_node *prev;
834
835         if (bt->start < minaddr)
836                 return FALSE;
837         prev = rb_prev(&bt->all_link);
838         if (!prev)
839                 return TRUE;
840         if (container_of(prev, struct btag, all_link)->start < minaddr)
841                 return TRUE;
842         return FALSE;
843 }
844
845 /* Does the a search in min/max for a segment. */
846 static void *__xalloc_min_max(struct arena *arena, size_t size,
847                               size_t align, size_t phase, size_t nocross,
848                               uintptr_t minaddr, uintptr_t maxaddr)
849 {
850         struct rb_node *node = arena->all_segs.rb_node;
851         struct btag *bt;
852         uintptr_t try;
853
854         /* Find the first bt >= minaddr */
855         while (node) {
856                 bt = container_of(node, struct btag, all_link);
857                 if (__found_least_upper_btag(bt, minaddr))
858                         break;
859                 if (minaddr < bt->start)
860                         node = node->rb_left;
861                 else
862                         node = node->rb_right;
863         }
864         /* Now we're probably at the first start point (or there's no node).
865          * Just scan from here. */
866         for (/* node set */; node; node = rb_next(node)) {
867                 bt = container_of(node, struct btag, all_link);
868                 try = __find_sufficient(bt->start, bt->size, size, align, phase,
869                                         nocross);
870                 if (!try)
871                         continue;
872                 if (maxaddr && (try + size > maxaddr))
873                         return NULL;
874                 __untrack_free_seg(arena, bt);
875                 if (try != bt->start)
876                         __split_bt_at(arena, bt, try);
877                 __account_alloc(arena, bt, size, NULL);
878                 return (void*)bt->start;
879         }
880         return NULL;
881 }
882
883 /* For xalloc, there isn't any real instant fit, due to the nocross issues.  We
884  * can still try to get a quicker fit by starting on a higher order list. */
885 static void *__xalloc_from_freelists(struct arena *arena, size_t size,
886                                      size_t align, size_t phase, size_t nocross,
887                                      bool try_instant_fit)
888 {
889         int list_idx;
890         struct btag *bt_i;
891         uintptr_t try = 0;
892
893         if (ROUNDUP(size, align) + phase < size)
894                 return NULL;
895         list_idx = LOG2_DOWN(ROUNDUP(size, align) + phase);
896         list_idx += try_instant_fit ? 1 : 0;
897         for (int i = list_idx; i < ARENA_NR_FREE_LISTS; i++) {
898                 BSD_LIST_FOREACH(bt_i, &arena->free_segs[i], misc_link) {
899                         try = __find_sufficient(bt_i->start, bt_i->size, size,
900                                                 align, phase, nocross);
901                         if (try) {
902                                 BSD_LIST_REMOVE(bt_i, misc_link);
903                                 break;
904                         }
905                 }
906                 if (try)
907                         break;
908         }
909         if (!try)
910                 return NULL;
911         if (try != bt_i->start)
912                 __split_bt_at(arena, bt_i, try);
913         __account_alloc(arena, bt_i, size, NULL);
914         return (void*)bt_i->start;
915 }
916
917 static void *__xalloc_nextfit(struct arena *arena, size_t size, size_t align,
918                               size_t phase, size_t nocross)
919 {
920         void *ret;
921
922         /* NEXTFIT is a lot like a minaddr.  We can start from the old addr + 1,
923          * since the implementation of that helper starts a search from minaddr.
924          * If it fails, we can try again from 1 (quantum, really), skipping 0.
925          * */
926         ret = __xalloc_min_max(arena, size, align, phase, nocross,
927                                arena->last_nextfit_alloc + arena->quantum, 0);
928         if (!ret) {
929                 ret = __xalloc_min_max(arena, size, align, phase, nocross,
930                                        arena->quantum, 0);
931         }
932         if (!ret)
933                 return NULL;
934         arena->last_nextfit_alloc = (uintptr_t)ret;
935         return ret;
936 }
937
938 static void *xalloc_from_arena(struct arena *arena, size_t size,
939                                size_t align, size_t phase, size_t nocross,
940                                void *minaddr, void *maxaddr, int flags)
941 {
942         void *ret;
943         void *to_free_addr = 0;
944         size_t to_free_sz = 0;
945
946         spin_lock_irqsave(&arena->lock);
947         /* Need two, since we might split a BT into 3 BTs. */
948         if (!__get_enough_btags(arena, 2, flags & MEM_FLAGS)) {
949                 spin_unlock_irqsave(&arena->lock);
950                 return NULL;
951         }
952         if (minaddr || maxaddr) {
953                 ret = __xalloc_min_max(arena, size, align, phase, nocross,
954                                        (uintptr_t)minaddr, (uintptr_t)maxaddr);
955         } else {
956                 if (flags & ARENA_BESTFIT) {
957                         ret = __xalloc_from_freelists(arena, size, align, phase,
958                                                       nocross, FALSE);
959                 } else if (flags & ARENA_NEXTFIT) {
960                         ret = __xalloc_nextfit(arena, size, align, phase,
961                                                nocross);
962                 } else {
963                         ret = __xalloc_from_freelists(arena, size, align, phase,
964                                                       nocross, TRUE);
965                 }
966         }
967         /* Careful, this will unlock and relock.  It's OK right before an
968          * unlock. */
969         __try_hash_resize(arena, flags, &to_free_addr, &to_free_sz);
970         spin_unlock_irqsave(&arena->lock);
971         if (to_free_addr)
972                 base_free(arena, to_free_addr, to_free_sz);
973         return ret;
974 }
975
976 void *arena_xalloc(struct arena *arena, size_t size, size_t align, size_t phase,
977                    size_t nocross, void *minaddr, void *maxaddr, int flags)
978 {
979         void *ret;
980         size_t req_size;
981
982         size = ROUNDUP(size, arena->quantum);
983         if (!size)
984                 panic("Arena %s, request for zero", arena->name);
985         if (!IS_PWR2(align))
986                 panic("Arena %s, non-power of two align %p", arena->name,
987                       align);
988         if (nocross && !IS_PWR2(nocross))
989                 panic("Arena %s, non-power of nocross %p", arena->name,
990                       nocross);
991         if (!ALIGNED(align, arena->quantum))
992                 panic("Arena %s, non-aligned align %p", arena->name, align);
993         if (!ALIGNED(nocross, arena->quantum))
994                 panic("Arena %s, non-aligned nocross %p", arena->name, nocross);
995         if (!ALIGNED(phase, arena->quantum))
996                 panic("Arena %s, non-aligned phase %p", arena->name, phase);
997         if (size + align < size)
998                 panic("Arena %s, size %p + align %p overflow%p", arena->name,
999                       size, align);
1000         if (size + phase < size)
1001                 panic("Arena %s, size %p + phase %p overflow%p", arena->name,
1002                       size, phase);
1003         if (align + phase < align)
1004                 panic("Arena %s, align %p + phase %p overflow%p", arena->name,
1005                       align, phase);
1006         /* Ok, it's a pain to import resources from a source such that we'll be
1007          * able to guarantee we make progress without stranding resources if we
1008          * have nocross or min/maxaddr.  For min/maxaddr, when we ask the
1009          * source, we aren't easily able to xalloc from their (it may depend on
1010          * the afunc).  For nocross, we can't easily ask the source for the
1011          * right span that satisfies the request (again, no real xalloc).  Some
1012          * constraints might not even be possible.
1013          *
1014          * If we get a span from the source and never use it, then we run a risk
1015          * of fragmenting and stranding a bunch of spans in our current arena.
1016          * Imagine the loop where we keep asking for spans (e.g. 8 pgs) and
1017          * getting something that doesn't work.  Those 8 pgs are fragmented, and
1018          * we won't give them back to the source until we allocate and then free
1019          * them (barring some sort of reclaim callback).
1020          *
1021          * Besides, I don't know if we even need/want nocross/min/maxaddr. */
1022         if (arena->source && (nocross || minaddr || maxaddr))
1023                 panic("Arena %s, has source, can't xalloc with nocross %p, minaddr %p, or maxaddr %p",
1024                       arena->name, nocross, minaddr, maxaddr);
1025         while (1) {
1026                 ret = xalloc_from_arena(arena, size, align, phase, nocross,
1027                                         minaddr, maxaddr, flags);
1028                 if (ret)
1029                         return ret;
1030                 /* We checked earlier than no two of these overflow, so I think
1031                  * we don't need to worry about multiple overflows. */
1032                 req_size = size + align + phase;
1033                 /* Note that this check isn't the same as the one we make when
1034                  * finding a sufficient segment.  Here we check overflow on the
1035                  * requested size.  Later, we check aligned bt_start + phase.
1036                  * The concern is that this check succeeds, but the other fails.
1037                  * (Say size = PGSIZE, phase =
1038                  * -PGSIZE -1.  req_size is very large.
1039                  *
1040                  * In this case, we're still fine - if our source is able to
1041                  * satisfy the request, our bt_start and bt_size will be able to
1042                  * express that size without wrapping. */
1043                 if (req_size < size)
1044                         panic("Arena %s, size %p + align %p + phase %p overflw",
1045                               arena->name, size, align, phase);
1046                 if (!get_more_resources(arena, req_size, flags))
1047                         return NULL;
1048                 /* Our source may have given us a segment that is on the BESTFIT
1049                  * list, same as with arena_alloc. */
1050                 flags &= ~ARENA_ALLOC_STYLES;
1051                 flags |= ARENA_BESTFIT;
1052                 /* TODO: could put a check in here to make sure we don't loop
1053                  * forever, in case we trip some other bug. */
1054         }
1055 }
1056
1057 /* Helper: if possible, merges the right BT to the left.  Returns TRUE if we
1058  * merged. */
1059 static bool __merge_right_to_left(struct arena *arena, struct btag *left,
1060                                   struct btag *right)
1061 {
1062         /* These checks will also make sure we never merge SPAN boundary tags.*/
1063         if (left->status != BTAG_FREE)
1064                 return FALSE;
1065         if (right->status != BTAG_FREE)
1066                 return FALSE;
1067         if (left->start + left->size == right->start) {
1068                 /* Need to yank left off its list before changing its size. */
1069                 __untrack_free_seg(arena, left);
1070                 __untrack_free_seg(arena, right);
1071                 left->size += right->size;
1072                 __track_free_seg(arena, left);
1073                 rb_erase(&right->all_link, &arena->all_segs);
1074                 __free_btag(arena, right);
1075                 return TRUE;
1076         }
1077         return FALSE;
1078 }
1079
1080 /* Merges @bt's segments with its adjacent neighbors.  If we end up having an
1081  * entire span free, we'll stop tracking it in this arena and return it for our
1082  * caller to free. */
1083 static void __coalesce_free_seg(struct arena *arena, struct btag *bt,
1084                                 void **to_free_addr, size_t *to_free_sz)
1085 {
1086         struct rb_node *rb_p, *rb_n;
1087         struct btag *bt_p, *bt_n;
1088
1089         rb_n = rb_next(&bt->all_link);
1090         if (rb_n) {
1091                 bt_n = container_of(rb_n, struct btag, all_link);
1092                 __merge_right_to_left(arena, bt, bt_n);
1093         }
1094         rb_p = rb_prev(&bt->all_link);
1095         if (rb_p) {
1096                 bt_p = container_of(rb_p, struct btag, all_link);
1097                 if (__merge_right_to_left(arena, bt_p, bt))
1098                         bt = bt_p;
1099         }
1100         /* Check for a span */
1101         rb_p = rb_prev(&bt->all_link);
1102         if (rb_p) {
1103                 bt_p = container_of(rb_p, struct btag, all_link);
1104                 if ((bt_p->status == BTAG_SPAN) &&
1105                     (bt_p->start == bt->start) &&
1106                     (bt_p->size == bt->size)) {
1107
1108                         *to_free_addr = (void*)bt_p->start;
1109                         *to_free_sz = bt_p->size;
1110                         /* Note the span was not on a free list */
1111                         __untrack_free_seg(arena, bt);
1112                         rb_erase(&bt_p->all_link, &arena->all_segs);
1113                         __free_btag(arena, bt_p);
1114                         rb_erase(&bt->all_link, &arena->all_segs);
1115                         __free_btag(arena, bt);
1116                 }
1117         }
1118 }
1119
1120 static void free_from_arena(struct arena *arena, void *addr, size_t size)
1121 {
1122         struct btag *bt;
1123         void *to_free_addr = 0;
1124         size_t to_free_sz = 0;
1125
1126         spin_lock_irqsave(&arena->lock);
1127         bt = __untrack_alloc_seg(arena, (uintptr_t)addr);
1128         if (!bt)
1129                 panic("Free of unallocated addr %p from arena %s", addr,
1130                       arena->name);
1131         if (bt->size != size)
1132                 panic("Free of %p with wrong size %p (%p) from arena %s", addr,
1133                       size, bt->size, arena->name);
1134         arena->amt_alloc_segs -= size;
1135         __track_free_seg(arena, bt);
1136         __coalesce_free_seg(arena, bt, &to_free_addr, &to_free_sz);
1137         arena->amt_total_segs -= to_free_sz;
1138         spin_unlock_irqsave(&arena->lock);
1139         if (to_free_addr)
1140                 arena->ffunc(arena->source, to_free_addr, to_free_sz);
1141 }
1142
1143 void arena_free(struct arena *arena, void *addr, size_t size)
1144 {
1145         size = ROUNDUP(size, arena->quantum);
1146         if (size <= arena->qcache_max)
1147                 return kmem_cache_free(size_to_qcache(arena, size), addr);
1148         free_from_arena(arena, addr, size);
1149 }
1150
1151 void arena_xfree(struct arena *arena, void *addr, size_t size)
1152 {
1153         size = ROUNDUP(size, arena->quantum);
1154         free_from_arena(arena, addr, size);
1155 }
1156
1157 /* Low-level arena builder.  Pass in a page address, and this will build an
1158  * arena in that memory.
1159  *
1160  * This will be used for each NUMA domain's base arena, kpages_arena, and
1161  * kmalloc_arena, since the normal arena_create() won't work yet (no kmalloc).
1162  */
1163 struct arena *arena_builder(void *pgaddr, char *name, size_t quantum,
1164                             void *(*afunc)(struct arena *, size_t, int),
1165                             void (*ffunc)(struct arena *, void *, size_t),
1166                             struct arena *source, size_t qcache_max)
1167 {
1168         struct arena *a = (struct arena*)pgaddr;
1169         struct btag *two_tags = (struct btag*)(pgaddr + sizeof(struct arena));
1170
1171         static_assert(sizeof(struct arena) + 2 * sizeof(struct btag) <= PGSIZE);
1172
1173         arena_init(a, name, quantum, afunc, ffunc, source, qcache_max);
1174         if (!source)
1175                 a->is_base = TRUE;
1176         BSD_LIST_INSERT_HEAD(&a->unused_btags, &two_tags[0], misc_link);
1177         BSD_LIST_INSERT_HEAD(&a->unused_btags, &two_tags[1], misc_link);
1178         return a;
1179 }
1180
1181 /* Sanity checker for an arena's structures.  Hold the lock. */
1182 static void __arena_asserter(struct arena *arena)
1183 {
1184         struct btag *bt_i;
1185         struct rb_node *rb_i;
1186         size_t amt_free = 0, amt_alloc = 0, nr_allocs = 0;
1187
1188         for (int i = 0; i < ARENA_NR_FREE_LISTS; i++) {
1189                 BSD_LIST_FOREACH(bt_i, &arena->free_segs[i], misc_link) {
1190                         assert(bt_i->status == BTAG_FREE);
1191                         assert(bt_i->size >= (1ULL << i));
1192                         assert(bt_i->size < (1ULL << (i + 1)));
1193                 }
1194         }
1195         for (int i = 0; i < arena->hh.nr_hash_lists; i++) {
1196                 BSD_LIST_FOREACH(bt_i, &arena->alloc_hash[i], misc_link)
1197                         assert(bt_i->status == BTAG_ALLOC);
1198         }
1199         for (rb_i = rb_first(&arena->all_segs); rb_i; rb_i = rb_next(rb_i)) {
1200                 bt_i = container_of(rb_i, struct btag, all_link);
1201                 if (bt_i->status == BTAG_FREE)
1202                         amt_free += bt_i->size;
1203                 if (bt_i->status == BTAG_ALLOC) {
1204                         amt_alloc += bt_i->size;
1205                         nr_allocs++;
1206                 }
1207         }
1208         assert(arena->amt_total_segs == amt_free + amt_alloc);
1209         assert(arena->amt_alloc_segs == amt_alloc);
1210         assert(arena->hh.nr_items == nr_allocs);
1211 }
1212
1213 size_t arena_amt_free(struct arena *arena)
1214 {
1215         return arena->amt_total_segs - arena->amt_alloc_segs;
1216 }
1217
1218 size_t arena_amt_total(struct arena *arena)
1219 {
1220         return arena->amt_total_segs;
1221 }
1222
1223 void add_importing_arena(struct arena *source, struct arena *importer)
1224 {
1225         qlock(&arenas_and_slabs_lock);
1226         TAILQ_INSERT_TAIL(&source->__importing_arenas, importer, import_link);
1227         qunlock(&arenas_and_slabs_lock);
1228 }
1229
1230 void del_importing_arena(struct arena *source, struct arena *importer)
1231 {
1232         qlock(&arenas_and_slabs_lock);
1233         TAILQ_REMOVE(&source->__importing_arenas, importer, import_link);
1234         qunlock(&arenas_and_slabs_lock);
1235 }
1236
1237 void add_importing_slab(struct arena *source, struct kmem_cache *importer)
1238 {
1239         qlock(&arenas_and_slabs_lock);
1240         TAILQ_INSERT_TAIL(&source->__importing_slabs, importer, import_link);
1241         qunlock(&arenas_and_slabs_lock);
1242 }
1243
1244 void del_importing_slab(struct arena *source, struct kmem_cache *importer)
1245 {
1246         qlock(&arenas_and_slabs_lock);
1247         TAILQ_REMOVE(&source->__importing_slabs, importer, import_link);
1248         qunlock(&arenas_and_slabs_lock);
1249 }
1250
1251 void *base_alloc(struct arena *guess, size_t size, int flags)
1252 {
1253         return arena_alloc(find_my_base(guess), size, flags);
1254 }
1255
1256 void *base_zalloc(struct arena *guess, size_t size, int flags)
1257 {
1258         void *ret = base_alloc(guess, size, flags);
1259
1260         if (!ret)
1261                 return NULL;
1262         memset(ret, 0, size);
1263         return ret;
1264 }
1265
1266 void base_free(struct arena *guess, void *addr, size_t size)
1267 {
1268         return arena_free(find_my_base(guess), addr, size);
1269 }