Esempio n. 1
0
void uv_inject(page_desc_t      *pd,
		page_desc_t      *pdbegin,
		page_desc_t      *pdend,
		unsigned long    pages,
		unsigned long    addr,
		unsigned long    addrend,
		unsigned int     pagesize,
		unsigned long    mattr,
		unsigned long    nodeid,
		unsigned long    paddr,
		char             *pte_str,
		unsigned long    nodeid_start,
		unsigned long    mattr_start,
		unsigned long    addr_start,
		int              mce_opt)
{
        int count = 0;
	eid.cpu = sched_getcpu();

        for (pd=pdbegin, pdend=pd+pages; pd<pdend && addr < addrend; pd++, addr += pagesize) {
		if (pd->flags & PD_HOLE) {
			pagesize = pd->pte;
			mattr = 0;
			nodeid = -1;
		} else {
			nodeid = get_pnodeid(*pd);
			paddr = get_paddr(*pd);
			if (nodeid == INVALID_NODE)
				nodeid = 0;

			mattr = get_memory_attr(*pd);
			pagesize = get_pagesize(*pd);
			if (mattr && paddr) {
				if ((pd_total / 2) == count){
				sprintf(pte_str, "  0x%016lx  ", pd->pte);
				printf("\t[%012lx] -> 0x%012lx on %s %3s  %s%s\n",
						addr, paddr, idstr(), nodestr(nodeid),
						pte_str, get_memory_attr_str(nodeid, mattr));
				/* Setting value at memory location  for recovery
 				 * before injecting.
 				 */
        			memset((void *)addr, 'A', pagesize);
				injecteddata = (char *)addr;
				printf("Data:%x\n",*injecteddata);
				eid.addr = paddr;
				eid.cpu = nodeid;
				break;//only allow once for now
				}
			}
		}
		count++;
	} 
	if (delay){
		printf("Enter char to inject..");
		getchar();
	}	
	if(!manual){
		inject_uc(eid.addr, 0 /*int notrigger*/);
	}
}
Esempio n. 2
0
static void cross_as_copy(
    ulong src_page_dir_pfn, ulong src_start, ulong length,
    ulong dest_page_dir_pfn, ulong dest_start)
{
    ulong i;
    
    ulong src_end = src_start + length;
    
    // Round down src start and dest start
    src_start /= sizeof(ulong);
    src_start *= sizeof(ulong);
    
    dest_start /= sizeof(ulong);
    dest_start *= sizeof(ulong);
    
    // Round up src end
    if (src_end % sizeof(ulong)) {
        src_end /= sizeof(ulong);
        src_end++;
        src_end *= sizeof(ulong);
    }
    
    // Calculate actual length
    length = src_end - src_start;
    
    // Do the actual copy
    ulong cur_src_paddr, cur_dest_paddr;
    for (i = 0; i < length; i += sizeof(ulong)) {
        // Get physical address
        cur_src_paddr = get_paddr(src_page_dir_pfn, src_start + i);
        cur_dest_paddr = get_paddr(dest_page_dir_pfn, dest_start + i);
        assert(cur_src_paddr && cur_dest_paddr);
        
        // Copy the value
        ulong word = *((ulong *)cur_src_paddr);
        *((ulong *)cur_dest_paddr) = word;
        
        //kprintf("%h ", word);
    }
}
Esempio n. 3
0
static int ioctl_codec_process(struct drm_device *dev, void *data,
		struct drm_file *file)
{
	struct dce_file_priv *priv = omap_drm_file_priv(file, dce_mapper_id);
	struct drm_omap_dce_codec_process *arg = data;
	struct dce_rpc_codec_process_rsp *rsp;
	int ret, i;

	/* if we are not re-starting a syscall, send req */
	if (!arg->token) {
		/* worst-case size allocation.. */
		struct dce_rpc_codec_process_req *req = kzalloc(RPMSG_BUF_SIZE, GFP_KERNEL);
		void *ptr = &req->data[0];
		void *end = ((void *)req) + RPMSG_BUF_SIZE;
		int32_t input_id = 0;

		req->hdr = MKHDR(CODEC_PROCESS);

		ret = codec_get(priv, arg->codec_handle, &req->codec, &req->codec_id);
		if (ret)
			goto rpsend_out;

		ret = PTR_RET(get_paddr(priv, hdr(&req), &req->out_args, arg->out_args_bo));
		if (ret)
			return rpabort(hdr(req), ret);

		/* the remainder of the req varies depending on codec family */
		switch (req->codec_id) {
		case OMAP_DCE_VIDENC2:
			ret = handle_videnc2(priv, &ptr, end, &input_id, req, arg);
			break;
		case OMAP_DCE_VIDDEC3:
			ret = handle_viddec3(priv, &ptr, end, &input_id, req, arg);
			break;
		default:
			ret = -EINVAL;
			break;
		}

		if (ret)
			goto rpsend_out;

		ret = rpsend(priv, &arg->token, hdr(req), ptr - (void *)req);
rpsend_out:
		kfree(req);
		if (ret) {
			/* if input buffer is already locked, unlock it now so we
			 * don't have a leak:
			 */
			if (input_id)
				codec_unlockbuf(priv, arg->codec_handle, input_id);
			return rpabort(hdr(req), ret);
		}
	}

	/* then wait for reply, which is interruptible */
	ret = rpwait(priv, arg->token, hdr(&rsp), sizeof(*rsp));
	if (ret)
		return ret;

	for (i = 0; i < rsp->count; i++) {
		codec_unlockbuf(priv, arg->codec_handle, rsp->freebuf_ids[i]);
	}

	arg->result = rsp->result;

	kfree(rsp);

	return 0;
}
Esempio n. 4
0
static int ioctl_codec_create(struct drm_device *dev, void *data,
		struct drm_file *file)
{
	struct dce_file_priv *priv = omap_drm_file_priv(file, dce_mapper_id);
	struct drm_omap_dce_codec_create *arg = data;
	struct dce_rpc_codec_create_rsp *rsp;
	int ret;

	/* if we are not re-starting a syscall, send req */
	if (!arg->token) {
		struct dce_rpc_codec_create_req req = {
				.hdr = MKHDR(CODEC_CREATE),
				.codec_id = arg->codec_id,
		};

		strncpy(req.name, arg->name, sizeof(req.name));

		ret = engine_get(priv, arg->eng_handle, &req.engine);
		if (ret)
			return ret;

		ret = PTR_RET(get_paddr(priv, hdr(&req), &req.sparams, arg->sparams_bo));
		if (ret)
			goto rpsend_out;

		ret = rpsend(priv, &arg->token, hdr(&req), sizeof(req));
rpsend_out:
		if (ret)
			return rpabort(hdr(&req), ret);
	}

	/* then wait for reply, which is interruptible */
	ret = rpwait(priv, arg->token, hdr(&rsp), sizeof(*rsp));
	if (ret)
		return ret;

	arg->codec_handle = codec_register(priv, rsp->codec, arg->codec_id);

	if (!codec_valid(priv, arg->codec_handle)) {
		codec_delete(priv, rsp->codec, arg->codec_id);
		ret = -ENOMEM;
	}

	kfree(rsp);

	return ret;
}

static int ioctl_codec_control(struct drm_device *dev, void *data,
		struct drm_file *file)
{
	struct dce_file_priv *priv = omap_drm_file_priv(file, dce_mapper_id);
	struct drm_omap_dce_codec_control *arg = data;
	struct dce_rpc_codec_control_rsp *rsp;
	int ret;

	/* if we are not re-starting a syscall, send req */
	if (!arg->token) {
		struct dce_rpc_codec_control_req req = {
				.hdr = MKHDR(CODEC_CONTROL),
				.cmd_id = arg->cmd_id,
		};

		ret = codec_get(priv, arg->codec_handle, &req.codec, &req.codec_id);
		if (ret)
			return ret;

		ret = PTR_RET(get_paddr(priv, hdr(&req), &req.dparams, arg->dparams_bo));
		if (ret)
			goto rpsend_out;

		ret = PTR_RET(get_paddr(priv, hdr(&req), &req.status, arg->status_bo));
		if (ret)
			goto rpsend_out;

		ret = rpsend(priv, &arg->token, hdr(&req), sizeof(req));
rpsend_out:
		if (ret)
			return rpabort(hdr(&req), ret);
	}

	/* then wait for reply, which is interruptible */
	ret = rpwait(priv, arg->token, hdr(&rsp), sizeof(*rsp));
	if (ret)
		return ret;

	arg->result = rsp->result;

	kfree(rsp);

	return 0;
}

struct viddec3_in_args {
	int32_t size;		/* struct size */
	int32_t num_bytes;
	int32_t input_id;
};
struct videnc2_in_args {
	int32_t size;
	int32_t input_id;
	int32_t control;
};

union xdm2_buf_size {
    struct {
        int32_t width;
        int32_t height;
    } tiled;
    int32_t bytes;
};
struct xdm2_single_buf_desc {
    uint32_t buf;
    int16_t  mem_type;	/* XXX should be XDM_MEMTYPE_BO */
    int16_t  usage_mode;
    union xdm2_buf_size buf_size;
    int32_t  accessMask;
};
struct xdm2_buf_desc {
    int32_t num_bufs;
    struct xdm2_single_buf_desc descs[16];
};

struct video2_buf_desc {
    int32_t num_planes;
    int32_t num_meta_planes;
    int32_t data_layout;
    struct xdm2_single_buf_desc plane_desc[3];
    struct xdm2_single_buf_desc metadata_plane_desc[3];
    /* rest of the struct isn't interesting to kernel.. if you are
     * curious look at IVIDEO2_BufDesc in ivideo.h in codec-engine
     */
    uint32_t data[30];
};
#define XDM_MEMTYPE_RAW       0
#define XDM_MEMTYPE_TILED8    1
#define XDM_MEMTYPE_TILED16   2
#define XDM_MEMTYPE_TILED32   3
#define XDM_MEMTYPE_TILEDPAGE 4

/* copy_from_user helper that also checks to avoid overrunning
 * the 'to' buffer and advances dst ptr
 */
static inline int cfu(void **top, uint64_t from, int n, void *end)
{
	void *to = *top;
	int ret;
	if ((to + n) >= end) {
		DBG("dst buffer overflow!");
		return -EFAULT;
	}
	ret = copy_from_user(to, (char __user *)(uintptr_t)from, n);
	*top = to + n;
	return ret;
}

static inline struct drm_gem_object * handle_single_buf_desc(
		struct dce_file_priv *priv, struct dce_rpc_hdr *req,
		uint32_t base_bo, struct xdm2_single_buf_desc *desc)
{
	struct drm_gem_object *obj;
	uint32_t flags;
	int32_t offset;

	/* maybe support remapping user ptrs later on.. */
	if (desc->mem_type != XDM_MEMTYPE_BO &&
			desc->mem_type != XDM_MEMTYPE_BO_OFFSET)
		return ERR_PTR(-EINVAL);

	if (desc->mem_type == XDM_MEMTYPE_BO_OFFSET) {
		/* desc->buf is an offset to base_bo, which is descs[0].buf as
		 * passed to _process */
		offset = desc->buf;
		desc->buf = base_bo;
	} else {
		offset = -1;
	}

	obj = get_paddr(priv, req, &desc->buf, desc->buf);
	if (IS_ERR(obj))
		return obj;

	if (offset != -1)
		desc->buf += offset;

	flags = omap_gem_flags(obj);
	switch(flags & OMAP_BO_TILED) {
	case OMAP_BO_TILED_8:
		desc->mem_type = XDM_MEMTYPE_TILED8;
		break;
	case OMAP_BO_TILED_16:
		desc->mem_type = XDM_MEMTYPE_TILED16;
		break;
	case OMAP_BO_TILED_32:
		desc->mem_type = XDM_MEMTYPE_TILED32;
		break;
	default:
		// XXX this is where it gets a bit messy..  some codecs
		// might want to see XDM_MEMTYPE_RAW for bitstream buffers
		desc->mem_type = XDM_MEMTYPE_TILEDPAGE;
		break;
	}

	if (flags & OMAP_BO_TILED) {
		uint16_t w, h;
		omap_gem_tiled_size(obj, &w, &h);
		desc->buf_size.tiled.width = w;
		desc->buf_size.tiled.height = h;
	}

	// XXX not sure if the codecs care about usage_mode.. but we
	// know if the buffer is cached or not so we could set DATASYNC
	// bit if needed..

	return obj;
}

static inline int handle_buf_desc(struct dce_file_priv *priv,
		void **ptr, void *end, struct dce_rpc_hdr *req, uint64_t usr,
		struct drm_gem_object **o1, struct drm_gem_object **o2, uint8_t *len)
{
	struct xdm2_buf_desc *bufs = *ptr;
	uint32_t base_bo;
	int i, ret;

	/* read num_bufs field: */
	ret = cfu(ptr, usr, 4, end);
	if (ret)
		return ret;

	/* read rest of structure: */
	ret = cfu(ptr, usr+4, bufs->num_bufs * sizeof(bufs->descs[0]), end);
	if (ret)
		return ret;

	*len = (4 + bufs->num_bufs * sizeof(bufs->descs[0])) / 4;

	/* the bo used as a base for XDM_MEMTYPE_BO_OFFSET descriptors */
	base_bo = bufs->descs[0].buf;

	/* handle buffer mapping.. */
	for (i = 0; i < bufs->num_bufs; i++) {
		struct drm_gem_object *obj =
				handle_single_buf_desc(priv, req, base_bo,
						&bufs->descs[i]);
		if (IS_ERR(obj)) {
			return PTR_ERR(obj);
		}

		if (i == 0)
			*o1 = obj;
		if (o2 && (i == 1))
			*o2 = obj;

	}

	return 0;
}

/*
 *   VIDDEC3_process			VIDENC2_process
 *   VIDDEC3_InArgs *inArgs		VIDENC2_InArgs *inArgs
 *   XDM2_BufDesc *outBufs		XDM2_BufDesc *outBufs
 *   XDM2_BufDesc *inBufs		VIDEO2_BufDesc *inBufs
 */

static inline int handle_videnc2(struct dce_file_priv *priv,
		void **ptr, void *end, int32_t *input_id,
		struct dce_rpc_codec_process_req *req,
		struct drm_omap_dce_codec_process *arg)
{
	WARN_ON(1); // XXX not implemented
	//	codec_lockbuf(priv, arg->codec_handle, in_args->input_id, y, uv);
	return -EFAULT;
}