static int compat_drm_addbufs(struct file *file, unsigned int cmd, unsigned long arg) { drm_buf_desc32_t __user *argp = (void __user *)arg; struct drm_buf_desc __user *buf; int err; unsigned long agp_start; buf = compat_alloc_user_space(sizeof(*buf)); if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)) || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))) return -EFAULT; if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start)) || __get_user(agp_start, &argp->agp_start) || __put_user(agp_start, &buf->agp_start)) return -EFAULT; err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf); if (err) return err; if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start)) || __get_user(agp_start, &buf->agp_start) || __put_user(agp_start, &argp->agp_start)) return -EFAULT; return 0; }
/** * Called whenever a 32-bit process running under a 64-bit kernel * performs an ioctl on /dev/dri/card<n>. * * \param filp file pointer. * \param cmd command. * \param arg user argument. * \return zero on success or negative number on failure. */ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); drm_ioctl_compat_t *fn = NULL; struct drm_file *file_priv = filp->private_data; struct drm_device *dev = file_priv->minor->dev; int ret; i915_rpm_get_ioctl(dev); if (nr < DRM_COMMAND_BASE) { ret = drm_compat_ioctl(filp, cmd, arg); goto out; } if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls)) fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE]; if (fn != NULL) ret = (*fn) (filp, cmd, arg); else ret = drm_ioctl(filp, cmd, arg); out: i915_rpm_put_ioctl(dev); return ret; }
static int compat_drm_getunique(struct file *file, unsigned int cmd, unsigned long arg) { drm_unique32_t uq32; struct drm_unique __user *u; int err; if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32))) return -EFAULT; u = compat_alloc_user_space(sizeof(*u)); if (!access_ok(VERIFY_WRITE, u, sizeof(*u))) return -EFAULT; if (__put_user(uq32.unique_len, &u->unique_len) || __put_user((void __user *)(unsigned long)uq32.unique, &u->unique)) return -EFAULT; err = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u); if (err) return err; if (__get_user(uq32.unique_len, &u->unique_len)) return -EFAULT; if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32))) return -EFAULT; return 0; }
static int compat_r128_depth(struct file *file, unsigned int cmd, unsigned long arg) { drm_r128_depth32_t depth32; drm_r128_depth_t __user *depth; if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32))) return -EFAULT; depth = compat_alloc_user_space(sizeof(*depth)); if (!access_ok(VERIFY_WRITE, depth, sizeof(*depth)) || __put_user(depth32.func, &depth->func) || __put_user(depth32.n, &depth->n) || __put_user((int __user *)(unsigned long)depth32.x, &depth->x) || __put_user((int __user *)(unsigned long)depth32.y, &depth->y) || __put_user((unsigned int __user *)(unsigned long)depth32.buffer, &depth->buffer) || __put_user((unsigned char __user *)(unsigned long)depth32.mask, &depth->mask)) return -EFAULT; return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_R128_DEPTH, (unsigned long)depth); }
static int compat_i915_batchbuffer(struct file *file, unsigned int cmd, unsigned long arg) { drm_i915_batchbuffer32_t batchbuffer32; drm_i915_batchbuffer_t __user *batchbuffer; if (copy_from_user (&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32))) return -EFAULT; batchbuffer = compat_alloc_user_space(sizeof(*batchbuffer)); if (!access_ok(VERIFY_WRITE, batchbuffer, sizeof(*batchbuffer)) || __put_user(batchbuffer32.start, &batchbuffer->start) || __put_user(batchbuffer32.used, &batchbuffer->used) || __put_user(batchbuffer32.DR1, &batchbuffer->DR1) || __put_user(batchbuffer32.DR4, &batchbuffer->DR4) || __put_user(batchbuffer32.num_cliprects, &batchbuffer->num_cliprects) || __put_user((int __user *)(unsigned long)batchbuffer32.cliprects, &batchbuffer->cliprects)) return -EFAULT; return drm_ioctl(file, DRM_IOCTL_I915_BATCHBUFFER, (unsigned long)batchbuffer); }
static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd, unsigned long arg) { drm_i915_cmdbuffer32_t cmdbuffer32; drm_i915_cmdbuffer_t __user *cmdbuffer; if (copy_from_user (&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32))) return -EFAULT; cmdbuffer = compat_alloc_user_space(sizeof(*cmdbuffer)); if (!access_ok(VERIFY_WRITE, cmdbuffer, sizeof(*cmdbuffer)) || __put_user((int __user *)(unsigned long)cmdbuffer32.buf, &cmdbuffer->buf) || __put_user(cmdbuffer32.sz, &cmdbuffer->sz) || __put_user(cmdbuffer32.DR1, &cmdbuffer->DR1) || __put_user(cmdbuffer32.DR4, &cmdbuffer->DR4) || __put_user(cmdbuffer32.num_cliprects, &cmdbuffer->num_cliprects) || __put_user((int __user *)(unsigned long)cmdbuffer32.cliprects, &cmdbuffer->cliprects)) return -EFAULT; return drm_ioctl(file, DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer); }
static int compat_drm_getclient(struct file *file, unsigned int cmd, unsigned long arg) { drm_client32_t c32; drm_client32_t __user *argp = (void __user *)arg; struct drm_client __user *client; int idx, err; if (get_user(idx, &argp->idx)) return -EFAULT; client = compat_alloc_user_space(sizeof(*client)); if (!access_ok(VERIFY_WRITE, client, sizeof(*client))) return -EFAULT; if (__put_user(idx, &client->idx)) return -EFAULT; err = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, (unsigned long)client); if (err) return err; if (__get_user(c32.auth, &client->auth) || __get_user(c32.pid, &client->pid) || __get_user(c32.uid, &client->uid) || __get_user(c32.magic, &client->magic) || __get_user(c32.iocs, &client->iocs)) return -EFAULT; if (copy_to_user(argp, &c32, sizeof(c32))) return -EFAULT; return 0; }
static int compat_drm_getstats(struct file *file, unsigned int cmd, unsigned long arg) { drm_stats32_t s32; drm_stats32_t __user *argp = (void __user *)arg; struct drm_stats __user *stats; int i, err; stats = compat_alloc_user_space(sizeof(*stats)); if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats))) return -EFAULT; err = drm_ioctl(file, DRM_IOCTL_GET_STATS, (unsigned long)stats); if (err) return err; if (__get_user(s32.count, &stats->count)) return -EFAULT; for (i = 0; i < 15; ++i) if (__get_user(s32.data[i].value, &stats->data[i].value) || __get_user(s32.data[i].type, &stats->data[i].type)) return -EFAULT; if (copy_to_user(argp, &s32, sizeof(s32))) return -EFAULT; return 0; }
/* This works around a bug in X servers prior to 1.18.4, which sometimes * submit more dirty rectangles than the kernel is willing to handle and * then disable dirty rectangle handling altogether when they see the * EINVAL error. I do not want the code to hang around forever, which is * why I am limiting it to certain kernel versions. We can increase the * limit if some distributions uses old X servers with new kernels. */ long vbox_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { long rc = drm_ioctl(filp, cmd, arg); if (cmd == DRM_IOCTL_MODE_DIRTYFB && rc == -EINVAL) return -EOVERFLOW; return rc; }
int iris_reg_read(struct iris_bufmgr *bufmgr, uint32_t offset, uint64_t *result) { struct drm_i915_reg_read reg_read = { .offset = offset }; int ret = drm_ioctl(bufmgr->fd, DRM_IOCTL_I915_REG_READ, ®_read); *result = reg_read.val; return ret; }
void iris_destroy_hw_context(struct iris_bufmgr *bufmgr, uint32_t ctx_id) { struct drm_i915_gem_context_destroy d = { .ctx_id = ctx_id }; if (ctx_id != 0 && drm_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &d) != 0) { fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n", strerror(errno)); } }
uint32_t iris_create_hw_context(struct iris_bufmgr *bufmgr) { struct drm_i915_gem_context_create create = { }; int ret = drm_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create); if (ret != 0) { DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n", strerror(errno)); return 0; } return create.ctx_id; }
long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); int ret; if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); ret = drm_ioctl(filp, cmd, arg); return ret; }
static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, unsigned long arg) { drm_mga_dma_bootstrap32_t dma_bootstrap32; drm_mga_dma_bootstrap_t __user *dma_bootstrap; int err; if (copy_from_user(&dma_bootstrap32, (void __user *)arg, sizeof(dma_bootstrap32))) return -EFAULT; dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap)); if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap)) || __put_user(dma_bootstrap32.texture_handle, &dma_bootstrap->texture_handle) || __put_user(dma_bootstrap32.texture_size, &dma_bootstrap->texture_size) || __put_user(dma_bootstrap32.primary_size, &dma_bootstrap->primary_size) || __put_user(dma_bootstrap32.secondary_bin_count, &dma_bootstrap->secondary_bin_count) || __put_user(dma_bootstrap32.secondary_bin_size, &dma_bootstrap->secondary_bin_size) || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode) || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size)) return -EFAULT; err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MGA_DMA_BOOTSTRAP, (unsigned long)dma_bootstrap); if (err) return err; if (__get_user(dma_bootstrap32.texture_handle, &dma_bootstrap->texture_handle) || __get_user(dma_bootstrap32.texture_size, &dma_bootstrap->texture_size) || __get_user(dma_bootstrap32.primary_size, &dma_bootstrap->primary_size) || __get_user(dma_bootstrap32.secondary_bin_count, &dma_bootstrap->secondary_bin_count) || __get_user(dma_bootstrap32.secondary_bin_size, &dma_bootstrap->secondary_bin_size) || __get_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode) || __get_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size)) return -EFAULT; if (copy_to_user((void __user *)arg, &dma_bootstrap32, sizeof(dma_bootstrap32))) return -EFAULT; return 0; }
static int compat_drm_infobufs(struct file *file, unsigned int cmd, unsigned long arg) { drm_buf_info32_t req32; drm_buf_info32_t __user *argp = (void __user *)arg; drm_buf_desc32_t __user *to; drm_buf_info_t __user *request; drm_buf_desc_t __user *list; size_t nbytes; int i, err; int count, actual; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; count = req32.count; to = (drm_buf_desc32_t __user *) (unsigned long)req32.list; if (count < 0) count = 0; if (count > 0 && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t))) return -EFAULT; nbytes = sizeof(*request) + count * sizeof(drm_buf_desc_t); request = compat_alloc_user_space(nbytes); if (!access_ok(VERIFY_WRITE, request, nbytes)) return -EFAULT; list = (drm_buf_desc_t *) (request + 1); if (__put_user(count, &request->count) || __put_user(list, &request->list)) return -EFAULT; err = drm_ioctl(file->f_dentry->d_inode, file, DRM_IOCTL_INFO_BUFS, (unsigned long)request); if (err) return err; if (__get_user(actual, &request->count)) return -EFAULT; if (count >= actual) for (i = 0; i < actual; ++i) if (__copy_in_user(&to[i], &list[i], offsetof(drm_buf_desc_t, flags))) return -EFAULT; if (__put_user(actual, &argp->count)) return -EFAULT; return 0; }
static uint64_t iris_gtt_size(int fd) { /* We use the default (already allocated) context to determine * the default configuration of the virtual address space. */ struct drm_i915_gem_context_param p = { .param = I915_CONTEXT_PARAM_GTT_SIZE, }; if (!drm_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &p)) return p.value; return 0; }
long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); int ret; if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); lock_kernel(); /* XXX for now */ ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; }
/** * Called whenever a 32-bit process running under a 64-bit kernel * performs an ioctl on /dev/dri/card<n>. * * \param filp file pointer. * \param cmd command. * \param arg user argument. * \return zero on success or negative number on failure. */ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); int ret; if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); if (nr < DRM_COMMAND_BASE + ARRAY_SIZE(i915_compat_ioctls) && i915_compat_ioctls[nr - DRM_COMMAND_BASE]) ret = (*i915_compat_ioctls[nr - DRM_COMMAND_BASE])(filp, cmd, arg); else ret = drm_ioctl(filp, cmd, arg); return ret; }
/** * Called whenever a 32-bit process running under a 64-bit kernel * performs an ioctl on /dev/dri/card<n>. * * \param filp file pointer. * \param cmd command. * \param arg user argument. * \return zero on success or negative number on failure. */ long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); int ret; if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls)) { drm_ioctl_compat_t fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE]; ret = (*fn) (filp, cmd, arg); } else ret = drm_ioctl(filp, cmd, arg); return ret; }
static int exit_drm(void) { int err; // stop being master err = drm_ioctl(filp, DRM_IOCTL_DROP_MASTER, 0); if(err) { printk(KERN_ERR "drmtest: error in drm_ioctl, DRM_IOCTL_DROP_MASTER (%d)", err); return err; } // default memory model set_fs(old_fs); // close device filp_close(filp, (void *)0); return 0; }
static int compat_mga_init(struct file *file, unsigned int cmd, unsigned long arg) { drm_mga_init32_t init32; drm_mga_init_t __user *init; int err = 0, i; if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) return -EFAULT; init = compat_alloc_user_space(sizeof(*init)); if (!access_ok(VERIFY_WRITE, init, sizeof(*init)) || __put_user(init32.func, &init->func) || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset) || __put_user(init32.chipset, &init->chipset) || __put_user(init32.sgram, &init->sgram) || __put_user(init32.maccess, &init->maccess) || __put_user(init32.fb_cpp, &init->fb_cpp) || __put_user(init32.front_offset, &init->front_offset) || __put_user(init32.front_pitch, &init->front_pitch) || __put_user(init32.back_offset, &init->back_offset) || __put_user(init32.back_pitch, &init->back_pitch) || __put_user(init32.depth_cpp, &init->depth_cpp) || __put_user(init32.depth_offset, &init->depth_offset) || __put_user(init32.depth_pitch, &init->depth_pitch) || __put_user(init32.fb_offset, &init->fb_offset) || __put_user(init32.mmio_offset, &init->mmio_offset) || __put_user(init32.status_offset, &init->status_offset) || __put_user(init32.warp_offset, &init->warp_offset) || __put_user(init32.primary_offset, &init->primary_offset) || __put_user(init32.buffers_offset, &init->buffers_offset)) return -EFAULT; for (i = 0; i < MGA_NR_TEX_HEAPS; i++) { err |= __put_user(init32.texture_offset[i], &init->texture_offset[i]); err |= __put_user(init32.texture_size[i], &init->texture_size[i]); } if (err) return -EFAULT; return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MGA_INIT, (unsigned long)init); }
static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, unsigned long arg) { drm_radeon_irq_emit32_t req32; drm_radeon_irq_emit_t __user *request; if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) return -EFAULT; request = compat_alloc_user_space(sizeof(*request)); if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) || __put_user((int __user *)(unsigned long)req32.irq_seq, &request->irq_seq)) return -EFAULT; return drm_ioctl(file, DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); }
static int compat_r128_stipple(struct file *file, unsigned int cmd, unsigned long arg) { drm_r128_stipple32_t stipple32; drm_r128_stipple_t __user *stipple; if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32))) return -EFAULT; stipple = compat_alloc_user_space(sizeof(*stipple)); if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple)) || __put_user((unsigned int __user *)(unsigned long)stipple32.mask, &stipple->mask)) return -EFAULT; return drm_ioctl(file->f_dentry->d_inode, file, DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple); }
static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, unsigned long arg) { drm_radeon_stipple32_t __user *argp = (void __user *)arg; drm_radeon_stipple_t __user *request; u32 mask; if (get_user(mask, &argp->mask)) return -EFAULT; request = compat_alloc_user_space(sizeof(*request)); if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) || __put_user((unsigned int __user *)(unsigned long)mask, &request->mask)) return -EFAULT; return drm_ioctl(file, DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); }
static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd, unsigned long arg) { drm_radeon_setparam32_t req32; drm_radeon_setparam_t __user *request; if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) return -EFAULT; request = compat_alloc_user_space(sizeof(*request)); if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) || __put_user(req32.param, &request->param) || __put_user((void __user *)(unsigned long)req32.value, &request->value)) return -EFAULT; return drm_ioctl(file, DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request); }
static int compat_drm_rmmap(struct file *file, unsigned int cmd, unsigned long arg) { drm_map32_t __user *argp = (void __user *)arg; struct drm_map __user *map; u32 handle; if (get_user(handle, &argp->handle)) return -EFAULT; map = compat_alloc_user_space(sizeof(*map)); if (!access_ok(VERIFY_WRITE, map, sizeof(*map))) return -EFAULT; if (__put_user((void *)(unsigned long)handle, &map->handle)) return -EFAULT; return drm_ioctl(file, DRM_IOCTL_RM_MAP, (unsigned long)map); }
int iris_hw_context_set_priority(struct iris_bufmgr *bufmgr, uint32_t ctx_id, int priority) { struct drm_i915_gem_context_param p = { .ctx_id = ctx_id, .param = I915_CONTEXT_PARAM_PRIORITY, .value = priority, }; int err; err = 0; if (drm_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &p)) err = -errno; return err; }
static int compat_r128_getparam(struct file *file, unsigned int cmd, unsigned long arg) { drm_r128_getparam32_t getparam32; drm_r128_getparam_t __user *getparam; if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32))) return -EFAULT; getparam = compat_alloc_user_space(sizeof(*getparam)); if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam)) || __put_user(getparam32.param, &getparam->param) || __put_user((void __user *)(unsigned long)getparam32.value, &getparam->value)) return -EFAULT; return drm_ioctl(file->f_dentry->d_inode, file, DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam); }
long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); drm_ioctl_compat_t *fn = NULL; int ret; if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls)) fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE]; if (fn != NULL) ret = (*fn) (filp, cmd, arg); else ret = drm_ioctl(filp, cmd, arg); return ret; }
static int compat_drm_setunique(struct file *file, unsigned int cmd, unsigned long arg) { drm_unique32_t uq32; struct drm_unique __user *u; if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32))) return -EFAULT; u = compat_alloc_user_space(sizeof(*u)); if (!u) return -EFAULT; if (__put_user(uq32.unique_len, &u->unique_len) || __put_user((void __user *)(unsigned long)uq32.unique, &u->unique)) return -EFAULT; return drm_ioctl(file, DRM_IOCTL_SET_UNIQUE, (unsigned long)u); }