Extra/pass paging state
This commit is contained in:
parent
ba1eaa12dc
commit
0224bc8fd2
@ -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",
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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(¤t.pt_slabs, pt_pt_slab_buf, PT_PT_SLAB_INITIAL_SPACE);
|
slab_grow(¤t.pt_slabs, pt_pt_slab_buf, PT_PT_SLAB_INITIAL_SPACE);
|
||||||
slab_grow(¤t.pt_children_slabs, pt_children_slab_buf, PT_CHILDREN_SLAB_INITIAL_SPACE);
|
slab_grow(¤t.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(¤t);
|
||||||
|
}
|
||||||
|
|
||||||
set_current_paging_state(¤t);
|
set_current_paging_state(¤t);
|
||||||
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
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user