[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [UNIKRAFT/BALLOON v2 7/7] lib/ukallocbbuddy: Balloon API calls insertion
From: Cezar Craciunoiu <cezar.craciunoiu@xxxxxxxxx> To call the balloon in a fashionable way, the calls were added to bbuddy. The palloc function calls deflate, pfree and addmem call inflate. The balloon is first started using the balloon_init function that is called just once. In the case of KVM, because it does not currently need to initialize itself by inflating the balloon, the calls to balloon_init and ukplat_inflate are skipped. As there might be a need in the future for balloon inflation for KVM, it was not removed from the original implementation. If needed (for cleaner code), it can be removed and replaced with a stub. The balloon calls do not influence the behaviour of bbuddy in a visible way, meaning that, if something fails in the balloon, it does not affect what is in bbuddy. Except for the case where an unknown error happens. Signed-off-by: Cezar Craciunoiu <cezar.craciunoiu@xxxxxxxxx> --- lib/ukallocbbuddy/Config.uk | 2 + lib/ukallocbbuddy/bbuddy.c | 137 +++++++++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 2 deletions(-) diff --git a/lib/ukallocbbuddy/Config.uk b/lib/ukallocbbuddy/Config.uk index c5a3025..5b3f9d2 100644 --- a/lib/ukallocbbuddy/Config.uk +++ b/lib/ukallocbbuddy/Config.uk @@ -4,3 +4,5 @@ config LIBUKALLOCBBUDDY select LIBNOLIBC if !HAVE_LIBC select LIBUKDEBUG select LIBUKALLOC + select BALLOON if HAVE_KVM + diff --git a/lib/ukallocbbuddy/bbuddy.c b/lib/ukallocbbuddy/bbuddy.c index 85f3e8d..becc36e 100644 --- a/lib/ukallocbbuddy/bbuddy.c +++ b/lib/ukallocbbuddy/bbuddy.c @@ -49,6 +49,8 @@ #include <uk/assert.h> #include <uk/page.h> +#include <uk/plat/balloon.h> + typedef struct chunk_head_st chunk_head_t; typedef struct chunk_tail_st chunk_tail_t; @@ -242,6 +244,51 @@ static inline unsigned long num_pages_to_order(unsigned long num_pages) return ukarch_flsl(num_pages - 1) + 1; } +/********************* + * BALLOON SUPPORT + */ + +static char using_balloon; + +/** + * Initializes the balloon once it is ready. Immediate for Xen, + * but later for KVM driver. + */ +static void balloon_init(struct uk_alloc *a) +{ + struct uk_bbpalloc *b; + size_t i; + int order; + chunk_head_t *chunk; + int r; + + b = (struct uk_bbpalloc *)&a->priv; + + ukplat_balloon_set(&using_balloon); + + if (using_balloon != 0) + return; + + for (i = 0; i < FREELIST_SIZE; i++) { + if (!FREELIST_EMPTY(b->free_head[i])) { + chunk = b->free_head[i]; + order = chunk->level; + + r = ukplat_inflate((void *)chunk, order); + if (r < 0) { + /* The balloon is ready but + * failed for another reason. + */ + return; + } + } + + } + using_balloon = 1; +} + + + /********************* * BINARY BUDDY PAGE ALLOCATOR */ @@ -249,6 +296,7 @@ static void *bbuddy_palloc(struct uk_alloc *a, unsigned long num_pages) { struct uk_bbpalloc *b; size_t i; + int r; chunk_head_t *alloc_ch, *spare_ch; chunk_tail_t *spare_ct; @@ -291,6 +339,31 @@ static void *bbuddy_palloc(struct uk_alloc *a, unsigned long num_pages) } map_alloc(b, (uintptr_t)alloc_ch, 1UL << order); + /* Remove the chunk from the balloon - not for KVM */ + if (using_balloon != 2) { + r = ukplat_deflate((void *)alloc_ch, (int)order); + if (r < 0) { + if (r == -ENXIO) { + /* The balloon isn't ready yet! + * We don't need to do anything. + */ + } else if (r == -ENOSYS) { + /* deflation not implemented */ + } else { + /* The balloon is ready but + * failed for another reason. + */ + return NULL; + } + } else if (using_balloon == 0) { + /* Deflate succeeded for the first time. + * The balloon driver is ready! We need to move + * all of the freelist data to the balloon. + */ + balloon_init(a); + } + } + return ((void *)alloc_ch); no_memory: @@ -306,6 +379,7 @@ static void bbuddy_pfree(struct uk_alloc *a, void *obj, unsigned long num_pages) chunk_head_t *freed_ch, *to_merge_ch; chunk_tail_t *freed_ct; unsigned long mask; + int r; UK_ASSERT(a != NULL); b = (struct uk_bbpalloc *)&a->priv; @@ -318,6 +392,29 @@ static void bbuddy_pfree(struct uk_alloc *a, void *obj, unsigned long num_pages) /* First free the chunk */ map_free(b, (uintptr_t)obj, 1UL << order); + /* Add the free chunk to the balloon */ + r = ukplat_inflate((void *)obj, (int)order); + if (r < 0) { + if (r == -ENXIO) { + /* The balloon isn't ready yet! + * We don't need to do anything. + */ + } else if (r == -ENOSYS) { + /* inflateion not implemented */ + } else { + /* The balloon is ready but + * failed for another reason. + */ + return; + } + } else if (using_balloon == 0) { + /* Inflate succeeded for the first time. + * The balloon driver is now ready! + * We need to move all of the free list data to the balloon. + */ + balloon_init(a); + } + /* Create free chunk */ freed_ch = (chunk_head_t *)obj; freed_ct = (chunk_tail_t *)((char *)obj @@ -371,6 +468,7 @@ static int bbuddy_addmem(struct uk_alloc *a, void *base, size_t len) chunk_head_t *ch; chunk_tail_t *ct; uintptr_t min, max, range; + int r; UK_ASSERT(a != NULL); UK_ASSERT(base != NULL); @@ -431,8 +529,10 @@ static int bbuddy_addmem(struct uk_alloc *a, void *base, size_t len) memset(memr->mm_alloc_bitmap, (unsigned char) ~0, memr->mm_alloc_bitmap_size); - /* free up the memory we've been given to play with */ - map_free(b, min, memr->nr_pages); + + /* Mock call to check if the balloon is implemented */ + if (ukplat_inflate(NULL, 0) == -ENOSYS) + map_free(b, min, memr->nr_pages); count = 0; while (range != 0) { @@ -448,6 +548,39 @@ static int bbuddy_addmem(struct uk_alloc *a, void *base, size_t len) (uintptr_t)a, min, (uintptr_t)(min + (1UL << i)), (i - __PAGE_SHIFT)); + /* + * For each free block we attempt to add it to the balloon + * Afterwards, if successful, all of our usable memory will be + * in the balloon. It will become accessible by calling deflate + * in ukpalloc, or directly for KVM! + * + * If the balloon device has not yet been added then the + * allocator will proceed without ballooning support until + * the device has been added (KVM). + */ + r = ukplat_inflate((void *)min, (int)(i - __PAGE_SHIFT)); + if (r < 0) { + if (r == -ENXIO) { + /* The balloon isn't ready yet! + * We don't need to do anything. + */ + } else if (r == -ENOSYS) { + /* inflation not implemented */ + } else { + /* The balloon is ready but failed + * for another reason. + */ + return r; + } + } else if (using_balloon == 0) { + /* Inflate succeeded for the first time. + * The balloon driver is now ready! + * We need to move all of the free list + * data to the balloon. + */ + balloon_init(a); + } + ch = (chunk_head_t *)min; min += 1UL << i; range -= 1UL << i; -- 2.20.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |