예제 #1
0
파일: cspace.c 프로젝트: BwRy/sel4test
static int
ipc_caller(seL4_Word ep0, seL4_Word ep1, seL4_Word word_bits, seL4_Word arg4)
{
    /* Let our parent know we are ready. */
    seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 1);
    seL4_SetMR(0, READY_MAGIC);
    seL4_Send(ep0, tag);
    /*
     * The parent has changed our cspace on us. Check that it makes sense.
     *
     * Basically the entire cspace should be empty except for the cap at ep0.
     * We should still test that various points in the cspace resolve correctly.
     */

    /* Check that none of the typical endpoints are valid. */
    for (unsigned long i = 0; i < word_bits; i++) {
        seL4_MessageInfo_ptr_new(&tag, 0, 0, 0, 0);
        tag = seL4_Call(i, tag);
        test_assert(seL4_MessageInfo_get_label(tag) == seL4_InvalidCapability);
    }

    /* Check that changing one bit still gives an invalid cap. */
    for (unsigned long i = 0; i < word_bits; i++) {
        seL4_MessageInfo_ptr_new(&tag, 0, 0, 0, 0);
        tag = seL4_Call(ep1 ^ BIT(i), tag);
        test_assert(seL4_MessageInfo_get_label(tag) == seL4_InvalidCapability);
    }

    /* And we're done. This should be a valid cap and get us out of here! */
    seL4_MessageInfo_ptr_new(&tag, 0, 0, 0, 1);
    seL4_SetMR(0, SUCCESS_MAGIC);
    seL4_Send(ep1, tag);

    return sel4test_get_result();
}
예제 #2
0
int /*? me.interface.name ?*/__run(void) {
    seL4_Word fault_type;
    seL4_Word length;
    seL4_MessageInfo_t info;
    seL4_Word args[4];
    seL4_Word reply_cap = /*? reply_cap_slot ?*/;
    while (1) {
        /* Wait for fault */
        info = seL4_Recv(/*? ep ?*/, &gdb_state.current_thread_tcb);
        /* Get the relevant registers */
        fault_type = seL4_MessageInfo_get_label(info);
        length = seL4_MessageInfo_get_length(info);
        for (int i = 0; i < length; i++) {
            args[i] = seL4_GetMR(i);
        }
        gdb_state.current_pc = args[0];
        ZF_LOGD("------------------------------");
        ZF_LOGD("Received fault for tcb %zu", gdb_state.current_thread_tcb);
        ZF_LOGD("Stopped at %zx", gdb_state.current_pc);
        ZF_LOGD("Length: %zu", length);
        // Save the reply cap
        seL4_CNode_SaveCaller(/*? cnode ?*/, reply_cap, 32);

        gdb_state.stop_reason = find_stop_reason(fault_type, args);
        gdb_state.current_thread_step_mode = false;

        /* Send fault message to gdb client */
        gdb_handle_fault(&gdb_state);

        /* Wait for gdb client to deal with fault */
        int UNUSED error = b_wait();

        /* Reply to the fault ep to restart the thread.
           We look inside the gdb_state struct to interpret how to restart the thread.
         */
        if (gdb_state.stop_reason == stop_step && gdb_state.current_thread_step_mode==false) {
            /* If this was a Debug Exception, then we respond with
               a bp_num and the number of instruction to step
               Since we're going to continue, we set MR0 to 0
             */
            info = seL4_MessageInfo_new(0, 0, 0, 1);
            seL4_SetMR(0, 0);
            seL4_Send(reply_cap, info);
        } else if (gdb_state.stop_reason == stop_none) {
            /* If this was a fault, set the instruction pointer to
               what we expect it to be
             */
            info = seL4_MessageInfo_new(0, 0, 0, 1);
            seL4_SetMR(0, gdb_state.current_pc);
            seL4_Send(reply_cap, info);
        } else {
            ZF_LOGD("Responding to some other debug exception %d", gdb_state.stop_reason);
            seL4_Signal(reply_cap);
        }

    }
    UNREACHABLE();
}
예제 #3
0
/* IRQ handler thread. Wait on a notification object for IRQs. When one arrives, send a
 * synchronous message to the registered endpoint. If no synchronous endpoint was
 * registered, call the appropriate handler function directly (must be thread safe) */
static void
_irq_thread_entry(struct irq_server_thread* st)
{
    seL4_CPtr sep;
    seL4_CPtr notification;
    uintptr_t node_ptr;
    seL4_Word label;

    sep = st->delivery_sep;
    notification = st->node->notification;
    node_ptr = (uintptr_t)st->node;
    label = st->label;
    DIRQSERVER("thread started. Waiting on endpoint %d\n", notification);

    while (1) {
        seL4_Word badge;
        seL4_Wait(notification, &badge);
        assert(badge != 0);
        if (sep != seL4_CapNull) {
            /* Synchronous endpoint registered. Send IPC */
            seL4_MessageInfo_t info = seL4_MessageInfo_new(label, 0, 0, 2);
            seL4_SetMR(0, badge);
            seL4_SetMR(1, node_ptr);
            seL4_Send(sep, info);
        } else {
            /* No synchronous endpoint. Call the handler directly */
            irq_server_node_handle_irq(st->node, badge);
        }
    }
}
예제 #4
0
파일: main.c 프로젝트: BwRy/sel4test
/* override abort, called by exit (and assert fail) */
void
abort(void)
{
    /* send back a failure */
    seL4_MessageInfo_t info = seL4_MessageInfo_new(seL4_NoFault, 0, 0, 1);
    seL4_SetMR(0, -1);
    seL4_Send(endpoint, info);

    /* we should not get here */
    assert(0);
    while (1);
}
예제 #5
0
파일: rpc.c 프로젝트: seL4/refos
void
rpc_sv_reply(void* cl)
{
    if (rpc_sv_skip_reply(cl)) return;
    seL4_CPtr reply_endpoint = rpc_sv_get_reply_endpoint(cl);
    seL4_MessageInfo_t reply = seL4_MessageInfo_new(0, 0, _rpc_cp, _rpc_mr);
    if (reply_endpoint) {
        seL4_Send(reply_endpoint, reply);
    } else {
        seL4_Reply(reply);
    }
}
예제 #6
0
파일: scheduler.c 프로젝트: BwRy/sel4test
/*
 * Test threads at all possible priorities, and that they get scheduled in the
 * correct order.
 */
static int
prio_test_func(seL4_Word my_prio, seL4_Word* last_prio, seL4_CPtr ep)
{
    test_check(*last_prio - 1 == my_prio);

    *last_prio = my_prio;

    /* Unsuspend the top thread if we are the last one. */
    if (my_prio == MIN_PRIO) {
        seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 0);
        seL4_Send(ep, tag);
    }
    return 0;
}
예제 #7
0
파일: ipc.c 프로젝트: seL4/camkes-tool
void ffiseL4_Send(unsigned char *c, long clen, unsigned char *a, long alen) {
    seL4_CPtr ep;
    int offset = 1;
    memcpy(&ep, a + offset, sizeof(ep));
    offset += sizeof(ep);
    seL4_Word len;
    memcpy(&len, a + offset, sizeof(len));
    offset += sizeof(len);
    memcpy(&seL4_GetIPCBuffer()->msg[0], a + offset, len);
    seL4_Send(
        ep,
        seL4_MessageInfo_new(0, 0, 0, ROUND_UP_UNSAFE(len, sizeof(seL4_Word)) / sizeof(seL4_Word)));
    a[0] = FFI_SUCCESS;
}
예제 #8
0
/* map the init data into the process, and send the address via ipc */
static void *
send_init_data(env_t env, seL4_CPtr endpoint, sel4utils_process_t *process)
{
    /* map the cap into remote vspace */
    void *remote_vaddr = vspace_map_pages(&process->vspace, &env->init_frame_cap_copy, NULL, seL4_AllRights, 1, PAGE_BITS_4K, 1);
    assert(remote_vaddr != 0);

    /* now send a message telling the process what address the data is at */
    seL4_MessageInfo_t info = seL4_MessageInfo_new(seL4_NoFault, 0, 0, 1);
    seL4_SetMR(0, (seL4_Word) remote_vaddr);
    seL4_Send(endpoint, info);

    return remote_vaddr;
}
예제 #9
0
파일: swap.c 프로젝트: ahixon/papaya
/* avoids the need for sync primitives */
int
mmap_swap (int direction, vaddr_t vaddr, struct frameinfo* frame,
	void* callback, struct pawpaw_event* evt) {

	seL4_MessageInfo_t msg = seL4_MessageInfo_new (0, 0, 0, 6);

	seL4_SetMR (0, MMAP_REQUEST);
	seL4_SetMR (1, direction);
	seL4_SetMR (2, vaddr);
	seL4_SetMR (3, (seL4_Word)frame);
	seL4_SetMR (4, (seL4_Word)callback);
	seL4_SetMR (5, (seL4_Word)evt);

	/* note: cannot be a Call since svc_mmap might require the root server
	 * to be free to handle some of its own requests, eg sbrk */
	seL4_Send (_mmap_ep, msg);

	return true;
}
예제 #10
0
파일: vm.c 프로젝트: gapry/AOS
static void
_sos_VMFaultHandler_reply(void* token, int err){
    dprintf(3, "sos_vmf_reply called\n");

    VMF_cont_t *cont= (VMF_cont_t*)token;
    if(err){
        dprintf(3, "sos_vmf received an err\n");
    }
    if (!is_proc_alive(cont->pid)) {
        cspace_free_slot(cur_cspace, cont->reply_cap);
        free(cont);
        return;
    }

    /* Flush the i-cache. Ideally, this should only be done when faulting on text segment */
    //if (cont->is_code) {
    if (!err) {
        seL4_Word vpage = PAGE_ALIGN(cont->vaddr);
        int x = PT_L1_INDEX(vpage);
        int y = PT_L2_INDEX(vpage);

        seL4_Word kvaddr = (cont->as->as_pd_regs[x][y] & PTE_KVADDR_MASK);
        seL4_CPtr kframe_cap;

        err = frame_get_cap(kvaddr, &kframe_cap);
        //assert(!err); // This kvaddr is ready to use, there should be no error
        seL4_ARM_Page_Unify_Instruction(kframe_cap, 0, PAGESIZE);
    }
    //}
    /* If there is an err here, it is not the process's fault
     * It is either the kernel running out of memory or swapping doesn't work
     */
    seL4_MessageInfo_t reply = seL4_MessageInfo_new(0, 0, 0, 0);
    seL4_Send(cont->reply_cap, reply);
    cspace_free_slot(cur_cspace, cont->reply_cap);
    free(cont);
    set_cur_proc(PROC_NULL);
}
예제 #11
0
파일: scheduler.c 프로젝트: BwRy/sel4test
static int
ipc_test_helper_3(ipc_test_data_t *data)
{
    seL4_MessageInfo_t tag;
    int last_spins, last_bounces, result = 0;

    /* This test starts here. */

    /* TEST PART 1 */
    /* Perform a send to a thread 1. It is not yet waiting. */
    CHECK_STEP(ipc_test_step, 0);
    seL4_MessageInfo_ptr_new(&tag, 0, 0, 0, 20);
    for (int i = 0; i < seL4_MessageInfo_get_length(tag); i++) {
        seL4_SetMR(i, i);
    }
    last_spins = data->spins;
    last_bounces = data->bounces;
    seL4_Send(data->ep1, tag);
    /* We block, causing thread 2 to spin for a while, before it calls the
     * bouncer thread 0, which finally lets thread 1 run and reply to us. */
    CHECK_STEP(ipc_test_step, 2);
    CHECK_TESTCASE(result, data->spins - last_spins == 1);
    CHECK_TESTCASE(result, data->bounces - last_bounces == 0);

    /* Now bounce ourselves, to ensure that thread 1 can check its stuff. */
    seL4_MessageInfo_ptr_set_length(&tag, 0);
    seL4_Call(data->ep0, tag);

    /* Two bounces - us and thread 1. */
    CHECK_TESTCASE(result, data->spins - last_spins == 2);
    CHECK_TESTCASE(result, data->bounces - last_bounces == 2);
    CHECK_STEP(ipc_test_step, 4);

    /* TEST PART 2 */
    /* Perform a send to a thread 1, which is already waiting. */
    /* Bounce first to let thread prepare. */
    last_spins = data->spins;
    last_bounces = data->bounces;

    seL4_MessageInfo_ptr_set_length(&tag, 0);
    seL4_Call(data->ep0, tag);
    CHECK_STEP(ipc_test_step, 6);

    /* Do the send. */
    seL4_MessageInfo_ptr_set_length(&tag, 19);
    for (int i = 0; i < seL4_MessageInfo_get_length(tag); i++) {
        seL4_SetMR(i, i);
    }
    seL4_Send(data->ep1, tag);

    CHECK_STEP(ipc_test_step, 7);

    /* Bounce to let thread 1 check again. */
    seL4_MessageInfo_ptr_set_length(&tag, 0);
    seL4_Call(data->ep0, tag);

    CHECK_STEP(ipc_test_step, 9);

    /* Five bounces in total. */
    CHECK_TESTCASE(result, data->spins - last_spins == 2);
    CHECK_TESTCASE(result, data->bounces - last_bounces == 5);

    return result;
}
예제 #12
0
파일: main.c 프로젝트: BwRy/sel4test
int
main(int argc, char **argv)
{

    test_init_data_t *init_data;
    struct env env;

    assert(argc >= 2);
    /* in order to have some shitty almost-fork-like semantics
     * main can get run multiple times. Look in src/helpers.c
     * for where this is used. Just means we check the first
     * arg, and if not NULL jmp to it */
    void (*helper_thread)(int argc,char **argv) = (void(*)(int, char**))atol(argv[1]);
    if (helper_thread) {
        helper_thread(argc, argv);
    }

    /* parse args */
    assert(argc == 3);
    endpoint = (seL4_CPtr) atoi(argv[2]);

    /* read in init data */
    init_data = receive_init_data(endpoint);

    /* configure env */
    env.cspace_root = init_data->root_cnode;
    env.page_directory = init_data->page_directory;
    env.endpoint = endpoint;
    env.priority = init_data->priority;
    env.cspace_size_bits = init_data->cspace_size_bits;
    env.tcb = init_data->tcb;
    env.domain = init_data->domain;
#ifndef CONFIG_KERNEL_STABLE
    env.asid_pool = init_data->asid_pool;
    env.asid_ctrl = init_data->asid_ctrl;
#endif /* CONFIG_KERNEL_STABLE */
#ifdef CONFIG_IOMMU
    env.io_space = init_data->io_space;
#endif
    env.num_regions = init_data->num_elf_regions;
    memcpy(env.regions, init_data->elf_regions, sizeof(sel4utils_elf_region_t) * env.num_regions);

    /* initialse cspace, vspace and untyped memory allocation */
    init_allocator(&env, init_data);

    /* initialise the timer */
    init_timer(&env, init_data);

    /* find the test */
    testcase_t *test = find_test(init_data->name);

    /* run the test */
    int result = 0;
    if (test) {
        printf("Running test %s (%s)\n", test->name, test->description);
        result = test->function(&env);
    } else {
        result = FAILURE;
        ZF_LOGF("Cannot find test %s\n", init_data->name);
    }

    printf("Test %s %s\n", init_data->name, result == SUCCESS ? "passed" : "failed");
    /* send our result back */
    seL4_MessageInfo_t info = seL4_MessageInfo_new(seL4_NoFault, 0, 0, 1);
    seL4_SetMR(0, result);
    seL4_Send(endpoint, info);

    /* It is expected that we are torn down by the test driver before we are
     * scheduled to run again after signalling them with the above send.
     */
    assert(!"unreachable");
    return 0;
}
예제 #13
0
파일: swap.c 프로젝트: ahixon/papaya
/* sends off a frame to the relevant swap file (in or out) 
 *
 * returns True if the root server needs to be notified immediately (ie not 
 * waiting for an async reply */
static int
mmap_queue_schedule (int direction, vaddr_t vaddr, struct frameinfo *frame,
	void* callback, struct pawpaw_event* evt) {

	struct mmap_queue_item* q = mmap_queue_new (frame, callback, evt);
	if (!q) {
		return false;
	}

	//assert (frame);

	if (direction == PAGE_SWAP_IN) {
		assert (frame->file);
		assert (frame->file->file);

		/* FIXME: seriously this needs work */
		struct seen_item *item = regd_caps;
		while (item) {
			if (item->cap == frame->file->file) {
			   break;
			}

		   item = item->next;
		}

		/* register with the filesystem for async notifications if this is our
		 * first time with this file */
		if (!item) {
			seL4_MessageInfo_t reg_msg = seL4_MessageInfo_new (0, 0, 1, 1);

			seL4_CPtr their_cap = cspace_mint_cap (cur_cspace, cur_cspace,
				_mmap_ep, seL4_AllRights,
				seL4_CapData_Badge_new ((seL4_Word)frame));

			assert (their_cap);

			seL4_SetMR (0, VFS_REGISTER_CAP);
			seL4_SetCap (0, their_cap);

			seL4_Call (frame->file->file, reg_msg);

			seL4_Word id = seL4_GetMR (0);
			assert (id > 0);

			item = malloc (sizeof (struct seen_item));
			assert (item);
			item->cap = frame->file->file;
			item->id = id;

			item->next = regd_caps;
			regd_caps = item;
		}

		seL4_MessageInfo_t msg = seL4_MessageInfo_new (0, 0, 1, 4);

		seL4_Word id = cid_next ();
		maps_append (id, ((thread_t)evt->args[1])->pid, vaddr);

		/* create a "valid badge" in the badgemap so we can mount the
	 	 * shared buffer */
		seL4_CPtr badge_cap = cspace_mint_cap (
			cur_cspace, cur_cspace, _badgemap_ep, seL4_AllRights,
			seL4_CapData_Badge_new (id));

		assert (badge_cap);
		assert (frame->file);

		msg = seL4_MessageInfo_new (0, 0, 1, 7);
		seL4_SetCap (0, badge_cap);
		seL4_SetMR (0, VFS_READ_OFFSET);
		seL4_SetMR (1, id);
		seL4_SetMR (2, frame->file->load_length);
		seL4_SetMR (3, frame->file->file_offset);
		seL4_SetMR (4, frame->file->load_offset);
		seL4_SetMR (5, item->id);	/* async ID */
		seL4_SetMR (6, (seL4_Word)frame);	/* use frame ptr as "event id" */

		seL4_Send (frame->file->file, msg);

		/* and we go back to waiting on our EP */
	} else if (direction == PAGE_SWAP_OUT) {
		seL4_MessageInfo_t msg = seL4_MessageInfo_new (0, 0, 1, 4);

		/* FIXME: needs to be cleaned up on successful swap */
		seL4_Word id = cid_next ();
		maps_append (id, 0, vaddr);

		/* create a "valid badge" in the badgemap so we can mount the shared 
		 * buffer */
		seL4_CPtr badge_cap = cspace_mint_cap (cur_cspace, cur_cspace,
			_badgemap_ep, seL4_AllRights, seL4_CapData_Badge_new (id));

		assert (badge_cap);

		seL4_Word page_id = last_page_id * PAGE_SIZE;
		last_page_id++;

		seL4_Word wrote = 0;
		while (wrote < PAGE_SIZE) {
			msg = seL4_MessageInfo_new (0, 0, 1, 7);
			seL4_SetCap (0, badge_cap);
			seL4_SetMR (0, VFS_WRITE_OFFSET);
			seL4_SetMR (1, id);
			seL4_SetMR (2, PAGE_SIZE - wrote);	/* write whole page out */
			seL4_SetMR (3, page_id + wrote);	/* file offset */
			seL4_SetMR (4, wrote);				/* load into start of share */
			//seL4_SetMR (5, swap_id);			/* async ID - NOT USED */
			seL4_SetMR (6, (seL4_Word)frame);

			/* and write it out */
			seL4_Call (swap_cap, msg);
			seL4_Word wrote_this_call = seL4_GetMR (0);
			assert (wrote_this_call >= 0);
			wrote += wrote_this_call;
		}

		cspace_delete_cap (cur_cspace, badge_cap);

		/* memory map it */
		frame->file = frame_create_mmap (swap_cap, 0, page_id, PAGE_SIZE);
		assert (frame->file);

		mmap_move_done (q);
		return true;
		/* and we go back to waiting on our EP */
	} else if (direction == BUFFER_OPEN_LOAD) {
		seL4_Word share_id = cid_next ();
		maps_append (share_id, 0, vaddr);

		/* create a "valid badge" in the badgemap so we can mount the shared 
		 * buffer */
		seL4_CPtr badge_cap = cspace_mint_cap (cur_cspace, cur_cspace,
			_badgemap_ep, seL4_AllRights, seL4_CapData_Badge_new (share_id));

		assert (badge_cap);

	    seL4_CPtr recv_cap = cspace_alloc_slot (cur_cspace);
	    assert (recv_cap);
	    seL4_SetCapReceivePath (cur_cspace->root_cnode, recv_cap, CSPACE_DEPTH);

	    printf ("OK, asking VFS to open our file '%s'\n", (char*)vaddr);

	    seL4_MessageInfo_t msg = seL4_MessageInfo_new (0, 0, 1, 4);
	    seL4_SetCap (0, badge_cap);
	    seL4_SetMR (0, VFS_OPEN);
	    seL4_SetMR (1, share_id);
	    seL4_SetMR (2, FM_READ);
	    seL4_SetMR (3, 0);

	    /* XXX: hack of the century - should really ask VFS async
	     * for cap */
	    seL4_CPtr nfs_fs_cap = service_lookup ("fs_nfs");
	    while (!nfs_fs_cap) {
	    	printf ("failed to find nfs service\n");
	    	nfs_fs_cap = service_lookup ("fs_nfs");
	        //return false;
	    }

	    printf ("calling on %d\n", nfs_fs_cap);
	    seL4_MessageInfo_t reply = seL4_Call (nfs_fs_cap, msg);

	    if (seL4_GetMR (0) != 0) {
	        printf ("%s: failed to open file\n", __FUNCTION__);
	        //return false;
	        mmap_move_done (q);
	        q->frame = NULL;
	    	return true;
	    }

	    assert (seL4_MessageInfo_get_capsUnwrapped (reply) == 0);

	    if (seL4_MessageInfo_get_extraCaps (reply) != 1) {
	        /* could not find file */
	        printf ("%s: did not have cap\n", __FUNCTION__);
	        return false;
	    }

	   	printf ("yum, setting evt arg\n");
	    evt->args[2] = recv_cap;

	    /* then, load in the first page worth of the file into kmem, so we
	     * can read the headers we need */

	    printf ("sweeto, trying to read in data...\n");
	    msg = seL4_MessageInfo_new (0, 0, 1, 3);
	    seL4_SetCap (0, badge_cap);
	    seL4_SetMR (0, VFS_READ);
	    seL4_SetMR (1, share_id);
	    seL4_SetMR (2, PAGE_SIZE);
	    //seL4_SetMR (3, 0);  /* offset */

	    printf ("ASKING TO READ FILE\n");
	    seL4_Call (recv_cap, msg);
	    if (seL4_GetMR (0) <= 0) {
	        printf ("%s: read was empty/failed\n", __FUNCTION__);
	        //return NULL;
	        return false;
	    }

	    printf("read was ok\n");

	    mmap_move_done (q);
	    return true;
	}

	return false;
}
예제 #14
0
파일: vm.c 프로젝트: gapry/AOS
void
sos_VMFaultHandler(seL4_CPtr reply_cap, seL4_Word fault_addr, seL4_Word fsr, bool is_code){
    dprintf(3, "sos vmfault handler \n");

    int err;

    dprintf(3, "sos vmfault handler, getting as \n");
    addrspace_t *as = proc_getas();
    dprintf(3, "sos vmfault handler, gotten as \n");
    if (as == NULL) {
        dprintf(3, "app as is NULL\n");
        /* Kernel is probably failed when bootstraping */
        set_cur_proc(PROC_NULL);
        cspace_free_slot(cur_cspace, reply_cap);
        return;
    }

    region_t *reg;

    /* Is this a segfault? */
    if (_check_segfault(as, fault_addr, fsr, &reg)) {
        dprintf(3, "vmf: segfault\n");
        proc_destroy(proc_get_id());
        set_cur_proc(PROC_NULL);
        cspace_free_slot(cur_cspace, reply_cap);
        return;
    }

    /*
     * If it comes here, this must be a valid address Therefore, this page is
     * either swapped out has never been mapped in
     */

    VMF_cont_t *cont = malloc(sizeof(VMF_cont_t));
    if (cont == NULL) {
        dprintf(3, "vmfault out of mem\n");
        /* We cannot handle the fault but the process still can run
         * There will be more faults coming though */
        set_cur_proc(PROC_NULL);
        seL4_MessageInfo_t reply = seL4_MessageInfo_new(0, 0, 0, 0);
        seL4_Send(reply_cap, reply);
        cspace_free_slot(cur_cspace, reply_cap);
        return;
    }

    cont->reply_cap = reply_cap;
    cont->as        = as;
    cont->vaddr     = fault_addr;
    cont->is_code   = is_code;
    cont->reg       = reg;
    cont->pid       = proc_get_id();

    /* Check if this page is an new, unmaped page or is it just swapped out */
    if (sos_page_is_inuse(as, fault_addr)) {
        if (sos_page_is_swapped(as, fault_addr)) {
            dprintf(3, "vmf tries to swapin\n");
            /* This page is swapped out, we need to swap it back in */
            err = swap_in(cont->as, cont->reg->rights, cont->vaddr,
                      cont->is_code, _sos_VMFaultHandler_reply, cont);
            if (err) {
                _sos_VMFaultHandler_reply((void*)cont, err);
                return;
            }
            return;
        } else {
            if (sos_page_is_locked(as, fault_addr)) {
                dprintf(3, "vmf page is locked\n");
                _sos_VMFaultHandler_reply((void*)cont, EFAULT);
                return;
            }

            dprintf(3, "vmf second chance mapping page back in\n");
            err = _set_page_reference(cont->as, cont->vaddr, cont->reg->rights);
            _sos_VMFaultHandler_reply((void*)cont, err);
            return;
        }
    } else {
        /* This page has never been mapped, so do that and return */
        dprintf(3, "vmf tries to map a page\n");
        inc_proc_size_proc(cur_proc());
        err = sos_page_map(proc_get_id(), as, fault_addr, reg->rights, _sos_VMFaultHandler_reply, (void*)cont, false);
        if(err){
            dec_proc_size_proc(cur_proc());
            _sos_VMFaultHandler_reply((void*)cont, err);
        }
        return;
    }
    /* Otherwise, this is not handled */
    dprintf(3, "vmf error at the end\n");
    _sos_VMFaultHandler_reply((void*)cont, EFAULT);
    return;
}