|
[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 |