Extra/pass paging state

This commit is contained in:
Sandro Rüegge 2022-03-24 14:18:15 +00:00
parent ba1eaa12dc
commit 0224bc8fd2
12 changed files with 233 additions and 21 deletions

View File

@ -600,6 +600,7 @@ errors spawn SPAWN_ERR_ {
failure COPY_VNODE "Failure copying top-level VNode from existing domain", failure COPY_VNODE "Failure copying top-level VNode from existing domain",
failure CREATE_DISPATCHER "Failure creating DCB", failure CREATE_DISPATCHER "Failure creating DCB",
failure CREATE_DISPATCHER_FRAME "Failure creating dispatcher frame", failure CREATE_DISPATCHER_FRAME "Failure creating dispatcher frame",
failure CREATE_VSPACE_BUF_FRAME "Failure creating vspace buf frame",
failure CREATE_SELFEP "Failure creating endpoint to self", failure CREATE_SELFEP "Failure creating endpoint to self",
failure CREATE_ARGSPG "Failure creating page for arguments", failure CREATE_ARGSPG "Failure creating page for arguments",
failure CREATE_FDSPG "Failure creating page for file descriptors", failure CREATE_FDSPG "Failure creating page for file descriptors",
@ -613,6 +614,8 @@ errors spawn SPAWN_ERR_ {
// setup_vspace // setup_vspace
failure MAP_DISPATCHER_TO_NEW "Failure mapping dispatcher frame to new domain", failure MAP_DISPATCHER_TO_NEW "Failure mapping dispatcher frame to new domain",
failure MAP_DISPATCHER_TO_SELF "Failure mapping dispatcher frame to parent", failure MAP_DISPATCHER_TO_SELF "Failure mapping dispatcher frame to parent",
failure MAP_VSPACE_BUF_TO_NEW "Failure mapping vspace buffer frame to new domain",
failure MAP_VSPACE_BUF_TO_SELF "Failure mapping vspace buffer frame to parent",
failure MAP_ARGSPG_TO_NEW "Failure mapping arguments page to new domain", failure MAP_ARGSPG_TO_NEW "Failure mapping arguments page to new domain",
failure MAP_ARGSPG_TO_SELF "Failure mapping arguments page to parent", failure MAP_ARGSPG_TO_SELF "Failure mapping arguments page to parent",
failure MAP_FDSPG_TO_NEW "Failure mapping file descriptors page to new domain", failure MAP_FDSPG_TO_NEW "Failure mapping file descriptors page to new domain",
@ -626,6 +629,7 @@ errors spawn SPAWN_ERR_ {
failure UNMAP_MODULE "Failed unmapping module", failure UNMAP_MODULE "Failed unmapping module",
failure CREATE_SEGCN "Failed to create segment CNode", failure CREATE_SEGCN "Failed to create segment CNode",
failure CREATE_SMALLCN "Failed to create small RAM caps CNode", failure CREATE_SMALLCN "Failed to create small RAM caps CNode",
failure SERIALISE_VSPACE_TOO_LARGE "Failure serializing vspace, using too many capabilities",
// setup env // setup env
failure ARGSPG_OVERFLOW "Overflow in arguments page: too many arguments or environment variables", failure ARGSPG_OVERFLOW "Overflow in arguments page: too many arguments or environment variables",

View File

@ -21,6 +21,7 @@
#include <aos/slab.h> #include <aos/slab.h>
#include <barrelfish_kpi/paging_arch.h> #include <barrelfish_kpi/paging_arch.h>
#include <aos/paging_types.h> #include <aos/paging_types.h>
#include <barrelfish_kpi/domain_params.h>
struct paging_state; struct paging_state;
@ -32,6 +33,7 @@ errval_t paging_init_state_foreign(struct paging_state *st, lvaddr_t start_vaddr
struct capref pdir, struct slot_allocator * ca); struct capref pdir, struct slot_allocator * ca);
/// initialize self-paging module /// initialize self-paging module
errval_t paging_init(void); errval_t paging_init(void);
errval_t paging_init_params(struct spawn_domain_params *params);
errval_t paging_init_onthread(struct thread *t); errval_t paging_init_onthread(struct thread *t);

View File

@ -26,6 +26,7 @@
#define VREGION_FLAGS_MPB 0x10 // Message passing buffer #define VREGION_FLAGS_MPB 0x10 // Message passing buffer
#define VREGION_FLAGS_GUARD 0x20 // Guard page #define VREGION_FLAGS_GUARD 0x20 // Guard page
#define VREGION_FLAGS_MASK 0x2f // Mask of all individual VREGION_FLAGS #define VREGION_FLAGS_MASK 0x2f // Mask of all individual VREGION_FLAGS
#define PT_CHILD_ARRAY_SIZE (PTABLE_ENTRIES * sizeof(void *)) // size of array holding references to page table children
#define VREGION_FLAGS_READ_WRITE \ #define VREGION_FLAGS_READ_WRITE \
(VREGION_FLAGS_READ | VREGION_FLAGS_WRITE) (VREGION_FLAGS_READ | VREGION_FLAGS_WRITE)

View File

@ -110,7 +110,8 @@
#define TASKCN_SLOT_PROC_MNG 18 ///< Cap for the process manager #define TASKCN_SLOT_PROC_MNG 18 ///< Cap for the process manager
#define TASKCN_SLOT_DOMAINID 19 ///< Domain ID cap #define TASKCN_SLOT_DOMAINID 19 ///< Domain ID cap
#define TASKCN_SLOT_DEVMAN 20 ///< DeviceID manager capability #define TASKCN_SLOT_DEVMAN 20 ///< DeviceID manager capability
#define TASKCN_SLOTS_USER 21 ///< First free slot in taskcn for user #define TASKCN_SLOT_VSPACE 21 ///< Vspace frame slot
#define TASKCN_SLOTS_USER 22 ///< First free slot in taskcn for user
/* Page CNode */ /* Page CNode */
#define PAGECN_SLOT_VROOT 0 ///< First slot of page cnode is root page table #define PAGECN_SLOT_VROOT 0 ///< First slot of page cnode is root page table

View File

@ -50,6 +50,7 @@ struct spawninfo {
struct capref cspace_cap_rootcn; // < Contains a capability for the root (L1) CNode. struct capref cspace_cap_rootcn; // < Contains a capability for the root (L1) CNode.
struct capref cspace_cap_dispframe; // < A capability to the dispatcher frame, used to communicate between a process and the CPU driver. struct capref cspace_cap_dispframe; // < A capability to the dispatcher frame, used to communicate between a process and the CPU driver.
struct capref cspace_cap_argspage; // < A page containing a list of command line arguments. struct capref cspace_cap_argspage; // < A page containing a list of command line arguments.
struct capref cspace_cap_vspace; // < The frame capability used to store the serialized vspace
struct capref vspace_cap_l0_pagetable; struct capref vspace_cap_l0_pagetable;
}; };

View File

@ -153,6 +153,7 @@ size_t strftime(char * __restrict, size_t, const char * __restrict,
const struct tm * __restrict); const struct tm * __restrict);
time_t time(time_t *); time_t time(time_t *);
void time_wait_ms(unsigned long); void time_wait_ms(unsigned long);
long time_to_ms(struct timespec tt);
#if __POSIX_VISIBLE >= 200112 #if __POSIX_VISIBLE >= 200112
struct sigevent; struct sigevent;
int timer_create(clockid_t, struct sigevent *__restrict, timer_t *__restrict); int timer_create(clockid_t, struct sigevent *__restrict, timer_t *__restrict);

View File

@ -128,7 +128,7 @@ errval_t barrelfish_init_onthread(struct spawn_domain_params *params)
return err_push(err, LIB_ERR_RAM_ALLOC_SET); return err_push(err, LIB_ERR_RAM_ALLOC_SET);
} }
err = paging_init(); err = paging_init_params(params);
if (err_is_fail(err)) { if (err_is_fail(err)) {
return err_push(err, LIB_ERR_VSPACE_INIT); return err_push(err, LIB_ERR_VSPACE_INIT);
} }

View File

@ -16,7 +16,6 @@
#include <aos/paging.h> #include <aos/paging.h>
#include <aos/except.h> #include <aos/except.h>
#include <aos/slab.h> #include <aos/slab.h>
#include <aos/slab.h>
#include "threads_priv.h" #include "threads_priv.h"
#include <stdio.h> #include <stdio.h>
@ -29,7 +28,7 @@ static struct paging_state current;
#define PT_META_MAX_SIZE MAX(sizeof(struct pt_t), sizeof(struct pt_vaddr_reg_t)) #define PT_META_MAX_SIZE MAX(sizeof(struct pt_t), sizeof(struct pt_vaddr_reg_t))
#define PT_PT_SLAB_INITIAL_SPACE SLAB_STATIC_SIZE(PT_PT_SLAB_MIN_SPACE, PT_META_MAX_SIZE) #define PT_PT_SLAB_INITIAL_SPACE SLAB_STATIC_SIZE(PT_PT_SLAB_MIN_SPACE, PT_META_MAX_SIZE)
#define PT_CHILDREN_SLAB_INITIAL_SPACE SLAB_STATIC_SIZE(PT_CHILDREN_SLAB_MIN_SPACE, BASE_PAGE_SIZE) #define PT_CHILDREN_SLAB_INITIAL_SPACE SLAB_STATIC_SIZE(PT_CHILDREN_SLAB_MIN_SPACE, PT_CHILD_ARRAY_SIZE)
/** /**
* \brief Helper function that allocates a slot and * \brief Helper function that allocates a slot and
@ -275,7 +274,7 @@ errval_t paging_init_state(struct paging_state *st, lvaddr_t start_vaddr,
// initialize slab allocators // initialize slab allocators
slab_init(&st->pt_slabs, PT_META_MAX_SIZE, NULL); slab_init(&st->pt_slabs, PT_META_MAX_SIZE, NULL);
slab_init(&st->pt_children_slabs, BASE_PAGE_SIZE, NULL); slab_init(&st->pt_children_slabs, PT_CHILD_ARRAY_SIZE, NULL);
// initialize shadow page tables // initialize shadow page tables
st->l0_pt.cap_pt = pdir; st->l0_pt.cap_pt = pdir;
@ -328,12 +327,7 @@ errval_t paging_init_state_foreign(struct paging_state *st, lvaddr_t start_vaddr
return paging_init_state(st, start_vaddr, pt_cap, ca); return paging_init_state(st, start_vaddr, pt_cap, ca);
} }
/** errval_t paging_init_params(struct spawn_domain_params *params)
* @brief This function initializes the paging for this domain
*
* Note: The function is called once before main.
*/
errval_t paging_init(void)
{ {
errval_t err; errval_t err;
debug_printf("paging_init\n"); debug_printf("paging_init\n");
@ -353,10 +347,28 @@ errval_t paging_init(void)
slab_grow(&current.pt_slabs, pt_pt_slab_buf, PT_PT_SLAB_INITIAL_SPACE); slab_grow(&current.pt_slabs, pt_pt_slab_buf, PT_PT_SLAB_INITIAL_SPACE);
slab_grow(&current.pt_children_slabs, pt_children_slab_buf, PT_CHILDREN_SLAB_INITIAL_SPACE); slab_grow(&current.pt_children_slabs, pt_children_slab_buf, PT_CHILDREN_SLAB_INITIAL_SPACE);
// if we got additional vspace info use it
if(params != NULL && params->vspace_buf != NULL) {
current.l0_pt = **(struct pt_t **)params->vspace_buf;
current.vaddr_head = **(struct pt_vaddr_reg_t **)(params->vspace_buf + sizeof(struct pt_t *));
debug_printf("Received initial paging state:\n");
pt_print_state(&current);
}
set_current_paging_state(&current); set_current_paging_state(&current);
return SYS_ERR_OK; return SYS_ERR_OK;
} }
/**
* @brief This function initializes the paging for this domain
*
* Note: The function is called once before main.
*/
errval_t paging_init(void)
{
return paging_init_params(NULL);
}
/** /**
* @brief Initializes the paging functionality for the calling thread * @brief Initializes the paging functionality for the calling thread
@ -565,7 +577,7 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
assert(vaddr % BASE_PAGE_SIZE == 0); assert(vaddr % BASE_PAGE_SIZE == 0);
assert(bytes % BASE_PAGE_SIZE == 0); assert(bytes % BASE_PAGE_SIZE == 0);
lvaddr_t end_vaddr = vaddr + bytes; lvaddr_t end_vaddr = vaddr + bytes;
assert(end_vaddr <= PTABLE_ENTRIES * PTABLE_ENTRIES *PTABLE_ENTRIES * PTABLE_ENTRIES * BASE_PAGE_SIZE); assert(end_vaddr <= PTABLE_ENTRIES * PTABLE_ENTRIES * PTABLE_ENTRIES * PTABLE_ENTRIES * BASE_PAGE_SIZE);
assert(st != NULL); assert(st != NULL);
assert(st->slot_alloc != NULL); assert(st->slot_alloc != NULL);
@ -590,7 +602,6 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
// make sure the virtual address space is reserved for this mapping. For this we require either an allocated vaddr reg to // make sure the virtual address space is reserved for this mapping. For this we require either an allocated vaddr reg to
// precisely exist as required or not at all, i.e. it is not overlapping multiple existing regions // precisely exist as required or not at all, i.e. it is not overlapping multiple existing regions
// TODO rueegges: not sure this is the best way to do this
struct pt_vaddr_reg_t *vaddr_reg = &st->vaddr_head; struct pt_vaddr_reg_t *vaddr_reg = &st->vaddr_head;
for(;vaddr_reg != NULL; vaddr_reg = vaddr_reg->next) { for(;vaddr_reg != NULL; vaddr_reg = vaddr_reg->next) {
// we have found the region it belongs to // we have found the region it belongs to
@ -611,7 +622,7 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
return LIB_ERR_PMAP_ADDR_NOT_FREE; return LIB_ERR_PMAP_ADDR_NOT_FREE;
} }
// TODO rueegges: cleanup partially completed mapping? // TODO: cleanup partially completed mapping?
size_t mapping_size; size_t mapping_size;
for(lvaddr_t current_vaddr = vaddr; current_vaddr < end_vaddr; current_vaddr += mapping_size * BASE_PAGE_SIZE) { for(lvaddr_t current_vaddr = vaddr; current_vaddr < end_vaddr; current_vaddr += mapping_size * BASE_PAGE_SIZE) {
capaddr_t l0_index = VMSAv8_64_L0_INDEX(current_vaddr); capaddr_t l0_index = VMSAv8_64_L0_INDEX(current_vaddr);
@ -662,6 +673,7 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
DEBUG_ERR(err, "Failed to refill slabs before adding page mapping."); DEBUG_ERR(err, "Failed to refill slabs before adding page mapping.");
return LIB_ERR_SLAB_ALLOC_FAIL; return LIB_ERR_SLAB_ALLOC_FAIL;
} }
pt_entry->cap_pt = NULL_CAP;
pt_entry->children = NULL; pt_entry->children = NULL;
pt_entry->mapping_size = mapping_size; pt_entry->mapping_size = mapping_size;
// allocate the new mapping // allocate the new mapping

View File

@ -1,6 +1,7 @@
#include <test_helper.h> #include <test_helper.h>
#include <test_mm.h> #include <test_mm.h>
#include <mm/mm.h> #include <mm/mm.h>
#include <time.h>
// ASSESSMENT M1: can be used to show the speed issues in mm_alloc // ASSESSMENT M1: can be used to show the speed issues in mm_alloc
#define TEST_MM_SMALL_COUNT 100 #define TEST_MM_SMALL_COUNT 100
@ -140,20 +141,33 @@ static errval_t test_mm_rand(struct mm *mm) {
static errval_t test_mm_many(struct mm *mm) { static errval_t test_mm_many(struct mm *mm) {
errval_t err; errval_t err;
struct timespec tt;
clock_gettime(CLOCK_REALTIME, &tt);
long start_ms = time_to_ms(tt);
for(int i = 0; i < TEST_MM_BIG_COUNT; ++i) { for(int i = 0; i < TEST_MM_BIG_COUNT; ++i) {
err = mm_alloc_aligned(mm, 1 << 10, 1 << 10, &caps_big[i]); err = mm_alloc_aligned(mm, 1 << 10, 1 << 10, &caps_big[i]);
if(err_is_fail(err)) { if(err_is_fail(err)) {
debug_printf("Iteration: %d\n", i); debug_printf("Iteration: %d\n", i);
return err_push(err, MM_ERR_NEW_NODE); return err_push(err, MM_ERR_NEW_NODE);
} }
if(!((i + 1) % 1000)) {
clock_gettime(CLOCK_REALTIME, &tt);
debug_printf("Mapped %d after %ld\n", i + 1, time_to_ms(tt) - start_ms);
}
} }
// free loads of small memory // free loads of small memory
clock_gettime(CLOCK_REALTIME, &tt);
start_ms = time_to_ms(tt);
for(int i = 0; i < TEST_MM_BIG_COUNT; ++i) { for(int i = 0; i < TEST_MM_BIG_COUNT; ++i) {
err = mm_free(mm, caps_big[i]); err = mm_free(mm, caps_big[i]);
if(err_is_fail(err)) { if(err_is_fail(err)) {
debug_printf("Iteration: %d\n", i); debug_printf("Iteration: %d\n", i);
return err_push(err, MM_ERR_MM_FREE); return err_push(err, MM_ERR_MM_FREE);
} }
if(!((i + 1) % 1000)) {
clock_gettime(CLOCK_REALTIME, &tt);
debug_printf("Freed %d after %ld\n", i + 1, time_to_ms(tt) - start_ms);
}
} }
return SYS_ERR_OK; return SYS_ERR_OK;
} }

View File

@ -154,6 +154,11 @@ static errval_t test_paging_unmap(struct paging_state *paging_state) {
if (err_is_fail(err)) { if (err_is_fail(err)) {
return err_push(err, LIB_ERR_PMAP_NOT_MAPPED); return err_push(err, LIB_ERR_PMAP_NOT_MAPPED);
} }
// check that it is mapped
*(uint8_t *) retaddr = 1;
assert(*(uint8_t *)retaddr == 1);
err = paging_unmap(paging_state, retaddr); err = paging_unmap(paging_state, retaddr);
if (err_is_fail(err)) { if (err_is_fail(err)) {
return err_push(err, LIB_ERR_PMAP_UNMAP); return err_push(err, LIB_ERR_PMAP_UNMAP);
@ -167,7 +172,7 @@ static errval_t test_paging_unmap(struct paging_state *paging_state) {
return err_push(err, LIB_ERR_PMAP_NOT_MAPPED); return err_push(err, LIB_ERR_PMAP_NOT_MAPPED);
} }
*(uint8_t *) retaddr = 1; // check that it is mapped
assert(*(uint8_t *)retaddr == 1); assert(*(uint8_t *)retaddr == 1);
return SYS_ERR_OK; return SYS_ERR_OK;

View File

@ -51,6 +51,11 @@ time(time_t *t)
return (retval); return (retval);
} }
long
time_to_ms(struct timespec tt) {
return tt.tv_sec * 1000 + tt.tv_nsec / 1000 / 1000;
}
/** /**
* \brief Wait for ms milliseconds before returning. * \brief Wait for ms milliseconds before returning.
* *
@ -64,10 +69,10 @@ time_wait_ms(unsigned long ms) {
struct timespec tt; struct timespec tt;
clock_gettime(CLOCK_REALTIME, &tt); clock_gettime(CLOCK_REALTIME, &tt);
long start = tt.tv_sec * 1000 + tt.tv_nsec / 1000 / 1000; long start = time_to_ms(tt);
long now; long now;
do { do {
clock_gettime(CLOCK_REALTIME, &tt); clock_gettime(CLOCK_REALTIME, &tt);
now = tt.tv_sec * 1000 + tt.tv_nsec / 1000 / 1000; now = time_to_ms(tt);
} while(start + ms > now); } while(start + ms > now);
} }

View File

@ -119,6 +119,166 @@ static errval_t elf_allocate(
return SYS_ERR_OK; return SYS_ERR_OK;
} }
static size_t spawn_serialice_vspace_pt_size(struct pt_t *pt) {
size_t sum = 0;
sum += sizeof(struct pt_t);
if(pt->children != NULL) {
// children array
sum += PT_CHILD_ARRAY_SIZE;
for(size_t i = 0; i < PTABLE_ENTRIES; ++i) {
if(pt->children[i] != NULL) {
sum += spawn_serialice_vspace_pt_size(pt->children[i]);
}
}
}
return sum;
}
// places pt as first thing in buf, then copies all else and increments curr_buf accordingly
static errval_t spawn_serialize_pt(struct spawninfo *si, struct pt_t *pt, void *self_buf, void *child_buf, size_t *curr_offset, cslot_t *pagecn_slot) {
errval_t err;
if (*pagecn_slot >= L2_CNODE_SLOTS - 2) {
return SPAWN_ERR_SERIALISE_VSPACE_TOO_LARGE;
}
// write pt to buffer
struct pt_t *pt_child = (struct pt_t *) (self_buf + *curr_offset);
memcpy(pt_child, pt, sizeof(struct pt_t));
*curr_offset += sizeof(struct pt_t);
// copy capability references to child
if(!capref_is_null(pt->cap_pt)) {
pt_child->cap_pt.cnode = si->cspace_l2_cnode_pagecn;
pt_child->cap_pt.slot = *pagecn_slot;
*pagecn_slot = *pagecn_slot + 1;
err = cap_copy(pt_child->cap_pt, pt->cap_pt);
if (err_is_fail(err)) {
return err_push(err, LIB_ERR_CAP_COPY_FAIL);
}
}
if(!capref_is_null(pt->cap_mapping)) {
pt_child->cap_mapping.cnode = si->cspace_l2_cnode_pagecn;
pt_child->cap_mapping.slot = *pagecn_slot;
*pagecn_slot = *pagecn_slot + 1;
err = cap_copy(pt_child->cap_mapping, pt->cap_mapping);
if (err_is_fail(err)) {
return err_push(err, LIB_ERR_CAP_COPY_FAIL);
}
}
if (pt->children == NULL) {
assert(pt_child->children == NULL);
return SYS_ERR_OK;
}
// serialize all children
pt_child->children = (struct pt_t **)(child_buf + *curr_offset);
struct pt_t ** children_self = (struct pt_t **)(self_buf + *curr_offset);
*curr_offset += PT_CHILD_ARRAY_SIZE;
for(size_t i = 0; i < PTABLE_ENTRIES; ++i) {
if (pt->children[i] == NULL) {
children_self[i] = NULL;
} else {
children_self[i] = (struct pt_t *)(child_buf + *curr_offset);
err = spawn_serialize_pt(si, pt->children[i], self_buf, child_buf, curr_offset, pagecn_slot);
if (err_is_fail(err)) {
return err;
}
}
}
return SYS_ERR_OK;
}
// serializes the vspace in a way that does not require deserialization
// vspace_buf->|l0_pt*,vaddr_head*,data....|
// so the child can just take the two pointers and store them into its current paging_state
static errval_t spawn_serialize_vspace(struct spawninfo *si, struct paging_state *paging_state, struct spawn_domain_params *domain_params) {
errval_t err;
// first calculate required vspace size
size_t pt_space = spawn_serialice_vspace_pt_size(&paging_state->l0_pt);
size_t vaddr_space = 0;
for(struct pt_vaddr_reg_t *cur_vaddr = &paging_state->vaddr_head; cur_vaddr != NULL; cur_vaddr = cur_vaddr->next) {
vaddr_space += sizeof(struct pt_vaddr_reg_t);
}
size_t pointer_space = 2 * sizeof(void *);
size_t total_space = pointer_space + pt_space + vaddr_space;
size_t reserve_space =
// additional structs for the vaddr allocation that is required
2 * sizeof(struct pt_vaddr_reg_t) +
// space for potential l1,l2,l3 page tables
6 * (sizeof(struct pt_t) + PT_CHILD_ARRAY_SIZE) +
// space for the page table entries when mapping up to 512 contiguous pages
2 * sizeof(struct pt_t);
total_space = ROUND_UP(total_space + reserve_space, BASE_PAGE_SIZE);
// require this limit to restrict the ammount of additionally reserved space
if(total_space > LARGE_PAGE_SIZE) {
return SPAWN_ERR_SERIALISE_VSPACE_TOO_LARGE;
}
// allocate memory to store the state
void *vspace_buf_self;
void *vspace_buf_child;
err = frame_create(si->cspace_cap_vspace, total_space, NULL);
if (err_is_fail(err)) {
return err_push(err, SPAWN_ERR_CREATE_VSPACE_BUF_FRAME);
}
err = paging_map_frame_attr(
get_current_paging_state(), &vspace_buf_self,
total_space, si->cspace_cap_vspace, VREGION_FLAGS_READ_WRITE
);
if (err_is_fail(err)) return err_push(err, SPAWN_ERR_MAP_VSPACE_BUF_TO_SELF);
err = paging_map_frame_attr(
paging_state, &vspace_buf_child,
total_space, si->cspace_cap_vspace, VREGION_FLAGS_READ_WRITE
);
if (err_is_fail(err)) return err_push(err, SPAWN_ERR_MAP_VSPACE_BUF_TO_NEW);
// first store all the page table structs
cslot_t pagecn_slot = PAGECN_SLOT_VROOT + 1;
size_t curr_offset = 2 * sizeof(void *);
*(void **) vspace_buf_self = vspace_buf_child + curr_offset;
err = spawn_serialize_pt(si, &paging_state->l0_pt, vspace_buf_self, vspace_buf_child, &curr_offset, &pagecn_slot);
if(err_is_fail(err)) {
return err;
}
// then store all the vaddr region structs
*(void **)(vspace_buf_self + sizeof(void *)) = vspace_buf_child + curr_offset;
for(struct pt_vaddr_reg_t *cur_vaddr = &paging_state->vaddr_head; cur_vaddr != NULL; cur_vaddr = cur_vaddr->next) {
struct pt_vaddr_reg_t *vaddr_child = (struct pt_vaddr_reg_t *)(vspace_buf_self + curr_offset);
memcpy(vaddr_child, cur_vaddr, sizeof(struct pt_vaddr_reg_t));
curr_offset += sizeof(struct pt_vaddr_reg_t);
if(cur_vaddr->next != NULL) {
vaddr_child->next = (struct pt_vaddr_reg_t *)(vspace_buf_child + curr_offset);
}
}
// unmap in self
err = paging_unmap(get_current_paging_state(), vspace_buf_self);
if (err_is_fail(err)) {
return err_push(err, LIB_ERR_PMAP_UNMAP);
}
assert(curr_offset <= total_space);
debug_printf("SPAWN: Passing vspace info at 0x%lx\n", vspace_buf_child);
domain_params->vspace_buf = vspace_buf_child;
domain_params->vspace_buf_len = total_space;
return SYS_ERR_OK;
}
/** /**
* (M2): Implement this function. * (M2): Implement this function.
@ -205,6 +365,9 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
si->cspace_cap_argspage.cnode = si->cspace_l2_cnode_taskcn; si->cspace_cap_argspage.cnode = si->cspace_l2_cnode_taskcn;
si->cspace_cap_argspage.slot = TASKCN_SLOT_ARGSPAGE; si->cspace_cap_argspage.slot = TASKCN_SLOT_ARGSPAGE;
si->cspace_cap_vspace.cnode = si->cspace_l2_cnode_taskcn;
si->cspace_cap_vspace.slot = TASKCN_SLOT_VSPACE;
err = cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_SLOT_ALLOC0, &si->cspace_l2_cnode_slot_alloc_0); err = cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_SLOT_ALLOC0, &si->cspace_l2_cnode_slot_alloc_0);
if (err_is_fail(err)) return err; if (err_is_fail(err)) return err;
err = cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_SLOT_ALLOC1, &si->cspace_l2_cnode_slot_alloc_1); err = cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_SLOT_ALLOC1, &si->cspace_l2_cnode_slot_alloc_1);
@ -353,16 +516,19 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
// afeer: put the arguments into the argspage // afeer: put the arguments into the argspage
struct spawn_domain_params * domain_params = (struct spawn_domain_params *) arguments_page_in_self; struct spawn_domain_params * domain_params = (struct spawn_domain_params *) arguments_page_in_self;
domain_params->argc = argc;
err = spawn_serialize_vspace(si, &child_paging_state, domain_params);
if (err_is_fail(err)) {
return err_push(err, SPAWN_ERR_SERIALISE_VSPACE);
}
// afeer: TODO: what do i put here? do we need to set these fields to some value? // afeer: TODO: what do i put here? do we need to set these fields to some value?
// domain_params->vspace_buf = NULL;
// domain_params->vspace_buf_len = 0;
// domain_params->tls_init_base = NULL; // domain_params->tls_init_base = NULL;
// domain_params->tls_init_len = 0; // domain_params->tls_init_len = 0;
// domain_params->tls_total_len = 0; // domain_params->tls_total_len = 0;
// domain_params->pagesize = BASE_PAGE_SIZE; // domain_params->pagesize = BASE_PAGE_SIZE;
domain_params->argc = argc;
size_t offset = sizeof(struct spawn_domain_params); size_t offset = sizeof(struct spawn_domain_params);
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
// afeer: put the argument into page in self // afeer: put the argument into page in self