/* * Call to give up a page of memory in an spd at an address. */ void mman_revoke_page(spdid_t spd, vaddr_t addr, int flags) { int alias, i; struct mem_cell *mc; struct mapping_info *mi; mc = find_cell(spd, addr, &alias); if (!mc) { /* FIXME: add return codes to this call */ return; } mi = mc->map; for (i = 0 ; i < MAX_ALIASES ; i++) { int idx; if (i == alias || !mi[i].owner_spd || !is_descendent(mi, alias, i)) continue; idx = cos_mmap_cntl(COS_MMAP_REVOKE, 0, mi[i].owner_spd, mi[i].addr, 0); assert(&cells[idx] == mc); /* mark page as removed */ mi[i].addr = 0; mc->naliases--; } /* Go through and free all pages marked as removed */ for (i = 0 ; i < MAX_ALIASES ; i++) { if (mi[i].addr == 0 && mi[i].owner_spd) { mi[i].owner_spd = 0; mi[i].parent = 0; } } return; }
/* * Call to get a page of memory at a location. */ vaddr_t mman_get_page(spdid_t spd, vaddr_t addr, int flags) { struct mem_cell *c; struct mapping_info *m; c = find_unused(); if (!c) { printc("mm: no more available pages!\n"); goto err; } c->naliases++; m = c->map; m->owner_spd = spd; m->addr = addr; m->parent = -1; /* Here we check for overwriting an already established mapping. */ if (cos_mmap_cntl(COS_MMAP_GRANT, 0, spd, addr, cell_index(c))) { printc("mm: could not grant page @ %x to spd %d\n", (unsigned int)addr, (unsigned int)spd); m->owner_spd = m->addr = 0; goto err; } return addr; err: return 0; }
/* * Make an alias to a page in a source spd @ a source address to a * destination spd/addr */ vaddr_t mman_alias_page(spdid_t s_spd, vaddr_t s_addr, spdid_t d_spd, vaddr_t d_addr) { int alias = -1, i; struct mem_cell *c; struct mapping_info *base; c = find_cell(s_spd, s_addr, &alias); if (-1 == alias) {printc("WTF\n");goto err;} assert(alias >= 0 && alias < MAX_ALIASES); base = c->map; for (i = 0 ; i < MAX_ALIASES ; i++) { if (alias == i || base[i].owner_spd != 0 || base[i].addr != 0) { continue; } if (cos_mmap_cntl(COS_MMAP_GRANT, 0, d_spd, d_addr, cell_index(c))) { printc("mm: could not alias page @ %x to spd %d from %x(%d)\n", (unsigned int)d_addr, (unsigned int)d_spd, (unsigned int)s_addr, (unsigned int)s_spd); goto err; } base[i].owner_spd = d_spd; base[i].addr = d_addr; base[i].parent = alias; c->naliases++; return d_addr; } /* no available alias slots! */ err: return 0; }
static inline void * __page_get(void) { void *hp = cos_get_vas_page(); struct frame *f = frame_alloc(); assert(hp && f); frame_ref(f); if (cos_mmap_cntl(COS_MMAP_GRANT, 0, cos_spd_id(), (vaddr_t)hp, frame_index(f))) { BUG(); } return hp; }
static inline void * __page_get(void) { void *hp = cos_get_vas_page(); struct frame *f = frame_alloc(); assert(hp && f); frame_ref(f); f->nmaps = -1; /* belongs to us... */ f->c.addr = (vaddr_t)hp; /* ...at this address */ if (cos_mmap_cntl(COS_MMAP_GRANT, MAPPING_RW, cos_spd_id(), (vaddr_t)hp, frame_index(f))) { printc("grant @ %p for frame %d\n", hp, frame_index(f)); BUG(); } return hp; }
/* Make a child mapping */ static struct mapping * mapping_crt(struct mapping *p, struct frame *f, spdid_t dest, vaddr_t to, int flags) { struct comp_vas *cv = cvas_lookup(dest); struct mapping *m = NULL; long idx = to >> PAGE_SHIFT; assert(!p || p->f == f); assert(dest && to); /* no vas structure for this spd yet... */ if (!cv) { cv = cvas_alloc(dest); if (!cv) goto done; assert(cv == cvas_lookup(dest)); } assert(cv->pages); if (cvect_lookup(cv->pages, idx)) goto collision; cvas_ref(cv); m = cslab_alloc_mapping(); if (!m) goto collision; if (cos_mmap_cntl(COS_MMAP_GRANT, flags, dest, to, frame_index(f))) { printc("mem_man: could not grant at %x:%d\n", dest, (int)to); goto no_mapping; } mapping_init(m, dest, to, p, f); assert(!p || frame_nrefs(f) > 0); frame_ref(f); assert(frame_nrefs(f) > 0); if (cvect_add(cv->pages, m, idx)) BUG(); done: return m; no_mapping: cslab_free_mapping(m); collision: cvas_deref(cv); m = NULL; goto done; }
static void __mapping_destroy(struct mapping *m) { struct comp_vas *cv; int idx; assert(m); assert(EMPTY_LIST(m, _s, s_)); assert(m->p == NULL && m->c == NULL); cv = cvas_lookup(m->spdid); assert(cv && cv->pages); assert(m == cvect_lookup(cv->pages, m->addr >> PAGE_SHIFT)); cvect_del(cv->pages, m->addr >> PAGE_SHIFT); cvas_deref(cv); idx = cos_mmap_cntl(COS_MMAP_REVOKE, 0, m->spdid, m->addr, 0); assert(idx == frame_index(m->f)); frame_deref(m->f); cslab_free_mapping(m); }
/* * FIXME: change interface to include the component making the call to * make sure that it owns the page it is trying to unmap (and the one * it is unmapping is a descendent. */ void mman_release_page(spdid_t spd, vaddr_t addr, int flags) { int alias; long idx; struct mem_cell *mc; struct mapping_info *mi; mman_revoke_page(spd, addr, flags); mc = find_cell(spd, addr, &alias); if (!mc) { /* FIXME: add return codes to this call */ return; } mi = mc->map; idx = cos_mmap_cntl(COS_MMAP_REVOKE, 0, mi[alias].owner_spd, mi[alias].addr, 0); assert(&cells[idx] == mc); mi[alias].addr = 0; mi[alias].owner_spd = 0; mi[alias].parent = 0; mc->naliases--; return; }