paging: Unmap and free

This commit is contained in:
Jan Schär 2022-03-23 23:15:15 +01:00
parent f2f7c37442
commit 24b4c54978
10 changed files with 217 additions and 142 deletions

View File

@ -41,6 +41,7 @@ struct ram_alloc_state {
errval_t mem_connect_err;
struct thread_mutex ram_alloc_lock;
ram_alloc_func_t ram_alloc_func;
ram_free_func_t ram_free_func;
uint64_t default_minbase;
uint64_t default_maxlimit;
int base_capnum;

View File

@ -77,11 +77,6 @@ struct paging_state {
// NOTE rueegges: remember if we are refilling so we can skip the checks
uint8_t refilling;
// NOTE rueegges: use to track an already allocated page table in failure conditions
struct capref free_l1_vnode;
struct capref free_l2_vnode;
struct capref free_l3_vnode;
struct pt_vaddr_reg_t vaddr_head;
};

View File

@ -25,12 +25,14 @@ __BEGIN_DECLS
struct capref;
typedef errval_t (* ram_alloc_func_t)(struct capref *ret, size_t size, size_t alignment);
typedef errval_t (* ram_free_func_t)(struct capref cap);
errval_t ram_alloc_fixed(struct capref *ret, size_t size, size_t alignment);
errval_t ram_alloc_aligned(struct capref *ret, size_t size, size_t alignment);
errval_t ram_alloc(struct capref *retcap, size_t size);
errval_t ram_free(struct capref cap);
errval_t ram_available(genpaddr_t *available, genpaddr_t *total);
errval_t ram_alloc_set(ram_alloc_func_t local_allocator);
errval_t ram_alloc_set(ram_alloc_func_t local_allocator, ram_free_func_t local_free);
void ram_set_affinity(uint64_t minbase, uint64_t maxlimit);
void ram_get_affinity(uint64_t *minbase, uint64_t *maxlimit);
void ram_alloc_init(void);

View File

@ -123,7 +123,7 @@ errval_t barrelfish_init_onthread(struct spawn_domain_params *params)
// Initialize ram_alloc state
ram_alloc_init();
/* All domains use smallcn to initialize */
err = ram_alloc_set(ram_alloc_fixed);
err = ram_alloc_set(ram_alloc_fixed, NULL);
if (err_is_fail(err)) {
return err_push(err, LIB_ERR_RAM_ALLOC_SET);
}

View File

@ -16,6 +16,7 @@
#include <aos/paging.h>
#include <aos/except.h>
#include <aos/slab.h>
#include <aos/slab.h>
#include "threads_priv.h"
#include <stdio.h>
@ -66,6 +67,19 @@ __attribute__((unused)) static errval_t pt_alloc_l3(struct paging_state * st, st
return pt_alloc(st, ObjType_VNode_AARCH64_l3, ret);
}
static errval_t pt_alloc_level(struct paging_state *st, struct capref *pt_cap, uint8_t level) {
switch(level){
case 1:
return pt_alloc_l1(st, pt_cap);
case 2:
return pt_alloc_l2(st, pt_cap);
case 3:
return pt_alloc_l3(st, pt_cap);
default:
return ERR_INVALID_ARGS;
}
}
void pt_print_state(struct paging_state *st) {
// iterates over all the page table entries and prints them
debug_printf("L0\n");
@ -88,11 +102,18 @@ void pt_print_state(struct paging_state *st) {
for(size_t i3 = 0; i3 < PTABLE_ENTRIES; ++i3) {
struct pt_t *l4_pt = l3_pt->children[i3];
if (l4_pt == NULL) continue;
debug_printf(" %lu -> Map\n", i3);
debug_printf(" %lu -> Map, size: %lu\n", i3, l4_pt->mapping_size);
}
}
}
}
debug_printf("ranges:\n");
struct pt_vaddr_reg_t *reg = &st->vaddr_head;
while (reg != NULL) {
debug_printf("- base=%lu, size=%lu, %s\n", reg->base, reg->size, reg->free ? "free" : "in use");
reg = reg->next;
}
}
// NOTE rueegges: each paging fixed call can use up to 4 pt slabs, up to 3 children slabs and up to 7 slots
@ -126,12 +147,7 @@ static errval_t pt_ensure_slabs(struct paging_state *st) {
st->refilling = 1;
struct capref frame_cap;
err = st->slot_alloc->alloc(st->slot_alloc, &frame_cap);
if (err_is_fail(err)) {
return err_push(err, LIB_ERR_SLOT_ALLOC);
}
err = slab_refill_no_pagefault(&st->pt_children_slabs, frame_cap, LARGE_PAGE_SIZE);
err = slab_refill_pages(&st->pt_children_slabs, LARGE_PAGE_SIZE);
st->refilling = 0;
// debug_printf("DEBUG rueegges: pt_ensure_slabs - refilling pt_children_slabs DONE\n");
@ -144,90 +160,27 @@ static errval_t pt_ensure_slabs(struct paging_state *st) {
return SYS_ERR_OK;
}
static errval_t pt_alloc_level(struct paging_state *st, struct capref *pt_cap, uint8_t level) {
// NOTE rueegges: ensures that a page table exists at the specified index in the parent page table
static errval_t pt_ensure(struct paging_state *st, struct pt_t *pt_parent, size_t pt_index, uint8_t level){
errval_t err;
switch(level){
case 1:
if(!capref_is_null(st->free_l1_vnode)){
*pt_cap = st->free_l1_vnode;
st->free_l1_vnode = NULL_CAP;
err = SYS_ERR_OK;
} else {
err = pt_alloc_l1(st, pt_cap);
}
break;
case 2:
if(!capref_is_null(st->free_l2_vnode)){
*pt_cap = st->free_l2_vnode;
st->free_l2_vnode = NULL_CAP;
err = SYS_ERR_OK;
} else {
err = pt_alloc_l2(st, pt_cap);
}
break;
case 3:
if(!capref_is_null(st->free_l3_vnode)){
*pt_cap = st->free_l3_vnode;
st->free_l3_vnode = NULL_CAP;
err = SYS_ERR_OK;
} else {
err = pt_alloc_l3(st, pt_cap);
}
break;
default:
err = ERR_INVALID_ARGS;
break;
}
return err;
}
static void pt_save_allocation(struct paging_state *st, struct capref cap, uint8_t level) {
switch(level){
case 1:
assert(capref_is_null(st->free_l1_vnode));
st->free_l1_vnode = cap;
break;
case 2:
assert(capref_is_null(st->free_l2_vnode));
st->free_l2_vnode = cap;
break;
case 3:
assert(capref_is_null(st->free_l3_vnode));
st->free_l3_vnode = cap;
break;
default:
assert(false);
break;
}
}
// NOTE rueegges: ensures that a page table exists at the specified index in the parent page table and return it
static errval_t pt_ensure(struct paging_state *st, struct pt_t *pt_parent, size_t pt_index, uint8_t level, struct pt_t **pt_ret){
errval_t err;
struct pt_t *res;
// debug_printf("DEBUG rueegges: pt_ensure l%u\n", level);
// If this fails we got an l3 pt as the parent
assert(pt_parent->children != NULL);
assert(level > 0 && level <= 3);
// MUST DO before check if table already exists since it might create it
// check if the page table already exists
if (pt_parent->children[pt_index] != NULL) {
return SYS_ERR_OK;
}
// make sure slot and slab refilling is performed in time
err = pt_ensure_slabs(st);
if(err_is_fail(err)) {
return err;
}
// check if the page table already exists
res = pt_parent->children[pt_index];
if (res != NULL) {
*pt_ret = res;
return SYS_ERR_OK;
}
// create the page table
struct capref pt_cap;
err = pt_alloc_level(st, &pt_cap, level);
@ -236,24 +189,17 @@ static errval_t pt_ensure(struct paging_state *st, struct pt_t *pt_parent, size_
return err;
}
// check again if the page table already exists
res = pt_parent->children[pt_index];
if (res != NULL) {
*pt_ret = res;
return SYS_ERR_OK;
}
// allocate shadow page table space
struct pt_t *pt_meta = (struct pt_t *) slab_alloc(&st->pt_slabs);
if(pt_meta == NULL) {
pt_save_allocation(st, pt_cap, level);
ram_free(pt_cap);
return LIB_ERR_SLAB_ALLOC_FAIL;
}
struct pt_t **pt_children = (struct pt_t **) slab_alloc(&st->pt_children_slabs);
if(pt_children == NULL) {
slab_free(&st->pt_slabs, pt_meta);
pt_save_allocation(st, pt_cap, level);
ram_free(pt_cap);
return LIB_ERR_SLAB_ALLOC_FAIL;
}
@ -263,9 +209,22 @@ static errval_t pt_ensure(struct paging_state *st, struct pt_t *pt_parent, size_
if (err_is_fail(err)) {
slab_free(&st->pt_slabs, pt_meta);
slab_free(&st->pt_children_slabs, pt_children);
pt_save_allocation(st, pt_cap, level);
ram_free(pt_cap);
return err_push(err, LIB_ERR_SLOT_ALLOC);
}
// check again if the page table already exists
if (pt_parent->children[pt_index] != NULL) {
errval_t err_err = st->slot_alloc->free(st->slot_alloc, pt_mapping);
if (err_is_fail(err_err)) {
DEBUG_ERR(err_err, "Failed to free capability slot during error handling");
}
slab_free(&st->pt_slabs, pt_meta);
slab_free(&st->pt_children_slabs, pt_children);
ram_free(pt_cap);
return SYS_ERR_OK;
}
err = vnode_map(pt_parent->cap_pt, pt_cap, pt_index, 0, 0, 1, pt_mapping);
if (err_is_fail(err)) {
errval_t err_err = st->slot_alloc->free(st->slot_alloc, pt_mapping);
@ -274,7 +233,7 @@ static errval_t pt_ensure(struct paging_state *st, struct pt_t *pt_parent, size_
}
slab_free(&st->pt_slabs, pt_meta);
slab_free(&st->pt_children_slabs, pt_children);
pt_save_allocation(st, pt_cap, level);
ram_free(pt_cap);
DEBUG_ERR(err, "Failed vnode_map for pt l%u", level);
return err_push(err, LIB_ERR_VNODE_MAP);
}
@ -288,13 +247,11 @@ static errval_t pt_ensure(struct paging_state *st, struct pt_t *pt_parent, size_
pt_parent->children[pt_index] = pt_meta;
*pt_ret = pt_meta;
return SYS_ERR_OK;
}
/**
* TODO(M2): Implement this function.
* (M2): Implement this function.
* TODO(M4): Improve this function.
* \brief Initialize the paging_state struct for the paging
* state of the calling process.
@ -310,7 +267,7 @@ static errval_t pt_ensure(struct paging_state *st, struct pt_t *pt_parent, size_
errval_t paging_init_state(struct paging_state *st, lvaddr_t start_vaddr,
struct capref pdir, struct slot_allocator *ca)
{
// TODO (M2): Implement state struct initialization
// (M2): Implement state struct initialization
// TODO (M4): Implement page fault handler that installs frames when a page fault
// occurs and keeps track of the virtual address space.
@ -334,15 +291,11 @@ errval_t paging_init_state(struct paging_state *st, lvaddr_t start_vaddr,
st->slot_alloc = ca;
st->refilling = 0;
st->free_l1_vnode = NULL_CAP;
st->free_l2_vnode = NULL_CAP;
st->free_l3_vnode = NULL_CAP;
return SYS_ERR_OK;
}
/**
* TODO(M2): Implement this function.
* (M2): Implement this function.
* TODO(M4): Improve this function.
* \brief Initialize the paging_state struct for the paging state
* of a child process.
@ -359,7 +312,7 @@ errval_t paging_init_state_foreign(struct paging_state *st, lvaddr_t start_vaddr
struct capref pdir, struct slot_allocator *ca)
{
errval_t err;
// TODO (M2): Implement state struct initialization
// (M2): Implement state struct initialization
// TODO (M4): Implement page fault handler that installs frames when a page fault
// occurs and keeps track of the virtual address space.
struct capref pt_cap;
@ -384,7 +337,7 @@ errval_t paging_init(void)
{
errval_t err;
debug_printf("paging_init\n");
// TODO (M2): Call paging_init_state for &current
// (M2): Call paging_init_state for &current
// TODO (M4): initialize self-paging handler
// TIP: use thread_set_exception_handler() to setup a page fault handler
// TIP: Think about the fact that later on, you'll have to make sure that
@ -425,7 +378,7 @@ static errval_t paging_insert_vaddr_reg(struct paging_state *st, struct pt_vaddr
assert(target_region->free);
assert(target_region->size >= prefix_size + alloc_size);
// calculate the number of bytes that are left overafter the region
// calculate the number of bytes that are left over after the region
size_t postfix_size = target_region->size - prefix_size - alloc_size;
struct pt_vaddr_reg_t *prefix_reg = NULL;
@ -481,7 +434,6 @@ static errval_t paging_insert_vaddr_reg(struct paging_state *st, struct pt_vaddr
}
return SYS_ERR_OK;
}
@ -501,7 +453,7 @@ errval_t paging_alloc(struct paging_state *st, void **buf, size_t bytes, size_t
errval_t err;
/**
* TODO(M2): Implement this function
* (M2): Implement this function
* - Find a region of free virtual address space that is large enough to
* accomodate a buffer of size `bytes`.
*/
@ -560,7 +512,7 @@ errval_t paging_map_frame_attr(struct paging_state *st, void **buf, size_t bytes
struct capref frame, int flags)
{
errval_t err;
// TODO(M2):
// (M2):
// - Find and allocate free region of virtual address space of at least bytes in size.
// - Map the user provided frame at the free virtual address
// - return the virtual address in the buf parameter
@ -599,9 +551,9 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
{
errval_t err;
/*
* TODO(M1):
* (M1):
* - Map a frame assuming all mappings will fit into one leaf page table (L3)
* TODO(M2):
* (M2):
* - General case: you will need to handle mappings spanning multiple leaf page tables.
* - Make sure to update your paging state to reflect the newly mapped region
*
@ -610,9 +562,10 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
*/
// preconditions
assert(vaddr % BASE_PAGE_SIZE == 0);
assert(bytes % BASE_PAGE_SIZE == 0);
lvaddr_t end_vaddr = vaddr + bytes;
assert(end_vaddr <= VADDR_OFFSET + 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->slot_alloc != NULL);
@ -641,13 +594,15 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
struct pt_vaddr_reg_t *vaddr_reg = &st->vaddr_head;
for(;vaddr_reg != NULL; vaddr_reg = vaddr_reg->next) {
// we have found the region it belongs to
if(vaddr_reg->base <= vaddr && vaddr + bytes <= vaddr_reg->base + vaddr_reg->size) {
if(vaddr_reg->base <= vaddr && end_vaddr <= vaddr_reg->base + vaddr_reg->size) {
if (vaddr_reg->free == true) {
// make sure the virtual memory is not used by anyone else
err = paging_insert_vaddr_reg(st, vaddr_reg, vaddr - vaddr_reg->base, bytes);
if (err_is_fail(err)) {
return err;
}
} else if (!(vaddr_reg->base == vaddr && end_vaddr == vaddr_reg->base + vaddr_reg->size)) {
return LIB_ERR_PMAP_ADDR_NOT_FREE;
}
break;
}
@ -658,39 +613,41 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
// TODO rueegges: cleanup partially completed mapping?
size_t mapping_size;
for(lvaddr_t current_vaddr = vaddr; current_vaddr < vaddr + bytes; 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 l1_index = VMSAv8_64_L1_INDEX(current_vaddr);
capaddr_t l2_index = VMSAv8_64_L2_INDEX(current_vaddr);
capaddr_t l3_index = VMSAv8_64_L3_INDEX(current_vaddr);
// get the size of the mapping
mapping_size = MIN(PTABLE_ENTRIES - l3_index, (vaddr + bytes - current_vaddr) / BASE_PAGE_SIZE);
mapping_size = MIN(PTABLE_ENTRIES - l3_index, (end_vaddr - current_vaddr) / BASE_PAGE_SIZE);
// get l1 page table
struct pt_t *l1_pt;
err = pt_ensure(st, l0_pt, l0_index, 1, &l1_pt);
err = pt_ensure(st, l0_pt, l0_index, 1);
if(err_is_fail(err)) {
return err;
}
struct pt_t *l1_pt = l0_pt->children[l0_index];
assert(l1_pt->children != NULL);
// get l2 page table
struct pt_t *l2_pt;
err = pt_ensure(st, l1_pt, l1_index, 2, &l2_pt);
err = pt_ensure(st, l1_pt, l1_index, 2);
if(err_is_fail(err)) {
return err;
}
struct pt_t *l2_pt = l1_pt->children[l1_index];
assert(l2_pt->children != NULL);
// get l3 page table
struct pt_t *l3_pt;
err = pt_ensure(st, l2_pt, l2_index, 3, &l3_pt);
err = pt_ensure(st, l2_pt, l2_index, 3);
if(err_is_fail(err)) {
return err;
}
struct pt_t *l3_pt = l2_pt->children[l2_index];
assert(l3_pt->children != NULL);
assert(l3_pt->children[l3_index] == NULL);
// debug_printf("DEBUG rueegges: paging_map_fixed_attr - allocate mapping meta\n");
// make sure we have enough slot and slab space left
@ -752,5 +709,73 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
*/
errval_t paging_unmap(struct paging_state *st, const void *region)
{
return LIB_ERR_NOT_IMPLEMENTED;
errval_t err;
lvaddr_t vaddr = (lvaddr_t)region;
assert(vaddr % BASE_PAGE_SIZE == 0);
struct pt_vaddr_reg_t *prev_reg = NULL;
struct pt_vaddr_reg_t *vaddr_reg = &st->vaddr_head;
for (; vaddr_reg != NULL; vaddr_reg = vaddr_reg->next) {
if (vaddr_reg->base == vaddr && !vaddr_reg->free) {
break;
}
prev_reg = vaddr_reg;
}
if (vaddr_reg == NULL) {
return LIB_ERR_PMAP_NOT_MAPPED;
}
struct pt_t *l0_pt = &st->l0_pt;
assert(l0_pt->children != NULL);
lvaddr_t end_vaddr = vaddr + vaddr_reg->size;
size_t mapping_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 l1_index = VMSAv8_64_L1_INDEX(current_vaddr);
capaddr_t l2_index = VMSAv8_64_L2_INDEX(current_vaddr);
capaddr_t l3_index = VMSAv8_64_L3_INDEX(current_vaddr);
mapping_size = MIN(PTABLE_ENTRIES - l3_index, (end_vaddr - current_vaddr) / BASE_PAGE_SIZE);
struct pt_t *l1_pt = l0_pt->children[l0_index];
assert(l1_pt->children != NULL);
struct pt_t *l2_pt = l1_pt->children[l1_index];
assert(l2_pt->children != NULL);
struct pt_t *l3_pt = l2_pt->children[l2_index];
assert(l3_pt->children != NULL);
struct pt_t *pt_entry = l3_pt->children[l3_index];
assert(pt_entry != NULL);
err = cap_delete(pt_entry->cap_mapping);
if (err_is_fail(err)) return err_push(err, LIB_ERR_VNODE_UNMAP);
err = st->slot_alloc->free(st->slot_alloc, pt_entry->cap_mapping);
if (err_is_fail(err)) return err_push(err, LIB_ERR_SLOT_FREE);
l3_pt->children[l3_index] = NULL;
slab_free(&st->pt_slabs, pt_entry);
}
vaddr_reg->free = true;
// Merge free regions
if (prev_reg != NULL && prev_reg->free && prev_reg->base + prev_reg->size == vaddr_reg->base) {
prev_reg->size += vaddr_reg->size;
prev_reg->next = vaddr_reg->next;
slab_free(&st->pt_slabs, vaddr_reg);
vaddr_reg = prev_reg;
}
struct pt_vaddr_reg_t *next_reg = vaddr_reg->next;
if (next_reg != NULL && next_reg->free && vaddr_reg->base + vaddr_reg->size == next_reg->base) {
vaddr_reg->size += next_reg->size;
vaddr_reg->next = next_reg->next;
slab_free(&st->pt_slabs, next_reg);
}
return SYS_ERR_OK;
}

View File

@ -97,6 +97,22 @@ errval_t ram_alloc(struct capref *ret, size_t size)
return ram_alloc_aligned(ret, size, BASE_PAGE_SIZE);
}
/**
* \brief Frees allocated memory
*
* \param cap A capability whose memory was allocated with ram_alloc.
* It will be destroyed by this function.
*/
errval_t ram_free(struct capref cap)
{
struct ram_alloc_state *ram_alloc_state = get_ram_alloc_state();
if (ram_alloc_state->ram_free_func == NULL) {
debug_printf("WARN: cannot free RAM, not supported by current allocator\n");
return SYS_ERR_OK;
}
return ram_alloc_state->ram_free_func(cap);
}
errval_t ram_available(genpaddr_t *available, genpaddr_t *total)
{
// TODO: Implement protocol to check amount of ram available with memserv
@ -114,6 +130,7 @@ void ram_alloc_init(void)
ram_alloc_state->mem_connect_err = 0;
thread_mutex_init(&ram_alloc_state->ram_alloc_lock);
ram_alloc_state->ram_alloc_func = NULL;
ram_alloc_state->ram_free_func = NULL;
ram_alloc_state->default_minbase = 0;
ram_alloc_state->default_maxlimit = 0;
ram_alloc_state->base_capnum = 0;
@ -125,16 +142,18 @@ void ram_alloc_init(void)
* If local_allocator is NULL, it will be initialized to the default
* remote allocator.
*/
errval_t ram_alloc_set(ram_alloc_func_t local_allocator)
errval_t ram_alloc_set(ram_alloc_func_t local_allocator, ram_free_func_t local_free)
{
struct ram_alloc_state *ram_alloc_state = get_ram_alloc_state();
/* Special case */
if (local_allocator != NULL) {
ram_alloc_state->ram_alloc_func = local_allocator;
ram_alloc_state->ram_free_func = local_free;
return SYS_ERR_OK;
}
ram_alloc_state->ram_alloc_func = ram_alloc_remote;
ram_alloc_state->ram_free_func = NULL;
return SYS_ERR_OK;
}

View File

@ -228,6 +228,7 @@ errval_t slab_refill_no_pagefault(struct slab_allocator *slabs, struct capref fr
alloc_bytes, frame, VREGION_FLAGS_READ_WRITE
);
if (err_is_fail(err)) {
// TODO: free the RAM, but without freeing the frame slot
cap_delete(frame);
return err;
}

View File

@ -232,7 +232,6 @@ errval_t mm_free(struct mm *mm, struct capref cap)
struct capability c;
err = cap_direct_identify(cap, &c);
if (err_is_fail(err)) return err;
assert(c.type == mm->objtype);
genpaddr_t base = get_address(&c);
assert(base != 0 && base % BASE_PAGE_SIZE == 0);
gensize_t size = get_size(&c);

View File

@ -49,10 +49,14 @@ static void armv8_set_registers(void *arch_load_info,
struct temp_mapping {
struct temp_mapping *next;
void *addr;
};
struct allocate_state {
// TODO: add fields
struct paging_state *paging_state;
struct temp_mapping *temp_mapping_head;
};
static errval_t elf_allocate(
@ -86,7 +90,6 @@ static errval_t elf_allocate(
alloc_bytes, frame, VREGION_FLAGS_READ_WRITE
);
if (err_is_fail(err)) return err;
*ret += base - sv;
// translate elf flags to paging flags
uint32_t paging_flags = 0;
@ -104,7 +107,14 @@ static errval_t elf_allocate(
if (err_is_fail(err)) return err;
// TODO: Keep track of the mapped regions, so you can unmap them later.
// Keep track of the mapped regions, so you can unmap them later.
struct temp_mapping *tm = malloc(sizeof(struct temp_mapping));
if (tm == NULL) return LIB_ERR_MALLOC_FAIL;
tm->next = st->temp_mapping_head;
tm->addr = *ret;
st->temp_mapping_head = tm;
*ret += base - sv;
return SYS_ERR_OK;
}
@ -238,6 +248,7 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
// - Load the ELF binary
struct allocate_state st = {
.paging_state = &child_paging_state,
.temp_mapping_head = NULL,
};
genvaddr_t entry;
err = elf_load(EM_AARCH64, elf_allocate, &st, (lvaddr_t)elf_base, elf_bytes, &entry);
@ -250,6 +261,22 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
got_addr = got_shdr->sh_addr;
}
debug_printf("SPAWN: self paging state after loading:\n");
pt_print_state(get_current_paging_state());
err = paging_unmap(get_current_paging_state(), elf_base);
if (err_is_fail(err)) return err_push(err, LIB_ERR_PMAP_UNMAP);
while (st.temp_mapping_head != NULL) {
struct temp_mapping *tm = st.temp_mapping_head;
err = paging_unmap(get_current_paging_state(), tm->addr);
if (err_is_fail(err)) return err_push(err, LIB_ERR_PMAP_UNMAP);
st.temp_mapping_head = tm->next;
free(tm);
}
debug_printf("SPAWN: self paging state after unmapping:\n");
pt_print_state(get_current_paging_state());
// - Setup the dispatcher
err = frame_create(si->cspace_cap_dispframe, DISPATCHER_FRAME_SIZE, NULL);
if (err_is_fail(err)) {
@ -353,6 +380,12 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
// afeer: script page 104: set the first register
registers_set_param(enabled_area, (uint64_t) arguments_page_in_child);
err = paging_unmap(get_current_paging_state(), (void *)handle);
if (err_is_fail(err)) return err_push(err, LIB_ERR_PMAP_UNMAP);
err = paging_unmap(get_current_paging_state(), arguments_page_in_self);
if (err_is_fail(err)) return err_push(err, LIB_ERR_PMAP_UNMAP);
// - Make the new dispatcher runnable
err = invoke_dispatcher(
si->dispatcher, cap_dispatcher,

View File

@ -71,7 +71,7 @@ errval_t initialize_ram_alloc(void)
// Initialize the generic RAM allocator to use our local allocator.
// We do this here, because mm_add allocates memory for the slab allocator,
// and that uses ram_alloc.
err = ram_alloc_set(aos_ram_alloc_aligned);
err = ram_alloc_set(aos_ram_alloc_aligned, aos_ram_free);
if (err_is_fail(err)) {
return err_push(err, LIB_ERR_RAM_ALLOC_SET);
}