libsel4utils: Initialise an empty vspace

Implemented a new interface function
'sel4utils_get_empty_vspace_with_map' that allows the user to
create a vspace (with map) that has no part of the virtual address
space being pre-reserved e.g. kernel region. This is useful in
cases where processes belong to virtual machine based applications
and need the full address space.
diff --git a/libsel4utils/include/sel4utils/vspace.h b/libsel4utils/include/sel4utils/vspace.h
index 5a5fa86..90020f6 100644
--- a/libsel4utils/include/sel4utils/vspace.h
+++ b/libsel4utils/include/sel4utils/vspace.h
@@ -80,6 +80,7 @@
     vspace_t *bootstrap;
     sel4utils_map_page_fn map_page;
     sel4utils_res_t *reservation_head;
+    bool is_empty;
 } sel4utils_alloc_data_t;
 
 static inline sel4utils_res_t *reservation_to_res(reservation_t res)
@@ -109,7 +110,28 @@
 sel4utils_get_vspace_with_map(vspace_t *loader, vspace_t *new_vspace, sel4utils_alloc_data_t *data,
                               vka_t *vka, seL4_CPtr vspace_root,
                               vspace_allocated_object_fn allocated_object_fn, void *allocated_object_cookie, sel4utils_map_page_fn map_page);
-
+/**
+ * Allows for an empty vspace to be created with an arbitrary function to invoke for the mapping of pages.
+ * This is useful if you want a vspace manager, but you do not want parts of the virtual address space to be
+ * pre-reserved e.g the kernel region. The vspace is useful for guest virtual machine-based applications.
+ *
+ * @param loader                  vspace of the current process, used to allocate
+ *                                virtual memory book keeping.
+ * @param new_vspace              uninitialised vspace struct to populate.
+ * @param data                    uninitialised vspace data struct to populate.
+ * @param vka                     initialised vka that this virtual memory allocator will use to
+ *                                allocate pages and pagetables. This allocator will never invoke free.
+ * @param vspace_root             root object for the new vspace.
+ * @param allocated_object_fn     function to call when objects are allocated. Can be null.
+ * @param allocated_object_cookie cookie passed when the above function is called. Can be null.
+ * @param map_page                Function that will be called to map seL4 pages
+ *
+ * @return 0 on success.
+ */
+int
+sel4utils_get_empty_vspace_with_map(vspace_t *loader, vspace_t *new_vspace, sel4utils_alloc_data_t *data,
+                                    vka_t *vka, seL4_CPtr vspace_root,
+                                    vspace_allocated_object_fn allocated_object_fn, void *allocated_object_cookie, sel4utils_map_page_fn map_page);
 /**
  * Initialise a vspace allocator for a new address space (not the current one).
  *
diff --git a/libsel4utils/src/vspace/bootstrap.c b/libsel4utils/src/vspace/bootstrap.c
index 0fd4de5..2ce9f4d 100644
--- a/libsel4utils/src/vspace/bootstrap.c
+++ b/libsel4utils/src/vspace/bootstrap.c
@@ -46,6 +46,7 @@
     data->vka = vka;
     data->last_allocated = 0x10000000;
     data->reservation_head = NULL;
+    data->is_empty = false;
 
     data->vspace_root = vspace_root;
     vspace->allocated_object = allocated_object_fn;
@@ -59,9 +60,11 @@
     sel4utils_alloc_data_t *data = get_alloc_data(vspace);
     /* reserve the kernel region, we do this by marking the
      * top level entry as RESERVED */
-    for (int i = TOP_LEVEL_INDEX(KERNEL_RESERVED_START);
-         i < VSPACE_LEVEL_SIZE; i++) {
-        data->top_level->table[i] = RESERVED;
+    if (!data->is_empty) {
+        for (int i = TOP_LEVEL_INDEX(KERNEL_RESERVED_START);
+             i < VSPACE_LEVEL_SIZE; i++) {
+            data->top_level->table[i] = RESERVED;
+        }
     }
 
     data->map_page = map_page;
@@ -315,6 +318,21 @@
     return get_vspace_bootstrap(loader, new_vspace, data, map_page);
 }
 
+int sel4utils_get_empty_vspace_with_map(vspace_t *loader, vspace_t *new_vspace, sel4utils_alloc_data_t *data,
+                                        vka_t *vka, seL4_CPtr vspace_root,
+                                        vspace_allocated_object_fn allocated_object_fn, void *allocated_object_cookie, sel4utils_map_page_fn map_page)
+{
+
+    new_vspace->data = (void *) data;
+
+    if (common_init(new_vspace, vka, vspace_root, allocated_object_fn, allocated_object_cookie)) {
+        return -1;
+    }
+    data->is_empty = true;
+
+    return get_vspace_bootstrap(loader, new_vspace, data, map_page);
+}
+
 int sel4utils_get_vspace(vspace_t *loader, vspace_t *new_vspace, sel4utils_alloc_data_t *data,
                          vka_t *vka, seL4_CPtr vspace_root,
                          vspace_allocated_object_fn allocated_object_fn, void *allocated_object_cookie)