Esempio n. 1
0
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;
}
Esempio n. 2
0
 MappingWrapper(int inputs_) {
     c_mapping = mapping_new(inputs_);
 }
Esempio n. 3
0
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;
}