paging: Unmap and free
This commit is contained in:
parent
f2f7c37442
commit
24b4c54978
@ -41,6 +41,7 @@ struct ram_alloc_state {
|
|||||||
errval_t mem_connect_err;
|
errval_t mem_connect_err;
|
||||||
struct thread_mutex ram_alloc_lock;
|
struct thread_mutex ram_alloc_lock;
|
||||||
ram_alloc_func_t ram_alloc_func;
|
ram_alloc_func_t ram_alloc_func;
|
||||||
|
ram_free_func_t ram_free_func;
|
||||||
uint64_t default_minbase;
|
uint64_t default_minbase;
|
||||||
uint64_t default_maxlimit;
|
uint64_t default_maxlimit;
|
||||||
int base_capnum;
|
int base_capnum;
|
||||||
|
|||||||
@ -77,11 +77,6 @@ struct paging_state {
|
|||||||
// NOTE rueegges: remember if we are refilling so we can skip the checks
|
// NOTE rueegges: remember if we are refilling so we can skip the checks
|
||||||
uint8_t refilling;
|
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;
|
struct pt_vaddr_reg_t vaddr_head;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -25,12 +25,14 @@ __BEGIN_DECLS
|
|||||||
struct capref;
|
struct capref;
|
||||||
|
|
||||||
typedef errval_t (* ram_alloc_func_t)(struct capref *ret, size_t size, size_t alignment);
|
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_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_aligned(struct capref *ret, size_t size, size_t alignment);
|
||||||
errval_t ram_alloc(struct capref *retcap, size_t size);
|
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_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_set_affinity(uint64_t minbase, uint64_t maxlimit);
|
||||||
void ram_get_affinity(uint64_t *minbase, uint64_t *maxlimit);
|
void ram_get_affinity(uint64_t *minbase, uint64_t *maxlimit);
|
||||||
void ram_alloc_init(void);
|
void ram_alloc_init(void);
|
||||||
|
|||||||
@ -123,7 +123,7 @@ errval_t barrelfish_init_onthread(struct spawn_domain_params *params)
|
|||||||
// Initialize ram_alloc state
|
// Initialize ram_alloc state
|
||||||
ram_alloc_init();
|
ram_alloc_init();
|
||||||
/* All domains use smallcn to initialize */
|
/* 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)) {
|
if (err_is_fail(err)) {
|
||||||
return err_push(err, LIB_ERR_RAM_ALLOC_SET);
|
return err_push(err, LIB_ERR_RAM_ALLOC_SET);
|
||||||
}
|
}
|
||||||
|
|||||||
283
lib/aos/paging.c
283
lib/aos/paging.c
@ -16,6 +16,7 @@
|
|||||||
#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>
|
||||||
@ -34,8 +35,8 @@ static struct paging_state current;
|
|||||||
* \brief Helper function that allocates a slot and
|
* \brief Helper function that allocates a slot and
|
||||||
* creates a aarch64 page table capability for a certain level
|
* creates a aarch64 page table capability for a certain level
|
||||||
*/
|
*/
|
||||||
static errval_t pt_alloc(struct paging_state * st, enum objtype type,
|
static errval_t pt_alloc(struct paging_state * st, enum objtype type,
|
||||||
struct capref *ret)
|
struct capref *ret)
|
||||||
{
|
{
|
||||||
errval_t err;
|
errval_t err;
|
||||||
err = st->slot_alloc->alloc(st->slot_alloc, ret);
|
err = st->slot_alloc->alloc(st->slot_alloc, ret);
|
||||||
@ -61,11 +62,24 @@ __attribute__((unused)) static errval_t pt_alloc_l2(struct paging_state * st, st
|
|||||||
return pt_alloc(st, ObjType_VNode_AARCH64_l2, ret);
|
return pt_alloc(st, ObjType_VNode_AARCH64_l2, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((unused)) static errval_t pt_alloc_l3(struct paging_state * st, struct capref *ret)
|
__attribute__((unused)) static errval_t pt_alloc_l3(struct paging_state * st, struct capref *ret)
|
||||||
{
|
{
|
||||||
return pt_alloc(st, ObjType_VNode_AARCH64_l3, ret);
|
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) {
|
void pt_print_state(struct paging_state *st) {
|
||||||
// iterates over all the page table entries and prints them
|
// iterates over all the page table entries and prints them
|
||||||
debug_printf("L0\n");
|
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) {
|
for(size_t i3 = 0; i3 < PTABLE_ENTRIES; ++i3) {
|
||||||
struct pt_t *l4_pt = l3_pt->children[i3];
|
struct pt_t *l4_pt = l3_pt->children[i3];
|
||||||
if (l4_pt == NULL) continue;
|
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
|
// NOTE rueegges: each paging fixed call can use up to 4 pt slabs, up to 3 children slabs and up to 7 slots
|
||||||
@ -107,7 +128,7 @@ static errval_t pt_ensure_slabs(struct paging_state *st) {
|
|||||||
if(slab_freecount(&st->pt_slabs) <= PT_PT_SLAB_MIN_SPACE && !st->refilling) {
|
if(slab_freecount(&st->pt_slabs) <= PT_PT_SLAB_MIN_SPACE && !st->refilling) {
|
||||||
// ASSESSMENT M1: show refilling
|
// ASSESSMENT M1: show refilling
|
||||||
// debug_printf("DEBUG rueegges: pt_ensure_slabs - refilling pt_slab\n");
|
// debug_printf("DEBUG rueegges: pt_ensure_slabs - refilling pt_slab\n");
|
||||||
|
|
||||||
st->refilling = 1;
|
st->refilling = 1;
|
||||||
|
|
||||||
err = slab_default_refill(&st->pt_slabs);
|
err = slab_default_refill(&st->pt_slabs);
|
||||||
@ -119,19 +140,14 @@ static errval_t pt_ensure_slabs(struct paging_state *st) {
|
|||||||
return err_push(err, LIB_ERR_SLAB_REFILL);
|
return err_push(err, LIB_ERR_SLAB_REFILL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(slab_freecount(&st->pt_children_slabs) <= PT_CHILDREN_SLAB_MIN_SPACE && !st->refilling) {
|
if(slab_freecount(&st->pt_children_slabs) <= PT_CHILDREN_SLAB_MIN_SPACE && !st->refilling) {
|
||||||
// ASSESSMENT M1: show refilling
|
// ASSESSMENT M1: show refilling
|
||||||
// debug_printf("DEBUG rueegges: pt_ensure_slabs - refilling pt_children_slabs\n");
|
// debug_printf("DEBUG rueegges: pt_ensure_slabs - refilling pt_children_slabs\n");
|
||||||
|
|
||||||
st->refilling = 1;
|
st->refilling = 1;
|
||||||
|
|
||||||
struct capref frame_cap;
|
err = slab_refill_pages(&st->pt_children_slabs, LARGE_PAGE_SIZE);
|
||||||
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);
|
|
||||||
|
|
||||||
st->refilling = 0;
|
st->refilling = 0;
|
||||||
// debug_printf("DEBUG rueegges: pt_ensure_slabs - refilling pt_children_slabs DONE\n");
|
// 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;
|
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;
|
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);
|
// debug_printf("DEBUG rueegges: pt_ensure l%u\n", level);
|
||||||
|
|
||||||
// If this fails we got an l3 pt as the parent
|
// If this fails we got an l3 pt as the parent
|
||||||
assert(pt_parent->children != NULL);
|
assert(pt_parent->children != NULL);
|
||||||
assert(level > 0 && level <= 3);
|
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
|
// make sure slot and slab refilling is performed in time
|
||||||
err = pt_ensure_slabs(st);
|
err = pt_ensure_slabs(st);
|
||||||
if(err_is_fail(err)) {
|
if(err_is_fail(err)) {
|
||||||
return 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
|
// create the page table
|
||||||
struct capref pt_cap;
|
struct capref pt_cap;
|
||||||
err = pt_alloc_level(st, &pt_cap, level);
|
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;
|
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
|
// allocate shadow page table space
|
||||||
struct pt_t *pt_meta = (struct pt_t *) slab_alloc(&st->pt_slabs);
|
struct pt_t *pt_meta = (struct pt_t *) slab_alloc(&st->pt_slabs);
|
||||||
if(pt_meta == NULL) {
|
if(pt_meta == NULL) {
|
||||||
pt_save_allocation(st, pt_cap, level);
|
ram_free(pt_cap);
|
||||||
return LIB_ERR_SLAB_ALLOC_FAIL;
|
return LIB_ERR_SLAB_ALLOC_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pt_t **pt_children = (struct pt_t **) slab_alloc(&st->pt_children_slabs);
|
struct pt_t **pt_children = (struct pt_t **) slab_alloc(&st->pt_children_slabs);
|
||||||
if(pt_children == NULL) {
|
if(pt_children == NULL) {
|
||||||
slab_free(&st->pt_slabs, pt_meta);
|
slab_free(&st->pt_slabs, pt_meta);
|
||||||
pt_save_allocation(st, pt_cap, level);
|
ram_free(pt_cap);
|
||||||
return LIB_ERR_SLAB_ALLOC_FAIL;
|
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)) {
|
if (err_is_fail(err)) {
|
||||||
slab_free(&st->pt_slabs, pt_meta);
|
slab_free(&st->pt_slabs, pt_meta);
|
||||||
slab_free(&st->pt_children_slabs, pt_children);
|
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);
|
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);
|
err = vnode_map(pt_parent->cap_pt, pt_cap, pt_index, 0, 0, 1, pt_mapping);
|
||||||
if (err_is_fail(err)) {
|
if (err_is_fail(err)) {
|
||||||
errval_t err_err = st->slot_alloc->free(st->slot_alloc, pt_mapping);
|
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_slabs, pt_meta);
|
||||||
slab_free(&st->pt_children_slabs, pt_children);
|
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);
|
DEBUG_ERR(err, "Failed vnode_map for pt l%u", level);
|
||||||
return err_push(err, LIB_ERR_VNODE_MAP);
|
return err_push(err, LIB_ERR_VNODE_MAP);
|
||||||
}
|
}
|
||||||
@ -288,17 +247,15 @@ static errval_t pt_ensure(struct paging_state *st, struct pt_t *pt_parent, size_
|
|||||||
|
|
||||||
pt_parent->children[pt_index] = pt_meta;
|
pt_parent->children[pt_index] = pt_meta;
|
||||||
|
|
||||||
*pt_ret = pt_meta;
|
|
||||||
|
|
||||||
return SYS_ERR_OK;
|
return SYS_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO(M2): Implement this function.
|
* (M2): Implement this function.
|
||||||
* TODO(M4): Improve this function.
|
* TODO(M4): Improve this function.
|
||||||
* \brief Initialize the paging_state struct for the paging
|
* \brief Initialize the paging_state struct for the paging
|
||||||
* state of the calling process.
|
* state of the calling process.
|
||||||
*
|
*
|
||||||
* \param st The struct to be initialized, must not be NULL.
|
* \param st The struct to be initialized, must not be NULL.
|
||||||
* \param start_vaddr Virtual address allocation should start at
|
* \param start_vaddr Virtual address allocation should start at
|
||||||
* this address.
|
* this address.
|
||||||
@ -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,
|
errval_t paging_init_state(struct paging_state *st, lvaddr_t start_vaddr,
|
||||||
struct capref pdir, struct slot_allocator *ca)
|
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
|
// TODO (M4): Implement page fault handler that installs frames when a page fault
|
||||||
// occurs and keeps track of the virtual address space.
|
// occurs and keeps track of the virtual address space.
|
||||||
|
|
||||||
@ -330,23 +287,19 @@ errval_t paging_init_state(struct paging_state *st, lvaddr_t start_vaddr,
|
|||||||
st->vaddr_head.size = VADDR_SIZE - start_vaddr;
|
st->vaddr_head.size = VADDR_SIZE - start_vaddr;
|
||||||
st->vaddr_head.free = true;
|
st->vaddr_head.free = true;
|
||||||
st->vaddr_head.next = NULL;
|
st->vaddr_head.next = NULL;
|
||||||
|
|
||||||
st->slot_alloc = ca;
|
st->slot_alloc = ca;
|
||||||
st->refilling = 0;
|
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;
|
return SYS_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO(M2): Implement this function.
|
* (M2): Implement this function.
|
||||||
* TODO(M4): Improve this function.
|
* TODO(M4): Improve this function.
|
||||||
* \brief Initialize the paging_state struct for the paging state
|
* \brief Initialize the paging_state struct for the paging state
|
||||||
* of a child process.
|
* of a child process.
|
||||||
*
|
*
|
||||||
* \param st The struct to be initialized, must not be NULL.
|
* \param st The struct to be initialized, must not be NULL.
|
||||||
* \param start_vaddr Virtual address allocation should start at
|
* \param start_vaddr Virtual address allocation should start at
|
||||||
* this address.
|
* this address.
|
||||||
@ -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)
|
struct capref pdir, struct slot_allocator *ca)
|
||||||
{
|
{
|
||||||
errval_t err;
|
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
|
// TODO (M4): Implement page fault handler that installs frames when a page fault
|
||||||
// occurs and keeps track of the virtual address space.
|
// occurs and keeps track of the virtual address space.
|
||||||
struct capref pt_cap;
|
struct capref pt_cap;
|
||||||
@ -384,7 +337,7 @@ errval_t paging_init(void)
|
|||||||
{
|
{
|
||||||
errval_t err;
|
errval_t err;
|
||||||
debug_printf("paging_init\n");
|
debug_printf("paging_init\n");
|
||||||
// TODO (M2): Call paging_init_state for ¤t
|
// (M2): Call paging_init_state for ¤t
|
||||||
// TODO (M4): initialize self-paging handler
|
// TODO (M4): initialize self-paging handler
|
||||||
// TIP: use thread_set_exception_handler() to setup a page fault 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
|
// 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->free);
|
||||||
assert(target_region->size >= prefix_size + alloc_size);
|
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;
|
size_t postfix_size = target_region->size - prefix_size - alloc_size;
|
||||||
|
|
||||||
struct pt_vaddr_reg_t *prefix_reg = NULL;
|
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;
|
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;
|
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
|
* - Find a region of free virtual address space that is large enough to
|
||||||
* accomodate a buffer of size `bytes`.
|
* accomodate a buffer of size `bytes`.
|
||||||
*/
|
*/
|
||||||
@ -523,7 +475,7 @@ errval_t paging_alloc(struct paging_state *st, void **buf, size_t bytes, size_t
|
|||||||
while(vaddr_reg != NULL) {
|
while(vaddr_reg != NULL) {
|
||||||
// calculate the number of bytes to skip to achieve alignment
|
// calculate the number of bytes to skip to achieve alignment
|
||||||
size_t prefix_size = (alignment - (vaddr_reg->base & (alignment - 1))) % alignment;
|
size_t prefix_size = (alignment - (vaddr_reg->base & (alignment - 1))) % alignment;
|
||||||
|
|
||||||
// check if it is a free region of sufficient size
|
// check if it is a free region of sufficient size
|
||||||
if (vaddr_reg->free && vaddr_reg->size >= prefix_size + bytes) {
|
if (vaddr_reg->free && vaddr_reg->size >= prefix_size + bytes) {
|
||||||
|
|
||||||
@ -534,7 +486,7 @@ errval_t paging_alloc(struct paging_state *st, void **buf, size_t bytes, size_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
*buf = (void *) (vaddr_reg->base + prefix_size);
|
*buf = (void *) (vaddr_reg->base + prefix_size);
|
||||||
|
|
||||||
return SYS_ERR_OK;
|
return SYS_ERR_OK;
|
||||||
}
|
}
|
||||||
vaddr_reg = vaddr_reg -> next;
|
vaddr_reg = vaddr_reg -> next;
|
||||||
@ -560,7 +512,7 @@ errval_t paging_map_frame_attr(struct paging_state *st, void **buf, size_t bytes
|
|||||||
struct capref frame, int flags)
|
struct capref frame, int flags)
|
||||||
{
|
{
|
||||||
errval_t err;
|
errval_t err;
|
||||||
// TODO(M2):
|
// (M2):
|
||||||
// - Find and allocate free region of virtual address space of at least bytes in size.
|
// - 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
|
// - Map the user provided frame at the free virtual address
|
||||||
// - return the virtual address in the buf parameter
|
// - 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;
|
errval_t err;
|
||||||
/*
|
/*
|
||||||
* TODO(M1):
|
* (M1):
|
||||||
* - Map a frame assuming all mappings will fit into one leaf page table (L3)
|
* - 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.
|
* - 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
|
* - 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
|
// preconditions
|
||||||
|
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 <= 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 != NULL);
|
||||||
assert(st->slot_alloc != 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;
|
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
|
||||||
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) {
|
if (vaddr_reg->free == true) {
|
||||||
// make sure the virtual memory is not used by anyone else
|
// make sure the virtual memory is not used by anyone else
|
||||||
err = paging_insert_vaddr_reg(st, vaddr_reg, vaddr - vaddr_reg->base, bytes);
|
err = paging_insert_vaddr_reg(st, vaddr_reg, vaddr - vaddr_reg->base, bytes);
|
||||||
if (err_is_fail(err)) {
|
if (err_is_fail(err)) {
|
||||||
return 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;
|
break;
|
||||||
}
|
}
|
||||||
@ -658,39 +613,41 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
|
|||||||
|
|
||||||
// TODO rueegges: cleanup partially completed mapping?
|
// TODO rueegges: cleanup partially completed mapping?
|
||||||
size_t mapping_size;
|
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 l0_index = VMSAv8_64_L0_INDEX(current_vaddr);
|
||||||
capaddr_t l1_index = VMSAv8_64_L1_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 l2_index = VMSAv8_64_L2_INDEX(current_vaddr);
|
||||||
capaddr_t l3_index = VMSAv8_64_L3_INDEX(current_vaddr);
|
capaddr_t l3_index = VMSAv8_64_L3_INDEX(current_vaddr);
|
||||||
|
|
||||||
// get the size of the mapping
|
// 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
|
// get l1 page table
|
||||||
struct pt_t *l1_pt;
|
err = pt_ensure(st, l0_pt, l0_index, 1);
|
||||||
err = pt_ensure(st, l0_pt, l0_index, 1, &l1_pt);
|
|
||||||
if(err_is_fail(err)) {
|
if(err_is_fail(err)) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
struct pt_t *l1_pt = l0_pt->children[l0_index];
|
||||||
assert(l1_pt->children != NULL);
|
assert(l1_pt->children != NULL);
|
||||||
|
|
||||||
// get l2 page table
|
// get l2 page table
|
||||||
struct pt_t *l2_pt;
|
err = pt_ensure(st, l1_pt, l1_index, 2);
|
||||||
err = pt_ensure(st, l1_pt, l1_index, 2, &l2_pt);
|
|
||||||
if(err_is_fail(err)) {
|
if(err_is_fail(err)) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
struct pt_t *l2_pt = l1_pt->children[l1_index];
|
||||||
assert(l2_pt->children != NULL);
|
assert(l2_pt->children != NULL);
|
||||||
|
|
||||||
// get l3 page table
|
// get l3 page table
|
||||||
struct pt_t *l3_pt;
|
err = pt_ensure(st, l2_pt, l2_index, 3);
|
||||||
err = pt_ensure(st, l2_pt, l2_index, 3, &l3_pt);
|
|
||||||
if(err_is_fail(err)) {
|
if(err_is_fail(err)) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
struct pt_t *l3_pt = l2_pt->children[l2_index];
|
||||||
assert(l3_pt->children != NULL);
|
assert(l3_pt->children != NULL);
|
||||||
|
|
||||||
|
assert(l3_pt->children[l3_index] == NULL);
|
||||||
|
|
||||||
// debug_printf("DEBUG rueegges: paging_map_fixed_attr - allocate mapping meta\n");
|
// debug_printf("DEBUG rueegges: paging_map_fixed_attr - allocate mapping meta\n");
|
||||||
|
|
||||||
// make sure we have enough slot and slab space left
|
// make sure we have enough slot and slab space left
|
||||||
@ -731,8 +688,8 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
|
|||||||
// add the new page table metadata to the shadow tables
|
// add the new page table metadata to the shadow tables
|
||||||
l3_pt->children[l3_index] = pt_entry;
|
l3_pt->children[l3_index] = pt_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
// debug_printf("DEBUG rueegges: paging_map_fixed_attr - success\n");
|
// debug_printf("DEBUG rueegges: paging_map_fixed_attr - success\n");
|
||||||
|
|
||||||
return SYS_ERR_OK;
|
return SYS_ERR_OK;
|
||||||
}
|
}
|
||||||
@ -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)
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,6 +97,22 @@ errval_t ram_alloc(struct capref *ret, size_t size)
|
|||||||
return ram_alloc_aligned(ret, size, BASE_PAGE_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)
|
errval_t ram_available(genpaddr_t *available, genpaddr_t *total)
|
||||||
{
|
{
|
||||||
// TODO: Implement protocol to check amount of ram available with memserv
|
// 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;
|
ram_alloc_state->mem_connect_err = 0;
|
||||||
thread_mutex_init(&ram_alloc_state->ram_alloc_lock);
|
thread_mutex_init(&ram_alloc_state->ram_alloc_lock);
|
||||||
ram_alloc_state->ram_alloc_func = NULL;
|
ram_alloc_state->ram_alloc_func = NULL;
|
||||||
|
ram_alloc_state->ram_free_func = NULL;
|
||||||
ram_alloc_state->default_minbase = 0;
|
ram_alloc_state->default_minbase = 0;
|
||||||
ram_alloc_state->default_maxlimit = 0;
|
ram_alloc_state->default_maxlimit = 0;
|
||||||
ram_alloc_state->base_capnum = 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
|
* If local_allocator is NULL, it will be initialized to the default
|
||||||
* remote allocator.
|
* 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();
|
struct ram_alloc_state *ram_alloc_state = get_ram_alloc_state();
|
||||||
|
|
||||||
/* Special case */
|
/* Special case */
|
||||||
if (local_allocator != NULL) {
|
if (local_allocator != NULL) {
|
||||||
ram_alloc_state->ram_alloc_func = local_allocator;
|
ram_alloc_state->ram_alloc_func = local_allocator;
|
||||||
|
ram_alloc_state->ram_free_func = local_free;
|
||||||
return SYS_ERR_OK;
|
return SYS_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ram_alloc_state->ram_alloc_func = ram_alloc_remote;
|
ram_alloc_state->ram_alloc_func = ram_alloc_remote;
|
||||||
|
ram_alloc_state->ram_free_func = NULL;
|
||||||
return SYS_ERR_OK;
|
return SYS_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -228,6 +228,7 @@ errval_t slab_refill_no_pagefault(struct slab_allocator *slabs, struct capref fr
|
|||||||
alloc_bytes, frame, VREGION_FLAGS_READ_WRITE
|
alloc_bytes, frame, VREGION_FLAGS_READ_WRITE
|
||||||
);
|
);
|
||||||
if (err_is_fail(err)) {
|
if (err_is_fail(err)) {
|
||||||
|
// TODO: free the RAM, but without freeing the frame slot
|
||||||
cap_delete(frame);
|
cap_delete(frame);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -232,7 +232,6 @@ errval_t mm_free(struct mm *mm, struct capref cap)
|
|||||||
struct capability c;
|
struct capability c;
|
||||||
err = cap_direct_identify(cap, &c);
|
err = cap_direct_identify(cap, &c);
|
||||||
if (err_is_fail(err)) return err;
|
if (err_is_fail(err)) return err;
|
||||||
assert(c.type == mm->objtype);
|
|
||||||
genpaddr_t base = get_address(&c);
|
genpaddr_t base = get_address(&c);
|
||||||
assert(base != 0 && base % BASE_PAGE_SIZE == 0);
|
assert(base != 0 && base % BASE_PAGE_SIZE == 0);
|
||||||
gensize_t size = get_size(&c);
|
gensize_t size = get_size(&c);
|
||||||
|
|||||||
@ -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 {
|
struct allocate_state {
|
||||||
// TODO: add fields
|
|
||||||
struct paging_state *paging_state;
|
struct paging_state *paging_state;
|
||||||
|
struct temp_mapping *temp_mapping_head;
|
||||||
};
|
};
|
||||||
|
|
||||||
static errval_t elf_allocate(
|
static errval_t elf_allocate(
|
||||||
@ -86,7 +90,6 @@ static errval_t elf_allocate(
|
|||||||
alloc_bytes, frame, VREGION_FLAGS_READ_WRITE
|
alloc_bytes, frame, VREGION_FLAGS_READ_WRITE
|
||||||
);
|
);
|
||||||
if (err_is_fail(err)) return err;
|
if (err_is_fail(err)) return err;
|
||||||
*ret += base - sv;
|
|
||||||
|
|
||||||
// translate elf flags to paging flags
|
// translate elf flags to paging flags
|
||||||
uint32_t paging_flags = 0;
|
uint32_t paging_flags = 0;
|
||||||
@ -104,7 +107,14 @@ static errval_t elf_allocate(
|
|||||||
if (err_is_fail(err)) return err;
|
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;
|
return SYS_ERR_OK;
|
||||||
}
|
}
|
||||||
@ -238,6 +248,7 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
|
|||||||
// - Load the ELF binary
|
// - Load the ELF binary
|
||||||
struct allocate_state st = {
|
struct allocate_state st = {
|
||||||
.paging_state = &child_paging_state,
|
.paging_state = &child_paging_state,
|
||||||
|
.temp_mapping_head = NULL,
|
||||||
};
|
};
|
||||||
genvaddr_t entry;
|
genvaddr_t entry;
|
||||||
err = elf_load(EM_AARCH64, elf_allocate, &st, (lvaddr_t)elf_base, elf_bytes, &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;
|
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
|
// - Setup the dispatcher
|
||||||
err = frame_create(si->cspace_cap_dispframe, DISPATCHER_FRAME_SIZE, NULL);
|
err = frame_create(si->cspace_cap_dispframe, DISPATCHER_FRAME_SIZE, NULL);
|
||||||
if (err_is_fail(err)) {
|
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
|
// afeer: script page 104: set the first register
|
||||||
registers_set_param(enabled_area, (uint64_t) arguments_page_in_child);
|
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
|
// - Make the new dispatcher runnable
|
||||||
err = invoke_dispatcher(
|
err = invoke_dispatcher(
|
||||||
si->dispatcher, cap_dispatcher,
|
si->dispatcher, cap_dispatcher,
|
||||||
|
|||||||
@ -71,7 +71,7 @@ errval_t initialize_ram_alloc(void)
|
|||||||
// Initialize the generic RAM allocator to use our local allocator.
|
// Initialize the generic RAM allocator to use our local allocator.
|
||||||
// We do this here, because mm_add allocates memory for the slab allocator,
|
// We do this here, because mm_add allocates memory for the slab allocator,
|
||||||
// and that uses ram_alloc.
|
// 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)) {
|
if (err_is_fail(err)) {
|
||||||
return err_push(err, LIB_ERR_RAM_ALLOC_SET);
|
return err_push(err, LIB_ERR_RAM_ALLOC_SET);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user