int mm_mmap(mm_context *ctx, void *addr, size_t len, int prot, int flags, int fildes, off_t off, void **paddr) { struct mm_mapping *new_map; struct mm_mapping *pmap; struct mm_object *new_obj; uintptr_t start; uintptr_t end; uintptr_t round_addr; size_t round_len; /* Do some error checking */ if (fildes != -1) { /* Currently not supported */ return EINVAL; } if (len == 0) { return EINVAL; } /* Round down the start address */ round_addr = (uintptr_t)addr & ~0xfff; round_len = (uintptr_t)addr - round_addr + len; /* Now round it up */ round_len = __PAGEROUND(round_len); rwlock_wrlock(&ctx->lock); if (!addr) { /* The user doesn't care so we put it above the anon addr. The thinking * here is that if we stay high there is still room for brk/sbrk * to work. Many mallocs rely on it. */ start = (uintptr_t)ctx->anon_addr; } else { start = (uintptr_t)round_addr; } //kdebug("start = %016lx\n", start); //kdebug("len = %d(%x)\n", round_len, round_len); /* Find where the new object will fit */ if (flags & MAP_FIXED) { /* Todo: Remove existing overlapping maps */ /* This is an absolute mapping */ end = start + round_len - 1; pmap = first_mapping(ctx); while (pmap && !(end < pmap->start_addr)) { pmap = next_mapping(ctx, pmap); } } else { /* We will take the first fit above start */ uintptr_t last_end; pmap = first_mapping(ctx); last_end = start; /* Just find a place where it fits that's above start */ while (pmap && (pmap->start_addr < start)) { pmap = next_mapping(ctx, pmap); } /* Now find the first fit */ while (pmap && !((pmap->start_addr - last_end) >= round_len)) { last_end = pmap->start_addr + pmap->length; pmap = next_mapping(ctx, pmap); } start = last_end; } /* Create an mm_object */ if ((new_obj = object_new()) == NULL) { rwlock_unlock(&ctx->lock); return ENOMEM; } /* Create a new mapping */ if ((new_map = mapping_new(start, round_len, prot, -1, new_obj)) == NULL) { rwlock_unlock(&ctx->lock); return ENOMEM; } /* Stick new_map before pmap */ ctx->mapping_list.add_before(pmap, new_map); mm_check_uncommit(ctx, pmap); /* We support 3 types of mapping */ if (flags & MAP_PHYS) { /* * 1. Map some physical memory. In this case all the pages will * mapped immediately and backing will be 'none' */ new_obj->backing = none; mm_commit_phys(ctx, new_map, off); } else if (fildes >= 0) { /* * 2. Mapping a file - currently not supported */ } else if (flags & MAP_ANON) { /* * 3. Map some anonymous memory. Backing will be 'anon' */ new_obj->backing = anon; } *paddr = (void *)new_map->start_addr; cpu_tlb_flush_global(); mm_context_dump(ctx); rwlock_unlock(&ctx->lock); pagestruct_audit(); return 0; }
MappingWrapper(int inputs_) { c_mapping = mapping_new(inputs_); }
int mm_ctx_dup(mm_context *dst_ctx, mm_context *src_ctx) { /* Copy the src ctx to the dst creating mappings as we go * * Return -1 if there is a problem */ struct mm_mapping *pmap; int err; kdebug("MM_CTX_DUP core = %d\n", get_core_id()); mm_context_dump(src_ctx); mm_context_dump(dst_ctx); rwlock_wrlock(&src_ctx->lock); pmap = first_mapping(src_ctx); while (pmap) { struct mm_object *new_obj1, *new_obj2; struct mm_mapping *new_map; if (!(pmap->prot & PROT_WRITE)) { /* This map is read-only - share the existing object */ new_obj1 = pmap->object; ++new_obj1->refcnt; /* Create a new mapping */ if ((new_map = mapping_new(pmap->start_addr, pmap->length, pmap->prot, pmap->fd, new_obj1)) == NULL) { rwlock_unlock(&src_ctx->lock); return -1; } } else { /* This map is writable - make a new object */ /* Create an mm_object */ /* TODO: COW */ /* * Create 2 new objects * Point them at the existing obj * Create new map * Point each map at an obj */ if ((new_obj1 = object_new()) == NULL) { rwlock_unlock(&src_ctx->lock); return -1; } if ((new_obj2 = object_new()) == NULL) { rwlock_unlock(&src_ctx->lock); return -1; } new_obj1->chain = pmap->object; new_obj1->share_type = share_private; new_obj2->chain = pmap->object; new_obj2->share_type = share_private; //pmap->object->share_type = cow; /* Point the original map at new_obj1 */ pmap->object = new_obj1; /* Create a new mapping to point at new_obj2 */ if ((new_map = mapping_new(pmap->start_addr, pmap->length, pmap->prot, pmap->fd, new_obj2)) == NULL) { rwlock_unlock(&src_ctx->lock); return -1; } mm_change_commit(src_ctx, pmap, PM_USER); } dst_ctx->mapping_list.add_tail(new_map); mm_check_uncommit(dst_ctx, new_map); /* Go to the next parent mapping */ pmap = next_mapping(src_ctx, pmap); } cpu_tlb_flush_global(); rwlock_unlock(&src_ctx->lock); // kdebug("MM_CTX_DUP done\n"); // mm_context_dump(src_ctx); // mm_context_dump(dst_ctx); // pagestruct_audit(); return 0; }