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*/); } }
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); } }
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; }
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; }