/*
* Copyright (c) 2009, 2010, 2011, ETH Zurich.
+ * Copyright (c) 2014, HP Labs.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
*/
#include <barrelfish/barrelfish.h>
#include "vspace_internal.h"
-#include <stdio.h>
/**
* \brief Map the memory object into a region
struct pmap *pmap = vspace_get_pmap(vspace);
genvaddr_t vregion_base = vregion_get_base_addr(vregion);
genvaddr_t vregion_off = vregion_get_offset(vregion);
+ size_t vregion_size = vregion_get_size(vregion);
+ genvaddr_t vregion_end = vregion_off + vregion_size;
- err = pmap->f.unmap(pmap, vregion_base + vregion_off, memobj->size, NULL);
- if (err_is_fail(err)) {
- return err_push(err, LIB_ERR_PMAP_UNMAP);
- }
+ //printf("(%s:%d) unmap(0x%"PRIxGENVADDR", memobj->size = %zd) vregion size = %zd\n", __FILE__, __LINE__, vregion_base + vregion_off, memobj->size, vregion_size);
- /* Remove the vregion from the list */
- struct vregion_list *prev = NULL;
- for (struct vregion_list *elt = anon->vregion_list; elt != NULL;
- elt = elt->next) {
- if (elt->region == vregion) {
- if (prev == NULL) {
- assert(elt == anon->vregion_list);
- anon->vregion_list = elt->next;
- } else {
- assert(prev->next == elt);
- prev->next = elt->next;
+ // unmap all affected frames
+ struct memobj_frame_list *fwalk = anon->frame_list;
+ struct memobj_frame_list *fprev = NULL;
+ //printf("vregion_off = 0x%"PRIxGENVADDR"\n", vregion_off);
+ //printf("vregion_end = 0x%"PRIxGENVADDR"\n", vregion_end);
+ err = LIB_ERR_VSPACE_VREGION_NOT_FOUND;
+ while (fwalk) {
+ //printf("fwalk->offset = %zd\n", fwalk->offset);
+ //printf("fwalk->next = %p\n", fwalk->next);
+ if (fwalk->offset < vregion_off) {
+ fprev = fwalk;
+ fwalk = fwalk->next;
+ continue;
+ }
+ else if (fwalk->offset < vregion_end) {
+ err = pmap->f.unmap(pmap, vregion_base + vregion_off, fwalk->size, NULL);
+ if (err_is_fail(err)) {
+ return err_push(err, LIB_ERR_PMAP_UNMAP);
}
- slab_free(&anon->vregion_slab, elt);
- return SYS_ERR_OK;
+
+ /* Remove the vregion from the list */
+ struct vregion_list *prev = NULL;
+ for (struct vregion_list *elt = anon->vregion_list; elt != NULL;
+ elt = elt->next) {
+ if (elt->region == vregion) {
+ if (prev == NULL) {
+ assert(elt == anon->vregion_list);
+ anon->vregion_list = elt->next;
+ } else {
+ assert(prev->next == elt);
+ prev->next = elt->next;
+ }
+ slab_free(&anon->vregion_slab, elt);
+ err = SYS_ERR_OK;
+ }
+ }
+ vregion_off += fwalk->size;
+ fprev = fwalk;
+ fwalk = fwalk->next;
}
}
- return LIB_ERR_VSPACE_VREGION_NOT_FOUND; // XXX: not quite the right error
+ return err; // XXX: not quite the right error
}
/**
*
* Pagefault relies on frames inserted in order
*/
-static errval_t fill(struct memobj *memobj, genvaddr_t offset, struct capref frame,
- size_t size)
+static errval_t fill_foff(struct memobj *memobj, genvaddr_t offset, struct capref frame,
+ size_t size, genpaddr_t foffset)
{
errval_t err;
struct memobj_anon *anon = (struct memobj_anon*)memobj;
return LIB_ERR_SLAB_ALLOC_FAIL;
}
}
- new->offset = offset;
- new->frame = frame;
- new->size = size;
+ new->offset = offset;
+ new->frame = frame;
+ new->size = size;
+ new->foffset = foffset;
+
+ {
+ struct frame_identity id;
+ err = invoke_frame_identify(frame, &id);
+ assert(err_is_ok(err));
+ new->pa = id.base;
+ }
// Insert in order
struct memobj_frame_list *walk = anon->frame_list;
}
return SYS_ERR_OK;
}
+static errval_t fill(struct memobj *memobj, genvaddr_t offset, struct capref frame,
+ size_t size)
+{
+ return fill_foff(memobj, offset, frame, size, 0);
+}
/**
* \brief Unmap/remove one frame from the end of the memobj
size_t retsize;
assert((vregion_base + fwalk->offset) % BASE_PAGE_SIZE == 0);
+ //printf("(%s:%d) unmap(0x%"PRIxGENVADDR", %zd)\n", __FILE__, __LINE__, vregion_base + fwalk->offset, fwalk->size);
err = pmap->f.unmap(pmap, vregion_base + fwalk->offset, fwalk->size,
&retsize);
if (err_is_fail(err)) {
}
// Return the frame
- *ret_offset = fwalk->offset;
- *ret_frame = fwalk->frame;
+ if (ret_offset) {
+ *ret_offset = fwalk->offset;
+ }
+ if (ret_frame) {
+ *ret_frame = fwalk->frame;
+ }
if (fprev) {
fprev->next = fwalk->next;
} else {
genvaddr_t vregion_off = vregion_get_offset(vregion);
vregion_flags_t flags = vregion_get_flags(vregion);
err = pmap->f.map(pmap, base + vregion_off + walk->offset,
- walk->frame, 0, walk->size, flags, NULL, NULL);
+ walk->frame, walk->foffset, walk->size, flags,
+ NULL, NULL);
if (err_is_fail(err)) {
return err_push(err, LIB_ERR_PMAP_MAP);
}
memobj->f.pin = pin;
memobj->f.unpin = unpin;
memobj->f.fill = fill;
+ memobj->f.fill_foff = fill_foff;
memobj->f.unfill = unfill;
memobj->f.pagefault = pagefault;
memobj->f.pager_free = pager_free;
/**
* \brief Destroy the object
*
- * \bug NYI
*/
errval_t memobj_destroy_anon(struct memobj *memobj)
{
- return SYS_ERR_OK;
+ struct memobj_anon *m = (struct memobj_anon *)memobj;
+
+ errval_t err = SYS_ERR_OK;
+
+ struct vregion_list *vwalk = m->vregion_list;
+ while (vwalk) {
+ err = vregion_destroy(vwalk->region);
+ if (err_is_fail(err)) {
+ return err;
+ }
+ struct vregion_list *old = vwalk;
+ vwalk = vwalk->next;
+ slab_free(&m->vregion_slab, old);
+ }
+
+ struct memobj_frame_list *fwalk = m->frame_list;
+ while (fwalk) {
+ err = cap_delete(fwalk->frame);
+ if (err_is_fail(err)) {
+ return err;
+ }
+ struct memobj_frame_list *old = fwalk;
+ fwalk = fwalk->next;
+ slab_free(&m->frame_slab, old);
+ }
+ return err;
}