Example #1
0
int
shmem_transport_xpmem_fini(void)
{
    int i, peer_num;

    if (NULL != shmem_transport_xpmem_peers) {
        for (i = 0 ; i < shmem_internal_num_pes; ++i) {
            peer_num = SHMEM_GET_RANK_SAME_NODE(i);
            if (-1 == peer_num) continue;
            if (shmem_internal_my_pe == i) continue;

            if (NULL != shmem_transport_xpmem_peers[peer_num].data_ptr) {
                xpmem_detach(shmem_transport_xpmem_peers[peer_num].data_attach_ptr);
            }
                
            if (0 != shmem_transport_xpmem_peers[peer_num].data_apid) {
                xpmem_release(shmem_transport_xpmem_peers[peer_num].data_apid);
            }
                
            if (NULL != shmem_transport_xpmem_peers[peer_num].heap_ptr) {
                xpmem_detach(shmem_transport_xpmem_peers[peer_num].heap_attach_ptr);
            }
                
            if (0 != shmem_transport_xpmem_peers[peer_num].heap_apid) {
                xpmem_release(shmem_transport_xpmem_peers[peer_num].heap_apid);
            }
        }
        free(shmem_transport_xpmem_peers);
    } 

    if (0 != my_info.data_seg) {
        xpmem_remove(my_info.data_seg);
    }
    if (0 != my_info.heap_seg) {
        xpmem_remove(my_info.heap_seg);
    }

    return 0;
}
Example #2
0
static ucs_status_t uct_xpmem_dereg(uct_mm_id_t mmid)
{
    int ret;

    ret = xpmem_remove(mmid);
    if (ret < 0) {
        /* No error since there a chance that it already was released
         * or deregistered */
        ucs_debug("Failed to remove xpmem segment 0x%"PRIx64": %m", mmid);
    }

    ucs_trace("xpmem removed segment 0x%"PRIx64, mmid);
    return UCS_OK;
}
Example #3
0
/*
 * Get permission to access a specified segid.
 */
int
xpmem_get(xpmem_segid_t segid, int flags, int permit_type, void *permit_value,
      xpmem_apid_t *apid_p)
{
    xpmem_apid_t apid       = 0;
    int          status     = 0;
    int          shadow_seg = 0;

    struct xpmem_segment *seg = NULL;
    struct xpmem_thread_group *ap_tg, *seg_tg;

    if (segid <= 0)
        return -EINVAL;

    if ((flags & ~(XPMEM_RDONLY | XPMEM_RDWR)) ||
        (flags & (XPMEM_RDONLY | XPMEM_RDWR)) ==
        (XPMEM_RDONLY | XPMEM_RDWR))
        return -EINVAL;

    switch (permit_type) {
	case XPMEM_PERMIT_MODE:
	case XPMEM_GLOBAL_MODE:
	    if (permit_value != NULL)
		return -EINVAL;

	    break;
	default:
	    return -EINVAL;
    }

    /* There are 2 cases that result in a remote lookup:
     * (1) The thread group encoded in the segment does not exist locally.
     *	
     * (2) The thread group exists locally, but the segment does not. The
     * ids for thread groups are not globally unique, so it's possible that
     * the same thread group id exists in two separate enclaves, but only
     * one will own the segment
     */

    seg_tg = xpmem_tg_ref_by_segid(segid);
    if (IS_ERR(seg_tg)) {
	seg_tg = xpmem_tg_ref_by_gid(current->aspace->id);
	if (IS_ERR(seg_tg))
	    return PTR_ERR(seg_tg);

	shadow_seg = 1;
    }

    if (!shadow_seg) {
	seg = xpmem_seg_ref_by_segid(seg_tg, segid);
	if (IS_ERR(seg))
	    shadow_seg = 1;
    }

    if (shadow_seg) {
        /* No local segment found. Look for a remote one */
	/* NOTE: in either case, the tg has already been ref'd. We ref the 
	 * current process' tg if no tg is found for the segid
	 */
        status = xpmem_try_get_remote(seg_tg, segid, flags, permit_type, 
		permit_value);
	if (status != 0) {
	    xpmem_tg_deref(seg_tg);
	    return status;
        }

	/* Now, get the shadow segment */
	seg = xpmem_seg_ref_by_segid(seg_tg, segid);
	if (IS_ERR(seg)) {
	    /* Error should be impossible here, but we'll
	     * check anyway. The shadow segment was created in
	     * xpmem_try_get_remote, so destroy it here */
	    xpmem_remove(segid);
	    xpmem_tg_deref(seg_tg);
	    return PTR_ERR(seg);
	}
    }

    /* find accessor's thread group structure */
    ap_tg = xpmem_tg_ref_by_gid(current->aspace->id);
    if (IS_ERR(ap_tg)) {
        BUG_ON(PTR_ERR(ap_tg) != -ENOENT);
	status = -XPMEM_ERRNO_NOPROC;
	goto err_ap_tg;
    }

    apid = xpmem_make_apid(ap_tg);
    if (apid < 0) {
	status = apid;
	goto err_apid;
    }

    status = xpmem_get_segment(flags, permit_type, permit_value, apid, 
	seg, seg_tg, ap_tg);

    if (status != 0)
	goto err_get;

    *apid_p = apid;
    xpmem_tg_deref(ap_tg);

    /*
     * The following two derefs
     *
     *      xpmem_seg_deref(seg);
     *      xpmem_tg_deref(seg_tg);
     *
     * aren't being done at this time in order to prevent the seg
     * and seg_tg structures from being prematurely kmem_free'd as long as the
     * potential for them to be referenced via this ap structure exists.
     *
     * These two derefs will be done by xpmem_release_ap() at the time
     * this ap structure is destroyed.
     */

    return status;

err_get:
err_apid:
    xpmem_tg_deref(ap_tg); 

err_ap_tg:
    /* If we created a shadow segment, destroy it on error. Else, just 
     * deref it
     */
    if (shadow_seg)
	xpmem_remove(segid);
    else
	xpmem_seg_deref(seg);
    xpmem_tg_deref(seg_tg);

    return status;
}
Example #4
0
/*
 * User ioctl to the XPMEM driver. Only 64-bit user applications are
 * supported.
 */
static long
xpmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	long ret;

	switch (cmd) {
	case XPMEM_CMD_VERSION: {
		return XPMEM_CURRENT_VERSION;
	}
	case XPMEM_CMD_MAKE: {
		struct xpmem_cmd_make make_info;
		xpmem_segid_t segid;

		if (copy_from_user(&make_info, (void __user *)arg,
				   sizeof(struct xpmem_cmd_make)))
			return -EFAULT;

		ret = xpmem_make(make_info.vaddr, make_info.size,
				 make_info.permit_type,
				 (void *)make_info.permit_value, &segid);
		if (ret != 0)
			return ret;

		if (put_user(segid,
			     &((struct xpmem_cmd_make __user *)arg)->segid)) {
			(void)xpmem_remove(segid);
			return -EFAULT;
		}
		return 0;
	}
	case XPMEM_CMD_REMOVE: {
		struct xpmem_cmd_remove remove_info;

		if (copy_from_user(&remove_info, (void __user *)arg,
				   sizeof(struct xpmem_cmd_remove)))
			return -EFAULT;

		return xpmem_remove(remove_info.segid);
	}
	case XPMEM_CMD_GET: {
		struct xpmem_cmd_get get_info;
		xpmem_apid_t apid;

		if (copy_from_user(&get_info, (void __user *)arg,
				   sizeof(struct xpmem_cmd_get)))
			return -EFAULT;

		ret = xpmem_get(get_info.segid, get_info.flags,
				get_info.permit_type,
				(void *)get_info.permit_value, &apid);
		if (ret != 0)
			return ret;

		if (put_user(apid,
			     &((struct xpmem_cmd_get __user *)arg)->apid)) {
			(void)xpmem_release(apid);
			return -EFAULT;
		}
		return 0;
	}
	case XPMEM_CMD_RELEASE: {
		struct xpmem_cmd_release release_info;

		if (copy_from_user(&release_info, (void __user *)arg,
				   sizeof(struct xpmem_cmd_release)))
			return -EFAULT;

		return xpmem_release(release_info.apid);
	}
	case XPMEM_CMD_ATTACH: {
		struct xpmem_cmd_attach attach_info;
		u64 at_vaddr;

		if (copy_from_user(&attach_info, (void __user *)arg,
				   sizeof(struct xpmem_cmd_attach)))
			return -EFAULT;

		ret = xpmem_attach(file, attach_info.apid, attach_info.offset,
				   attach_info.size, attach_info.vaddr,
				   attach_info.fd, attach_info.flags,
				   &at_vaddr);
		if (ret != 0)
			return ret;

		if (put_user(at_vaddr,
			     &((struct xpmem_cmd_attach __user *)arg)->vaddr)) {
			(void)xpmem_detach(at_vaddr);
			return -EFAULT;
		}
		return 0;
	}
	case XPMEM_CMD_DETACH: {
		struct xpmem_cmd_detach detach_info;

		if (copy_from_user(&detach_info, (void __user *)arg,
				   sizeof(struct xpmem_cmd_detach)))
			return -EFAULT;

		return xpmem_detach(detach_info.vaddr);
	}
	case XPMEM_CMD_FORK_BEGIN: {
		return xpmem_fork_begin();
	}
	case XPMEM_CMD_FORK_END: {
		return xpmem_fork_end();
	}
	default:
		break;
	}
	return -ENOIOCTLCMD;
}