Esempio n. 1
0
/* Like getReceiveSlots, this is specialised for single-cap transfer. */
static seL4_MessageInfo_t
transferCaps(seL4_MessageInfo_t info, extra_caps_t caps,
             endpoint_t *endpoint, tcb_t *receiver,
             word_t *receiveBuffer, bool_t diminish)
{
    word_t i;
    cte_t* destSlot;

    info = seL4_MessageInfo_set_extraCaps(info, 0);
    info = seL4_MessageInfo_set_capsUnwrapped(info, 0);

    if (likely(!caps.excaprefs[0] || !receiveBuffer)) {
        return info;
    }

    destSlot = getReceiveSlots(receiver, receiveBuffer);

    for (i = 0; i < seL4_MsgMaxExtraCaps && caps.excaprefs[i] != NULL; i++) {
        cte_t *slot = caps.excaprefs[i];
        cap_t cap = slot->cap;

        if (cap_get_capType(cap) == cap_endpoint_cap &&
                EP_PTR(cap_endpoint_cap_get_capEPPtr(cap)) == endpoint) {
            /* If this is a cap to the endpoint on which the message was sent,
             * only transfer the badge, not the cap. */
            setExtraBadge(receiveBuffer,
                          cap_endpoint_cap_get_capEPBadge(cap), i);

            info = seL4_MessageInfo_set_capsUnwrapped(info,
                                                      seL4_MessageInfo_get_capsUnwrapped(info) | (1 << i));

        } else {
            deriveCap_ret_t dc_ret;

            if (!destSlot) {
                break;
            }

            if (diminish) {
                dc_ret = deriveCap(slot, maskCapRights(noWrite, cap));
            } else {
                dc_ret = deriveCap(slot, cap);
            }

            if (dc_ret.status != EXCEPTION_NONE) {
                break;
            }
            if (cap_get_capType(dc_ret.cap) == cap_null_cap) {
                break;
            }

            cteInsert(dc_ret.cap, slot, destSlot);

            destSlot = NULL;
        }
    }

    return seL4_MessageInfo_set_extraCaps(info, i);
}
Esempio n. 2
0
bool
srv_check_dispatch_caps(srv_msg_t *m, seL4_Word unwrappedMask, int numExtraCaps)
{
    assert(m);
    if (seL4_MessageInfo_get_capsUnwrapped(m->message) != unwrappedMask ||
            seL4_MessageInfo_get_extraCaps(m->message) != numExtraCaps) {
        return false;
    }
    return true;
}
Esempio n. 3
0
File: rpc.c Progetto: seL4/refos
ENDPT
rpc_sv_pop_cptr(void *cl)
{
    rpc_client_state_t* c = (rpc_client_state_t*)cl;
    if (_rpc_cp >= seL4_MessageInfo_get_extraCaps(c->minfo)) { 
        return 0;
    }
    seL4_Word unw = seL4_MessageInfo_get_capsUnwrapped(c->minfo);
    if (unw & (1 << _rpc_cp)) {
        return seL4_CapData_Badge_get_Badge(seL4_GetBadge(_rpc_cp++));
    }
    _rpc_cp++;
    assert(_rpc_recv_cslot);
    return _rpc_recv_cslot;
}
Esempio n. 4
0
File: swap.c Progetto: 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;
}