diff options
-rw-r--r-- | drivers/gpu/drm/drm_bufs.c | 116 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_internal.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_ioc32.c | 750 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_ioctl.c | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_legacy.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/mga/mga_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/mga/mga_ioc32.c | 149 | ||||
-rw-r--r-- | drivers/gpu/drm/mga/mga_state.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ioc32.c | 424 | ||||
-rw-r--r-- | include/drm/drm_ioctl.h | 1 |
12 files changed, 476 insertions, 1045 deletions
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index adb1dd7fde5f..1ee84dd802d4 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -1258,11 +1258,11 @@ int drm_legacy_addbufs(struct drm_device *dev, void *data, * lock, preventing of allocating more buffers after this call. Information * about each requested buffer is then copied into user space. */ -int drm_legacy_infobufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int __drm_legacy_infobufs(struct drm_device *dev, + void *data, int *p, + int (*f)(void *, int, struct drm_buf_entry *)) { struct drm_device_dma *dma = dev->dma; - struct drm_buf_info *request = data; int i; int count; @@ -1290,26 +1290,12 @@ int drm_legacy_infobufs(struct drm_device *dev, void *data, DRM_DEBUG("count = %d\n", count); - if (request->count >= count) { + if (*p >= count) { for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) { - if (dma->bufs[i].buf_count) { - struct drm_buf_desc __user *to = - &request->list[count]; - struct drm_buf_entry *from = &dma->bufs[i]; - if (copy_to_user(&to->count, - &from->buf_count, - sizeof(from->buf_count)) || - copy_to_user(&to->size, - &from->buf_size, - sizeof(from->buf_size)) || - copy_to_user(&to->low_mark, - &from->low_mark, - sizeof(from->low_mark)) || - copy_to_user(&to->high_mark, - &from->high_mark, - sizeof(from->high_mark))) + struct drm_buf_entry *from = &dma->bufs[i]; + if (from->buf_count) { + if (f(data, count, from) < 0) return -EFAULT; - DRM_DEBUG("%d %d %d %d %d\n", i, dma->bufs[i].buf_count, @@ -1320,11 +1306,29 @@ int drm_legacy_infobufs(struct drm_device *dev, void *data, } } } - request->count = count; + *p = count; return 0; } +static int copy_one_buf(void *data, int count, struct drm_buf_entry *from) +{ + struct drm_buf_info *request = data; + struct drm_buf_desc __user *to = &request->list[count]; + struct drm_buf_desc v = {.count = from->buf_count, + .size = from->buf_size, + .low_mark = from->low_mark, + .high_mark = from->high_mark}; + return copy_to_user(to, &v, offsetof(struct drm_buf_desc, flags)); +} + +int drm_legacy_infobufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_buf_info *request = data; + return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf); +} + /** * Specifies a low and high water mark for buffer allocation * @@ -1439,15 +1443,15 @@ int drm_legacy_freebufs(struct drm_device *dev, void *data, * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls * drm_mmap_dma(). */ -int drm_legacy_mapbufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int __drm_legacy_mapbufs(struct drm_device *dev, void *data, int *p, + void __user **v, + int (*f)(void *, int, unsigned long, + struct drm_buf *), + struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; int retcode = 0; - const int zero = 0; unsigned long virtual; - unsigned long address; - struct drm_buf_map *request = data; int i; if (!drm_core_check_feature(dev, DRIVER_LEGACY)) @@ -1467,7 +1471,7 @@ int drm_legacy_mapbufs(struct drm_device *dev, void *data, dev->buf_use++; /* Can't allocate more after this call */ spin_unlock(&dev->buf_lock); - if (request->count >= dma->buf_count) { + if (*p >= dma->buf_count) { if ((dev->agp && (dma->flags & _DRM_DMA_USE_AGP)) || (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG))) { @@ -1492,41 +1496,51 @@ int drm_legacy_mapbufs(struct drm_device *dev, void *data, retcode = (signed long)virtual; goto done; } - request->virtual = (void __user *)virtual; + *v = (void __user *)virtual; for (i = 0; i < dma->buf_count; i++) { - if (copy_to_user(&request->list[i].idx, - &dma->buflist[i]->idx, - sizeof(request->list[0].idx))) { - retcode = -EFAULT; - goto done; - } - if (copy_to_user(&request->list[i].total, - &dma->buflist[i]->total, - sizeof(request->list[0].total))) { - retcode = -EFAULT; - goto done; - } - if (copy_to_user(&request->list[i].used, - &zero, sizeof(zero))) { - retcode = -EFAULT; - goto done; - } - address = virtual + dma->buflist[i]->offset; /* *** */ - if (copy_to_user(&request->list[i].address, - &address, sizeof(address))) { + if (f(data, i, virtual, dma->buflist[i]) < 0) { retcode = -EFAULT; goto done; } } } done: - request->count = dma->buf_count; - DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode); + *p = dma->buf_count; + DRM_DEBUG("%d buffers, retcode = %d\n", *p, retcode); return retcode; } +static int map_one_buf(void *data, int idx, unsigned long virtual, + struct drm_buf *buf) +{ + struct drm_buf_map *request = data; + unsigned long address = virtual + buf->offset; /* *** */ + + if (copy_to_user(&request->list[idx].idx, &buf->idx, + sizeof(request->list[0].idx))) + return -EFAULT; + if (copy_to_user(&request->list[idx].total, &buf->total, + sizeof(request->list[0].total))) + return -EFAULT; + if (clear_user(&request->list[idx].used, sizeof(int))) + return -EFAULT; + if (copy_to_user(&request->list[idx].address, &address, + sizeof(address))) + return -EFAULT; + return 0; +} + +int drm_legacy_mapbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_buf_map *request = data; + return __drm_legacy_mapbufs(dev, data, &request->count, + &request->virtual, map_one_buf, + file_priv); +} + int drm_legacy_dma_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 3d8e8f878924..14dfa9c83d1d 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -143,3 +143,6 @@ static inline int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc) return 0; } #endif +drm_ioctl_t drm_version; +drm_ioctl_t drm_getunique; +drm_ioctl_t drm_getclient; diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index ae386783e3ea..0b2d8c4a2fa5 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -32,6 +32,9 @@ #include <linux/export.h> #include <drm/drmP.h> +#include "drm_legacy.h" +#include "drm_internal.h" +#include "drm_crtc_internal.h" #define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t) #define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t) @@ -87,39 +90,28 @@ static int compat_drm_version(struct file *file, unsigned int cmd, unsigned long arg) { drm_version32_t v32; - struct drm_version __user *version; + struct drm_version v; int err; if (copy_from_user(&v32, (void __user *)arg, sizeof(v32))) return -EFAULT; - version = compat_alloc_user_space(sizeof(*version)); - if (!version) - return -EFAULT; - if (__put_user(v32.name_len, &version->name_len) - || __put_user((void __user *)(unsigned long)v32.name, - &version->name) - || __put_user(v32.date_len, &version->date_len) - || __put_user((void __user *)(unsigned long)v32.date, - &version->date) - || __put_user(v32.desc_len, &version->desc_len) - || __put_user((void __user *)(unsigned long)v32.desc, - &version->desc)) - return -EFAULT; - - err = drm_ioctl(file, - DRM_IOCTL_VERSION, (unsigned long)version); + v = (struct drm_version) { + .name_len = v32.name_len, + .name = compat_ptr(v32.name), + .date_len = v32.date_len, + .date = compat_ptr(v32.date), + .desc_len = v32.desc_len, + .desc = compat_ptr(v32.desc), + }; + err = drm_ioctl_kernel(file, drm_version, &v, + DRM_UNLOCKED|DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW); if (err) return err; - if (__get_user(v32.version_major, &version->version_major) - || __get_user(v32.version_minor, &version->version_minor) - || __get_user(v32.version_patchlevel, &version->version_patchlevel) - || __get_user(v32.name_len, &version->name_len) - || __get_user(v32.date_len, &version->date_len) - || __get_user(v32.desc_len, &version->desc_len)) - return -EFAULT; - + v32.version_major = v.version_major; + v32.version_minor = v.version_minor; + v32.version_patchlevel = v.version_patchlevel; if (copy_to_user((void __user *)arg, &v32, sizeof(v32))) return -EFAULT; return 0; @@ -134,26 +126,21 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, unsigned long arg) { drm_unique32_t uq32; - struct drm_unique __user *u; + struct drm_unique uq; int err; if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32))) return -EFAULT; + uq = (struct drm_unique){ + .unique_len = uq32.unique_len, + .unique = compat_ptr(uq32.unique), + }; - 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; - - err = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u); + err = drm_ioctl_kernel(file, drm_getunique, &uq, DRM_UNLOCKED); if (err) return err; - if (__get_user(uq32.unique_len, &u->unique_len)) - return -EFAULT; + uq32.unique_len = uq.unique_len; if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32))) return -EFAULT; return 0; @@ -162,21 +149,8 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, 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); + /* it's dead */ + return -EINVAL; } typedef struct drm_map32 { @@ -193,32 +167,23 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd, { drm_map32_t __user *argp = (void __user *)arg; drm_map32_t m32; - struct drm_map __user *map; - int idx, err; - void *handle; - - if (get_user(idx, &argp->offset)) - return -EFAULT; + struct drm_map map; + int err; - map = compat_alloc_user_space(sizeof(*map)); - if (!map) - return -EFAULT; - if (__put_user(idx, &map->offset)) + if (copy_from_user(&m32, argp, sizeof(m32))) return -EFAULT; - err = drm_ioctl(file, DRM_IOCTL_GET_MAP, (unsigned long)map); + map.offset = m32.offset; + err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, DRM_UNLOCKED); if (err) return err; - if (__get_user(m32.offset, &map->offset) - || __get_user(m32.size, &map->size) - || __get_user(m32.type, &map->type) - || __get_user(m32.flags, &map->flags) - || __get_user(handle, &map->handle) - || __get_user(m32.mtrr, &map->mtrr)) - return -EFAULT; - - m32.handle = (unsigned long)handle; + m32.offset = map.offset; + m32.size = map.size; + m32.type = map.type; + m32.flags = map.flags; + m32.handle = ptr_to_compat(map.handle); + m32.mtrr = map.mtrr; if (copy_to_user(argp, &m32, sizeof(m32))) return -EFAULT; return 0; @@ -230,35 +195,28 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd, { drm_map32_t __user *argp = (void __user *)arg; drm_map32_t m32; - struct drm_map __user *map; + struct drm_map map; int err; - void *handle; if (copy_from_user(&m32, argp, sizeof(m32))) return -EFAULT; - map = compat_alloc_user_space(sizeof(*map)); - if (!map) - return -EFAULT; - if (__put_user(m32.offset, &map->offset) - || __put_user(m32.size, &map->size) - || __put_user(m32.type, &map->type) - || __put_user(m32.flags, &map->flags)) - return -EFAULT; + map.offset = m32.offset; + map.size = m32.size; + map.type = m32.type; + map.flags = m32.flags; - err = drm_ioctl(file, DRM_IOCTL_ADD_MAP, (unsigned long)map); + err = drm_ioctl_kernel(file, drm_legacy_addmap_ioctl, &map, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); if (err) return err; - if (__get_user(m32.offset, &map->offset) - || __get_user(m32.mtrr, &map->mtrr) - || __get_user(handle, &map->handle)) - return -EFAULT; - - m32.handle = (unsigned long)handle; - if (m32.handle != (unsigned long)handle) + m32.offset = map.offset; + m32.mtrr = map.mtrr; + m32.handle = ptr_to_compat(map.handle); + if (map.handle != compat_ptr(m32.handle)) pr_err_ratelimited("compat_drm_addmap truncated handle %p for type %d offset %x\n", - handle, m32.type, m32.offset); + map.handle, m32.type, m32.offset); if (copy_to_user(argp, &m32, sizeof(m32))) return -EFAULT; @@ -270,19 +228,13 @@ 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; + struct drm_map map; u32 handle; if (get_user(handle, &argp->handle)) return -EFAULT; - - map = compat_alloc_user_space(sizeof(*map)); - if (!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); + map.handle = compat_ptr(handle); + return drm_ioctl_kernel(file, drm_legacy_rmmap_ioctl, &map, DRM_AUTH); } typedef struct drm_client32 { @@ -299,29 +251,24 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd, { drm_client32_t c32; drm_client32_t __user *argp = (void __user *)arg; - struct drm_client __user *client; - int idx, err; + struct drm_client client; + int err; - if (get_user(idx, &argp->idx)) + if (copy_from_user(&c32, argp, sizeof(c32))) return -EFAULT; - client = compat_alloc_user_space(sizeof(*client)); - if (!client) - return -EFAULT; - if (__put_user(idx, &client->idx)) - return -EFAULT; + client.idx = c32.idx; - err = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, (unsigned long)client); + err = drm_ioctl_kernel(file, drm_getclient, &client, DRM_UNLOCKED); if (err) return err; - if (__get_user(c32.idx, &client->idx) - || __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; + c32.idx = client.idx; + c32.auth = client.auth; + c32.pid = client.pid; + c32.uid = client.uid; + c32.magic = client.magic; + c32.iocs = client.iocs; if (copy_to_user(argp, &c32, sizeof(c32))) return -EFAULT; @@ -339,28 +286,14 @@ typedef struct drm_stats32 { 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; - - memset(&s32, 0, sizeof(drm_stats32_t)); - stats = compat_alloc_user_space(sizeof(*stats)); - if (!stats) - return -EFAULT; + int err; - err = drm_ioctl(file, DRM_IOCTL_GET_STATS, (unsigned long)stats); + err = drm_ioctl_kernel(file, drm_noop, NULL, DRM_UNLOCKED); 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))) + if (clear_user(argp, sizeof(drm_stats32_t))) return -EFAULT; return 0; } @@ -378,26 +311,28 @@ 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; + drm_buf_desc32_t desc32; + struct drm_buf_desc desc; int err; - unsigned long agp_start; - buf = compat_alloc_user_space(sizeof(*buf)); - if (!buf || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))) + if (copy_from_user(&desc32, argp, sizeof(drm_buf_desc32_t))) 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; + desc = (struct drm_buf_desc){ + desc32.count, desc32.size, desc32.low_mark, desc32.high_mark, + desc32.flags, desc32.agp_start + }; - err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf); + err = drm_ioctl_kernel(file, drm_legacy_addbufs, &desc, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 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)) + desc32 = (drm_buf_desc32_t){ + desc.count, desc.size, desc.low_mark, desc.high_mark, + desc.flags, desc.agp_start + }; + if (copy_to_user(argp, &desc32, sizeof(drm_buf_desc32_t))) return -EFAULT; return 0; @@ -408,21 +343,17 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd, { drm_buf_desc32_t b32; drm_buf_desc32_t __user *argp = (void __user *)arg; - struct drm_buf_desc __user *buf; + struct drm_buf_desc buf; if (copy_from_user(&b32, argp, sizeof(b32))) return -EFAULT; - buf = compat_alloc_user_space(sizeof(*buf)); - if (!buf) - return -EFAULT; - - if (__put_user(b32.size, &buf->size) - || __put_user(b32.low_mark, &buf->low_mark) - || __put_user(b32.high_mark, &buf->high_mark)) - return -EFAULT; + buf.size = b32.size; + buf.low_mark = b32.low_mark; + buf.high_mark = b32.high_mark; - return drm_ioctl(file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf); + return drm_ioctl_kernel(file, drm_legacy_markbufs, &buf, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } typedef struct drm_buf_info32 { @@ -430,52 +361,42 @@ typedef struct drm_buf_info32 { u32 list; } drm_buf_info32_t; +static int copy_one_buf32(void *data, int count, struct drm_buf_entry *from) +{ + drm_buf_info32_t *request = data; + drm_buf_desc32_t __user *to = compat_ptr(request->list); + drm_buf_desc32_t v = {.count = from->buf_count, + .size = from->buf_size, + .low_mark = from->low_mark, + .high_mark = from->high_mark}; + return copy_to_user(to + count, &v, offsetof(drm_buf_desc32_t, flags)); +} + +static int drm_legacy_infobufs32(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + drm_buf_info32_t *request = data; + return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf32); +} + 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; - struct drm_buf_info __user *request; - struct drm_buf_desc __user *list; - size_t nbytes; - int i, err; - int count, actual; + int err; 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(struct drm_buf_desc); - request = compat_alloc_user_space(nbytes); - if (!request) - return -EFAULT; - list = (struct drm_buf_desc *) (request + 1); - - if (__put_user(count, &request->count) - || __put_user(list, &request->list)) - return -EFAULT; + if (req32.count < 0) + req32.count = 0; - err = drm_ioctl(file, DRM_IOCTL_INFO_BUFS, (unsigned long)request); + err = drm_ioctl_kernel(file, drm_legacy_infobufs32, &req32, DRM_AUTH); 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(struct drm_buf_desc, flags))) - return -EFAULT; - - if (__put_user(actual, &argp->count)) + if (put_user(req32.count, &argp->count)) return -EFAULT; return 0; @@ -494,54 +415,52 @@ typedef struct drm_buf_map32 { u32 list; /**< Buffer information */ } drm_buf_map32_t; +static int map_one_buf32(void *data, int idx, unsigned long virtual, + struct drm_buf *buf) +{ + drm_buf_map32_t *request = data; + drm_buf_pub32_t __user *to = compat_ptr(request->list) + idx; + drm_buf_pub32_t v; + + v.idx = buf->idx; + v.total = buf->total; + v.used = 0; + v.address = virtual + buf->offset; + if (copy_to_user(to, &v, sizeof(v))) + return -EFAULT; + return 0; +} + +static int drm_legacy_mapbufs32(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + drm_buf_map32_t *request = data; + void __user *v; + int err = __drm_legacy_mapbufs(dev, data, &request->count, + &v, map_one_buf32, + file_priv); + request->virtual = ptr_to_compat(v); + return err; +} + static int compat_drm_mapbufs(struct file *file, unsigned int cmd, unsigned long arg) { drm_buf_map32_t __user *argp = (void __user *)arg; drm_buf_map32_t req32; - drm_buf_pub32_t __user *list32; - struct drm_buf_map __user *request; - struct drm_buf_pub __user *list; - int i, err; - int count, actual; - size_t nbytes; - void __user *addr; + int err; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - count = req32.count; - list32 = (void __user *)(unsigned long)req32.list; - - if (count < 0) + if (req32.count < 0) return -EINVAL; - nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub); - request = compat_alloc_user_space(nbytes); - if (!request) - return -EFAULT; - list = (struct drm_buf_pub *) (request + 1); - - if (__put_user(count, &request->count) - || __put_user(list, &request->list)) - return -EFAULT; - err = drm_ioctl(file, DRM_IOCTL_MAP_BUFS, (unsigned long)request); + err = drm_ioctl_kernel(file, drm_legacy_mapbufs32, &req32, DRM_AUTH); 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(&list32[i], &list[i], - offsetof(struct drm_buf_pub, address)) - || __get_user(addr, &list[i].address) - || __put_user((unsigned long)addr, - &list32[i].address)) - return -EFAULT; - - if (__put_user(actual, &argp->count) - || __get_user(addr, &request->virtual) - || __put_user((unsigned long)addr, &argp->virtual)) + if (put_user(req32.count, &argp->count) + || put_user(req32.virtual, &argp->virtual)) return -EFAULT; return 0; @@ -556,21 +475,15 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd, unsigned long arg) { drm_buf_free32_t req32; - struct drm_buf_free __user *request; + struct drm_buf_free request; drm_buf_free32_t __user *argp = (void __user *)arg; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - request = compat_alloc_user_space(sizeof(*request)); - if (!request) - return -EFAULT; - if (__put_user(req32.count, &request->count) - || __put_user((int __user *)(unsigned long)req32.list, - &request->list)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_FREE_BUFS, (unsigned long)request); + request.count = req32.count; + request.list = compat_ptr(req32.list); + return drm_ioctl_kernel(file, drm_legacy_freebufs, &request, DRM_AUTH); } typedef struct drm_ctx_priv_map32 { @@ -582,48 +495,36 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd, unsigned long arg) { drm_ctx_priv_map32_t req32; - struct drm_ctx_priv_map __user *request; + struct drm_ctx_priv_map request; drm_ctx_priv_map32_t __user *argp = (void __user *)arg; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - request = compat_alloc_user_space(sizeof(*request)); - if (!request) - return -EFAULT; - if (__put_user(req32.ctx_id, &request->ctx_id) - || __put_user((void *)(unsigned long)req32.handle, - &request->handle)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request); + request.ctx_id = req32.ctx_id; + request.handle = compat_ptr(req32.handle); + return drm_ioctl_kernel(file, drm_legacy_setsareactx, &request, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } static int compat_drm_getsareactx(struct file *file, unsigned int cmd, unsigned long arg) { - struct drm_ctx_priv_map __user *request; + struct drm_ctx_priv_map req; + drm_ctx_priv_map32_t req32; drm_ctx_priv_map32_t __user *argp = (void __user *)arg; int err; - unsigned int ctx_id; - void *handle; - - if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp)) - || __get_user(ctx_id, &argp->ctx_id)) - return -EFAULT; - request = compat_alloc_user_space(sizeof(*request)); - if (!request) - return -EFAULT; - if (__put_user(ctx_id, &request->ctx_id)) + if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - err = drm_ioctl(file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request); + req.ctx_id = req32.ctx_id; + err = drm_ioctl_kernel(file, drm_legacy_getsareactx, &req, DRM_AUTH); if (err) return err; - if (__get_user(handle, &request->handle) - || __put_user((unsigned long)handle, &argp->handle)) + req32.handle = ptr_to_compat(req.handle); + if (copy_to_user(argp, &req32, sizeof(req32))) return -EFAULT; return 0; @@ -639,26 +540,20 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd, { drm_ctx_res32_t __user *argp = (void __user *)arg; drm_ctx_res32_t res32; - struct drm_ctx_res __user *res; + struct drm_ctx_res res; int err; if (copy_from_user(&res32, argp, sizeof(res32))) return -EFAULT; - res = compat_alloc_user_space(sizeof(*res)); - if (!res) - return -EFAULT; - if (__put_user(res32.count, &res->count) - || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts, - &res->contexts)) - return -EFAULT; - - err = drm_ioctl(file, DRM_IOCTL_RES_CTX, (unsigned long)res); + res.count = res32.count; + res.contexts = compat_ptr(res32.contexts); + err = drm_ioctl_kernel(file, drm_legacy_resctx, &res, DRM_AUTH); if (err) return err; - if (__get_user(res32.count, &res->count) - || __put_user(res32.count, &argp->count)) + res32.count = res.count; + if (copy_to_user(argp, &res32, sizeof(res32))) return -EFAULT; return 0; @@ -682,38 +577,26 @@ static int compat_drm_dma(struct file *file, unsigned int cmd, { drm_dma32_t d32; drm_dma32_t __user *argp = (void __user *)arg; - struct drm_dma __user *d; + struct drm_dma d; int err; if (copy_from_user(&d32, argp, sizeof(d32))) return -EFAULT; - d = compat_alloc_user_space(sizeof(*d)); - if (!d) - return -EFAULT; - - if (__put_user(d32.context, &d->context) - || __put_user(d32.send_count, &d->send_count) - || __put_user((int __user *)(unsigned long)d32.send_indices, - &d->send_indices) - || __put_user((int __user *)(unsigned long)d32.send_sizes, - &d->send_sizes) - || __put_user(d32.flags, &d->flags) - || __put_user(d32.request_count, &d->request_count) - || __put_user((int __user *)(unsigned long)d32.request_indices, - &d->request_indices) - || __put_user((int __user *)(unsigned long)d32.request_sizes, - &d->request_sizes)) - return -EFAULT; - - err = drm_ioctl(file, DRM_IOCTL_DMA, (unsigned long)d); + d.context = d32.context; + d.send_count = d32.send_count; + d.send_indices = compat_ptr(d32.send_indices); + d.send_sizes = compat_ptr(d32.send_sizes); + d.flags = d32.flags; + d.request_count = d32.request_count; + d.request_indices = compat_ptr(d32.request_indices); + d.request_sizes = compat_ptr(d32.request_sizes); + err = drm_ioctl_kernel(file, drm_legacy_dma_ioctl, &d, DRM_AUTH); if (err) return err; - if (__get_user(d32.request_size, &d->request_size) - || __get_user(d32.granted_count, &d->granted_count) - || __put_user(d32.request_size, &argp->request_size) - || __put_user(d32.granted_count, &argp->granted_count)) + if (put_user(d.request_size, &argp->request_size) + || put_user(d.granted_count, &argp->granted_count)) return -EFAULT; return 0; @@ -728,17 +611,13 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd, unsigned long arg) { drm_agp_mode32_t __user *argp = (void __user *)arg; - drm_agp_mode32_t m32; - struct drm_agp_mode __user *mode; - - if (get_user(m32.mode, &argp->mode)) - return -EFAULT; + struct drm_agp_mode mode; - mode = compat_alloc_user_space(sizeof(*mode)); - if (put_user(m32.mode, &mode->mode)) + if (get_user(mode.mode, &argp->mode)) return -EFAULT; - return drm_ioctl(file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode); + return drm_ioctl_kernel(file, drm_agp_enable_ioctl, &mode, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } typedef struct drm_agp_info32 { @@ -760,28 +639,22 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd, { drm_agp_info32_t __user *argp = (void __user *)arg; drm_agp_info32_t i32; - struct drm_agp_info __user *info; + struct drm_agp_info info; int err; - info = compat_alloc_user_space(sizeof(*info)); - if (!info) - return -EFAULT; - - err = drm_ioctl(file, DRM_IOCTL_AGP_INFO, (unsigned long)info); + err = drm_ioctl_kernel(file, drm_agp_info_ioctl, &info, DRM_AUTH); if (err) return err; - if (__get_user(i32.agp_version_major, &info->agp_version_major) - || __get_user(i32.agp_version_minor, &info->agp_version_minor) - || __get_user(i32.mode, &info->mode) - || __get_user(i32.aperture_base, &info->aperture_base) - || __get_user(i32.aperture_size, &info->aperture_size) - || __get_user(i32.memory_allowed, &info->memory_allowed) - || __get_user(i32.memory_used, &info->memory_used) - || __get_user(i32.id_vendor, &info->id_vendor) - || __get_user(i32.id_device, &info->id_device)) - return -EFAULT; - + i32.agp_version_major = info.agp_version_major; + i32.agp_version_minor = info.agp_version_minor; + i32.mode = info.mode; + i32.aperture_base = info.aperture_base; + i32.aperture_size = info.aperture_size; + i32.memory_allowed = info.memory_allowed; + i32.memory_used = info.memory_used; + i32.id_vendor = info.id_vendor; + i32.id_device = info.id_device; if (copy_to_user(argp, &i32, sizeof(i32))) return -EFAULT; @@ -800,26 +673,24 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd, { drm_agp_buffer32_t __user *argp = (void __user *)arg; drm_agp_buffer32_t req32; - struct drm_agp_buffer __user *request; + struct drm_agp_buffer request; int err; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - request = compat_alloc_user_space(sizeof(*request)); - if (!request - || __put_user(req32.size, &request->size) - || __put_user(req32.type, &request->type)) - return -EFAULT; - - err = drm_ioctl(file, DRM_IOCTL_AGP_ALLOC, (unsigned long)request); + request.size = req32.size; + request.type = req32.type; + err = drm_ioctl_kernel(file, drm_agp_alloc_ioctl, &request, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); if (err) return err; - if (__get_user(req32.handle, &request->handle) - || __get_user(req32.physical, &request->physical) - || copy_to_user(argp, &req32, sizeof(req32))) { - drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request); + req32.handle = request.handle; + req32.physical = request.physical; + if (copy_to_user(argp, &req32, sizeof(req32))) { + drm_ioctl_kernel(file, drm_agp_free_ioctl, &request, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); return -EFAULT; } @@ -830,16 +701,13 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd, unsigned long arg) { drm_agp_buffer32_t __user *argp = (void __user *)arg; - struct drm_agp_buffer __user *request; - u32 handle; + struct drm_agp_buffer request; - request = compat_alloc_user_space(sizeof(*request)); - if (!request - || get_user(handle, &argp->handle) - || __put_user(handle, &request->handle)) + if (get_user(request.handle, &argp->handle)) return -EFAULT; - return drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request); + return drm_ioctl_kernel(file, drm_agp_free_ioctl, &request, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } typedef struct drm_agp_binding32 { @@ -852,34 +720,28 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd, { drm_agp_binding32_t __user *argp = (void __user *)arg; drm_agp_binding32_t req32; - struct drm_agp_binding __user *request; + struct drm_agp_binding request; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - request = compat_alloc_user_space(sizeof(*request)); - if (!request - || __put_user(req32.handle, &request->handle) - || __put_user(req32.offset, &request->offset)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_AGP_BIND, (unsigned long)request); + request.handle = req32.handle; + request.offset = req32.offset; + return drm_ioctl_kernel(file, drm_agp_bind_ioctl, &request, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } static int compat_drm_agp_unbind(struct file *file, unsigned int cmd, unsigned long arg) { drm_agp_binding32_t __user *argp = (void __user *)arg; - struct drm_agp_binding __user *request; - u32 handle; + struct drm_agp_binding request; - request = compat_alloc_user_space(sizeof(*request)); - if (!request - || get_user(handle, &argp->handle) - || __put_user(handle, &request->handle)) + if (get_user(request.handle, &argp->handle)) return -EFAULT; - return drm_ioctl(file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request); + return drm_ioctl_kernel(file, drm_agp_unbind_ioctl, &request, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } #endif /* CONFIG_AGP */ @@ -892,23 +754,19 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd, unsigned long arg) { drm_scatter_gather32_t __user *argp = (void __user *)arg; - struct drm_scatter_gather __user *request; + struct drm_scatter_gather request; int err; - unsigned long x; - request = compat_alloc_user_space(sizeof(*request)); - if (!request || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)) - || __get_user(x, &argp->size) - || __put_user(x, &request->size)) + if (get_user(request.size, &argp->size)) return -EFAULT; - err = drm_ioctl(file, DRM_IOCTL_SG_ALLOC, (unsigned long)request); + err = drm_ioctl_kernel(file, drm_legacy_sg_alloc, &request, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); if (err) return err; /* XXX not sure about the handle conversion here... */ - if (__get_user(x, &request->handle) - || __put_user(x >> PAGE_SHIFT, &argp->handle)) + if (put_user(request.handle >> PAGE_SHIFT, &argp->handle)) return -EFAULT; return 0; @@ -918,19 +776,17 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd, unsigned long arg) { drm_scatter_gather32_t __user *argp = (void __user *)arg; - struct drm_scatter_gather __user *request; + struct drm_scatter_gather request; unsigned long x; - request = compat_alloc_user_space(sizeof(*request)); - if (!request || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)) - || __get_user(x, &argp->handle) - || __put_user(x << PAGE_SHIFT, &request->handle)) + if (get_user(x, &argp->handle)) return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_SG_FREE, (unsigned long)request); + request.handle = x << PAGE_SHIFT; + return drm_ioctl_kernel(file, drm_legacy_sg_free, &request, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } -#if defined(CONFIG_X86) || defined(CONFIG_IA64) +#if defined(CONFIG_X86) typedef struct drm_update_draw32 { drm_drawable_t handle; unsigned int type; @@ -943,22 +799,11 @@ static int compat_drm_update_draw(struct file *file, unsigned int cmd, unsigned long arg) { drm_update_draw32_t update32; - struct drm_update_draw __user *request; - int err; - if (copy_from_user(&update32, (void __user *)arg, sizeof(update32))) return -EFAULT; - request = compat_alloc_user_space(sizeof(*request)); - if (!request || - __put_user(update32.handle, &request->handle) || - __put_user(update32.type, &request->type) || - __put_user(update32.num, &request->num) || - __put_user(update32.data, &request->data)) - return -EFAULT; - - err = drm_ioctl(file, DRM_IOCTL_UPDATE_DRAW, (unsigned long)request); - return err; + return drm_ioctl_kernel(file, drm_noop, NULL, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } #endif @@ -985,36 +830,30 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, { drm_wait_vblank32_t __user *argp = (void __user *)arg; drm_wait_vblank32_t req32; - union drm_wait_vblank __user *request; + union drm_wait_vblank req; int err; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - request = compat_alloc_user_space(sizeof(*request)); - if (!request - || __put_user(req32.request.type, &request->request.type) - || __put_user(req32.request.sequence, &request->request.sequence) - || __put_user(req32.request.signal, &request->request.signal)) - return -EFAULT; - - err = drm_ioctl(file, DRM_IOCTL_WAIT_VBLANK, (unsigned long)request); + req.request.type = req32.request.type; + req.request.sequence = req32.request.sequence; + req.request.signal = req32.request.signal; + err = drm_ioctl_kernel(file, drm_wait_vblank, &req, DRM_UNLOCKED); if (err) return err; - if (__get_user(req32.reply.type, &request->reply.type) - || __get_user(req32.reply.sequence, &request->reply.sequence) - || __get_user(req32.reply.tval_sec, &request->reply.tval_sec) - || __get_user(req32.reply.tval_usec, &request->reply.tval_usec)) - return -EFAULT; - + req32.reply.type = req.reply.type; + req32.reply.sequence = req.reply.sequence; + req32.reply.tval_sec = req.reply.tval_sec; + req32.reply.tval_usec = req.reply.tval_usec; if (copy_to_user(argp, &req32, sizeof(req32))) return -EFAULT; return 0; } -#if defined(CONFIG_X86) || defined(CONFIG_IA64) +#if defined(CONFIG_X86) typedef struct drm_mode_fb_cmd232 { u32 fb_id; u32 width; @@ -1031,82 +870,67 @@ static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd, unsigned long arg) { struct drm_mode_fb_cmd232 __user *argp = (void __user *)arg; - struct drm_mode_fb_cmd232 req32; - struct drm_mode_fb_cmd2 __user *req64; - int i; + struct drm_mode_fb_cmd2 req64; int err; - if (copy_from_user(&req32, argp, sizeof(req32))) + if (copy_from_user(&req64, argp, + offsetof(drm_mode_fb_cmd232_t, modifier))) return -EFAULT; - req64 = compat_alloc_user_space(sizeof(*req64)); - - if (!access_ok(VERIFY_WRITE, req64, sizeof(*req64)) - || __put_user(req32.width, &req64->width) - || __put_user(req32.height, &req64->height) - || __put_user(req32.pixel_format, &req64->pixel_format) - || __put_user(req32.flags, &req64->flags)) + if (copy_from_user(&req64.modifier, &argp->modifier, + sizeof(req64.modifier))) return -EFAULT; - for (i = 0; i < 4; i++) { - if (__put_user(req32.handles[i], &req64->handles[i])) - return -EFAULT; - if (__put_user(req32.pitches[i], &req64->pitches[i])) - return -EFAULT; - if (__put_user(req32.offsets[i], &req64->offsets[i])) - return -EFAULT; - if (__put_user(req32.modifier[i], &req64->modifier[i])) - return -EFAULT; - } - - err = drm_ioctl(file, DRM_IOCTL_MODE_ADDFB2, (unsigned long)req64); + err = drm_ioctl_kernel(file, drm_mode_addfb2, &req64, + DRM_CONTROL_ALLOW|DRM_UNLOCKED); if (err) return err; - if (__get_user(req32.fb_id, &req64->fb_id)) - return -EFAULT; - - if (copy_to_user(argp, &req32, sizeof(req32))) + if (put_user(req64.fb_id, &argp->fb_id)) return -EFAULT; return 0; } #endif -static drm_ioctl_compat_t *drm_compat_ioctls[] = { - [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version, - [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique, - [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap, - [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient, - [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats, - [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs, - [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs, - [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs, - [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs, - [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs, - [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap, - [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx, - [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx, - [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx, - [DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma, +static struct { + drm_ioctl_compat_t *fn; + char *name; +} drm_compat_ioctls[] = { +#define DRM_IOCTL32_DEF(n, f) [DRM_IOCTL_NR(n##32)] = {.fn = f, .name = #n} + DRM_IOCTL32_DEF(DRM_IOCTL_VERSION, compat_drm_version), + DRM_IOCTL32_DEF(DRM_IOCTL_GET_UNIQUE, compat_drm_getunique), + DRM_IOCTL32_DEF(DRM_IOCTL_GET_MAP, compat_drm_getmap), + DRM_IOCTL32_DEF(DRM_IOCTL_GET_CLIENT, compat_drm_getclient), + DRM_IOCTL32_DEF(DRM_IOCTL_GET_STATS, compat_drm_getstats), + DRM_IOCTL32_DEF(DRM_IOCTL_SET_UNIQUE, compat_drm_setunique), + DRM_IOCTL32_DEF(DRM_IOCTL_ADD_MAP, compat_drm_addmap), + DRM_IOCTL32_DEF(DRM_IOCTL_ADD_BUFS, compat_drm_addbufs), + DRM_IOCTL32_DEF(DRM_IOCTL_MARK_BUFS, compat_drm_markbufs), + DRM_IOCTL32_DEF(DRM_IOCTL_INFO_BUFS, compat_drm_infobufs), + DRM_IOCTL32_DEF(DRM_IOCTL_MAP_BUFS, compat_drm_mapbufs), + DRM_IOCTL32_DEF(DRM_IOCTL_FREE_BUFS, compat_drm_freebufs), + DRM_IOCTL32_DEF(DRM_IOCTL_RM_MAP, compat_drm_rmmap), + DRM_IOCTL32_DEF(DRM_IOCTL_SET_SAREA_CTX, compat_drm_setsareactx), + DRM_IOCTL32_DEF(DRM_IOCTL_GET_SAREA_CTX, compat_drm_getsareactx), + DRM_IOCTL32_DEF(DRM_IOCTL_RES_CTX, compat_drm_resctx), + DRM_IOCTL32_DEF(DRM_IOCTL_DMA, compat_drm_dma), #if IS_ENABLED(CONFIG_AGP) - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind, + DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ENABLE, compat_drm_agp_enable), + DRM_IOCTL32_DEF(DRM_IOCTL_AGP_INFO, compat_drm_agp_info), + DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ALLOC, compat_drm_agp_alloc), + DRM_IOCTL32_DEF(DRM_IOCTL_AGP_FREE, compat_drm_agp_free), + DRM_IOCTL32_DEF(DRM_IOCTL_AGP_BIND, compat_drm_agp_bind), + DRM_IOCTL32_DEF(DRM_IOCTL_AGP_UNBIND, compat_drm_agp_unbind), #endif - [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc, - [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free, + DRM_IOCTL32_DEF(DRM_IOCTL_SG_ALLOC, compat_drm_sg_alloc), + DRM_IOCTL32_DEF(DRM_IOCTL_SG_FREE, compat_drm_sg_free), #if defined(CONFIG_X86) || defined(CONFIG_IA64) - [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw, + DRM_IOCTL32_DEF(DRM_IOCTL_UPDATE_DRAW, compat_drm_update_draw), #endif - [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank, + DRM_IOCTL32_DEF(DRM_IOCTL_WAIT_VBLANK, compat_drm_wait_vblank), #if defined(CONFIG_X86) || defined(CONFIG_IA64) - [DRM_IOCTL_NR(DRM_IOCTL_MODE_ADDFB232)] = compat_drm_mode_addfb2, + DRM_IOCTL32_DEF(DRM_IOCTL_MODE_ADDFB2, compat_drm_mode_addfb2), #endif }; @@ -1127,6 +951,7 @@ static drm_ioctl_compat_t *drm_compat_ioctls[] = { long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); + struct drm_file *file_priv = filp->private_data; drm_ioctl_compat_t *fn; int ret; @@ -1137,13 +962,18 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (nr >= ARRAY_SIZE(drm_compat_ioctls)) return drm_ioctl(filp, cmd, arg); - fn = drm_compat_ioctls[nr]; - - if (fn != NULL) - ret = (*fn) (filp, cmd, arg); - else - ret = drm_ioctl(filp, cmd, arg); + fn = drm_compat_ioctls[nr].fn; + if (!fn) + return drm_ioctl(filp, cmd, arg); + DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", + task_pid_nr(current), + (long)old_encode_dev(file_priv->minor->kdev->devt), + file_priv->authenticated, + drm_compat_ioctls[nr].name); + ret = (*fn)(filp, cmd, arg); + if (ret) + DRM_DEBUG("ret = %d\n", ret); return ret; } EXPORT_SYMBOL(drm_compat_ioctl); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 865e3ee4d743..335821153776 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -107,7 +107,7 @@ * * Copies the bus id from drm_device::unique into user space. */ -static int drm_getunique(struct drm_device *dev, void *data, +int drm_getunique(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_unique *u = data; @@ -172,7 +172,7 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) * Searches for the client with the specified index and copies its information * into userspace */ -static int drm_getclient(struct drm_device *dev, void *data, +int drm_getclient(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_client *client = data; @@ -461,7 +461,7 @@ static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value) * * Fills in the version information in \p arg. */ -static int drm_version(struct drm_device *dev, void *data, +int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_version *version = data; @@ -694,6 +694,33 @@ static const struct drm_ioctl_desc drm_ioctls[] = { * structure. */ +long drm_ioctl_kernel(struct file *file, drm_ioctl_t *func, void *kdata, + u32 flags) +{ + struct drm_file *file_priv = file->private_data; + struct drm_device *dev = file_priv->minor->dev; + int retcode; + + if (drm_device_is_unplugged(dev)) + return -ENODEV; + + retcode = drm_ioctl_permit(flags, file_priv); + if (unlikely(retcode)) + return retcode; + + /* Enforce sane locking for modern driver ioctls. */ + if (!drm_core_check_feature(dev, DRIVER_LEGACY) || + (flags & DRM_UNLOCKED)) + retcode = func(dev, kdata, file_priv); + else { + mutex_lock(&drm_global_mutex); + retcode = func(dev, kdata, file_priv); + mutex_unlock(&drm_global_mutex); + } + return retcode; +} +EXPORT_SYMBOL(drm_ioctl_kernel); + /** * drm_ioctl - ioctl callback implementation for DRM drivers * @filp: file this ioctl is called on @@ -762,10 +789,6 @@ long drm_ioctl(struct file *filp, goto err_i1; } - retcode = drm_ioctl_permit(ioctl->flags, file_priv); - if (unlikely(retcode)) - goto err_i1; - if (ksize <= sizeof(stack_kdata)) { kdata = stack_kdata; } else { @@ -784,16 +807,7 @@ long drm_ioctl(struct file *filp, if (ksize > in_size) memset(kdata + in_size, 0, ksize - in_size); - /* Enforce sane locking for modern driver ioctls. */ - if (!drm_core_check_feature(dev, DRIVER_LEGACY) || - (ioctl->flags & DRM_UNLOCKED)) - retcode = func(dev, kdata, file_priv); - else { - mutex_lock(&drm_global_mutex); - retcode = func(dev, kdata, file_priv); - mutex_unlock(&drm_global_mutex); - } - + retcode = drm_ioctl_kernel(filp, func, kdata, ioctl->flags); if (copy_to_user((void __user *)arg, kdata, out_size) != 0) retcode = -EFAULT; diff --git a/drivers/gpu/drm/drm_legacy.h b/drivers/gpu/drm/drm_legacy.h index e4bb5ad747c8..280fbeb846ff 100644 --- a/drivers/gpu/drm/drm_legacy.h +++ b/drivers/gpu/drm/drm_legacy.h @@ -74,6 +74,13 @@ int drm_legacy_freebufs(struct drm_device *d, void *v, struct drm_file *f); int drm_legacy_mapbufs(struct drm_device *d, void *v, struct drm_file *f); int drm_legacy_dma_ioctl(struct drm_device *d, void *v, struct drm_file *f); +int __drm_legacy_infobufs(struct drm_device *, void *, int *, + int (*)(void *, int, struct drm_buf_entry *)); +int __drm_legacy_mapbufs(struct drm_device *, void *, int *, + void __user **, + int (*)(void *, int, unsigned long, struct drm_buf *), + struct drm_file *); + #ifdef CONFIG_DRM_VM void drm_legacy_vma_flush(struct drm_device *d); #else diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h index 45cf363d25ad..a45bb22275a7 100644 --- a/drivers/gpu/drm/mga/mga_drv.h +++ b/drivers/gpu/drm/mga/mga_drv.h @@ -159,6 +159,8 @@ extern int mga_dma_bootstrap(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int mga_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int mga_getparam(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int mga_dma_flush(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int mga_dma_reset(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/mga/mga_ioc32.c b/drivers/gpu/drm/mga/mga_ioc32.c index 729bfd56b55f..245fb2e359cf 100644 --- a/drivers/gpu/drm/mga/mga_ioc32.c +++ b/drivers/gpu/drm/mga/mga_ioc32.c @@ -61,46 +61,25 @@ 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; + drm_mga_init_t init; 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, DRM_IOCTL_MGA_INIT, (unsigned long)init); + init.func = init32.func; + init.sarea_priv_offset = init32.sarea_priv_offset; + memcpy(&init.chipset, &init32.chipset, + offsetof(drm_mga_init_t, fb_offset) - + offsetof(drm_mga_init_t, chipset)); + init.fb_offset = init32.fb_offset; + init.mmio_offset = init32.mmio_offset; + init.status_offset = init32.status_offset; + init.warp_offset = init32.warp_offset; + init.primary_offset = init32.primary_offset; + init.buffers_offset = init32.buffers_offset; + + return drm_ioctl_kernel(file, mga_dma_init, &init, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } typedef struct drm_mga_getparam32 { @@ -112,19 +91,14 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd, unsigned long arg) { drm_mga_getparam32_t getparam32; - drm_mga_getparam_t __user *getparam; + drm_mga_getparam_t 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, DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam); + getparam.param = getparam32.param; + getparam.value = compat_ptr(getparam32.value); + return drm_ioctl_kernel(file, mga_getparam, &getparam, DRM_AUTH); } typedef struct drm_mga_drm_bootstrap32 { @@ -141,48 +115,33 @@ 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; + drm_mga_dma_bootstrap_t 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; + dma_bootstrap.texture_handle = dma_bootstrap32.texture_handle; + dma_bootstrap.texture_size = dma_bootstrap32.texture_size; + dma_bootstrap.primary_size = dma_bootstrap32.primary_size; + dma_bootstrap.secondary_bin_count = dma_bootstrap32.secondary_bin_count; + dma_bootstrap.secondary_bin_size = dma_bootstrap32.secondary_bin_size; + dma_bootstrap.agp_mode = dma_bootstrap32.agp_mode; + dma_bootstrap.agp_size = dma_bootstrap32.agp_size; - err = drm_ioctl(file, DRM_IOCTL_MGA_DMA_BOOTSTRAP, - (unsigned long)dma_bootstrap); + err = drm_ioctl_kernel(file, mga_dma_bootstrap, &dma_bootstrap, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 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; - + dma_bootstrap32.texture_handle = dma_bootstrap.texture_handle; + dma_bootstrap32.texture_size = dma_bootstrap.texture_size; + dma_bootstrap32.primary_size = dma_bootstrap.primary_size; + dma_bootstrap32.secondary_bin_count = dma_bootstrap.secondary_bin_count; + dma_bootstrap32.secondary_bin_size = dma_bootstrap.secondary_bin_size; + dma_bootstrap32.agp_mode = dma_bootstrap.agp_mode; + dma_bootstrap32.agp_size = dma_bootstrap.agp_size; if (copy_to_user((void __user *)arg, &dma_bootstrap32, sizeof(dma_bootstrap32))) return -EFAULT; @@ -190,10 +149,14 @@ static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, return 0; } -drm_ioctl_compat_t *mga_compat_ioctls[] = { - [DRM_MGA_INIT] = compat_mga_init, - [DRM_MGA_GETPARAM] = compat_mga_getparam, - [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap, +static struct { + drm_ioctl_compat_t *fn; + char *name; +} mga_compat_ioctls[] = { +#define DRM_IOCTL32_DEF(n, f)[DRM_##n] = {.fn = f, .name = #n} + DRM_IOCTL32_DEF(MGA_INIT, compat_mga_init), + DRM_IOCTL32_DEF(MGA_GETPARAM, compat_mga_getparam), + DRM_IOCTL32_DEF(MGA_DMA_BOOTSTRAP, compat_mga_dma_bootstrap), }; /** @@ -208,19 +171,27 @@ drm_ioctl_compat_t *mga_compat_ioctls[] = { long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); + struct drm_file *file_priv = filp->private_data; 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 + ARRAY_SIZE(mga_compat_ioctls)) - fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE]; - - if (fn != NULL) - ret = (*fn) (filp, cmd, arg); - else - ret = drm_ioctl(filp, cmd, arg); - + if (nr >= DRM_COMMAND_BASE + ARRAY_SIZE(mga_compat_ioctls)) + return drm_ioctl(filp, cmd, arg); + + fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE].fn; + if (!fn) + return drm_ioctl(filp, cmd, arg); + + DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", + task_pid_nr(current), + (long)old_encode_dev(file_priv->minor->kdev->devt), + file_priv->authenticated, + mga_compat_ioctls[nr - DRM_COMMAND_BASE].name); + ret = (*fn) (filp, cmd, arg); + if (ret) + DRM_DEBUG("ret = %d\n", ret); return ret; } diff --git a/drivers/gpu/drm/mga/mga_state.c b/drivers/gpu/drm/mga/mga_state.c index 792f924496fc..e5f6b735f575 100644 --- a/drivers/gpu/drm/mga/mga_state.c +++ b/drivers/gpu/drm/mga/mga_state.c @@ -1005,7 +1005,7 @@ static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *fil return 0; } -static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) +int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_getparam_t *param = data; diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index 08bd17d3925c..640f8b3f9443 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -105,7 +105,6 @@ radeon-y += \ vce_v2_0.o \ radeon_kfd.o -radeon-$(CONFIG_COMPAT) += radeon_ioc32.o radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o radeon-$(CONFIG_ACPI) += radeon_acpi.o diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 93d45aa5c3d4..e25cb51ce0ca 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -38,6 +38,7 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/vga_switcheroo.h> +#include <linux/compat.h> #include <drm/drm_gem.h> #include <drm/drm_fb_helper.h> @@ -154,8 +155,6 @@ void radeon_gem_prime_unpin(struct drm_gem_object *obj); struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *); void *radeon_gem_prime_vmap(struct drm_gem_object *obj); void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); -extern long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg); /* atpx handler */ #if defined(CONFIG_VGA_SWITCHEROO) @@ -505,6 +504,21 @@ long radeon_drm_ioctl(struct file *filp, return ret; } +#ifdef CONFIG_COMPAT +static 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 = radeon_drm_ioctl(filp, cmd, arg); + + return ret; +} +#endif + static const struct dev_pm_ops radeon_pm_ops = { .suspend = radeon_pmops_suspend, .resume = radeon_pmops_resume, diff --git a/drivers/gpu/drm/radeon/radeon_ioc32.c b/drivers/gpu/drm/radeon/radeon_ioc32.c deleted file mode 100644 index 0b98ea134579..000000000000 --- a/drivers/gpu/drm/radeon/radeon_ioc32.c +++ /dev/null @@ -1,424 +0,0 @@ -/** - * \file radeon_ioc32.c - * - * 32-bit ioctl compatibility routines for the Radeon DRM. - * - * \author Paul Mackerras <paulus@samba.org> - * - * Copyright (C) Paul Mackerras 2005 - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include <linux/compat.h> - -#include <drm/drmP.h> -#include <drm/radeon_drm.h> -#include "radeon_drv.h" - -typedef struct drm_radeon_init32 { - int func; - u32 sarea_priv_offset; - int is_pci; - int cp_mode; - int gart_size; - int ring_size; - int usec_timeout; - - unsigned int fb_bpp; - unsigned int front_offset, front_pitch; - unsigned int back_offset, back_pitch; - unsigned int depth_bpp; - unsigned int depth_offset, depth_pitch; - - u32 fb_offset; - u32 mmio_offset; - u32 ring_offset; - u32 ring_rptr_offset; - u32 buffers_offset; - u32 gart_textures_offset; -} drm_radeon_init32_t; - -static int compat_radeon_cp_init(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_radeon_init32_t init32; - drm_radeon_init_t __user *init; - - 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.is_pci, &init->is_pci) - || __put_user(init32.cp_mode, &init->cp_mode) - || __put_user(init32.gart_size, &init->gart_size) - || __put_user(init32.ring_size, &init->ring_size) - || __put_user(init32.usec_timeout, &init->usec_timeout) - || __put_user(init32.fb_bpp, &init->fb_bpp) - || __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_bpp, &init->depth_bpp) - || __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.ring_offset, &init->ring_offset) - || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset) - || __put_user(init32.buffers_offset, &init->buffers_offset) - || __put_user(init32.gart_textures_offset, - &init->gart_textures_offset)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); -} - -typedef struct drm_radeon_clear32 { - unsigned int flags; - unsigned int clear_color; - unsigned int clear_depth; - unsigned int color_mask; - unsigned int depth_mask; /* misnamed field: should be stencil */ - u32 depth_boxes; -} drm_radeon_clear32_t; - -static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_radeon_clear32_t clr32; - drm_radeon_clear_t __user *clr; - - if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32))) - return -EFAULT; - - clr = compat_alloc_user_space(sizeof(*clr)); - if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr)) - || __put_user(clr32.flags, &clr->flags) - || __put_user(clr32.clear_color, &clr->clear_color) - || __put_user(clr32.clear_depth, &clr->clear_depth) - || __put_user(clr32.color_mask, &clr->color_mask) - || __put_user(clr32.depth_mask, &clr->depth_mask) - || __put_user((void __user *)(unsigned long)clr32.depth_boxes, - &clr->depth_boxes)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); -} - -typedef struct drm_radeon_stipple32 { - u32 mask; -} drm_radeon_stipple32_t; - -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); -} - -typedef struct drm_radeon_tex_image32 { - unsigned int x, y; /* Blit coordinates */ - unsigned int width, height; - u32 data; -} drm_radeon_tex_image32_t; - -typedef struct drm_radeon_texture32 { - unsigned int offset; - int pitch; - int format; - int width; /* Texture image coordinates */ - int height; - u32 image; -} drm_radeon_texture32_t; - -static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_radeon_texture32_t req32; - drm_radeon_texture_t __user *request; - drm_radeon_tex_image32_t img32; - drm_radeon_tex_image_t __user *image; - - if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) - return -EFAULT; - if (req32.image == 0) - return -EINVAL; - if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image, - sizeof(img32))) - return -EFAULT; - - request = compat_alloc_user_space(sizeof(*request) + sizeof(*image)); - if (!access_ok(VERIFY_WRITE, request, - sizeof(*request) + sizeof(*image))) - return -EFAULT; - image = (drm_radeon_tex_image_t __user *) (request + 1); - - if (__put_user(req32.offset, &request->offset) - || __put_user(req32.pitch, &request->pitch) - || __put_user(req32.format, &request->format) - || __put_user(req32.width, &request->width) - || __put_user(req32.height, &request->height) - || __put_user(image, &request->image) - || __put_user(img32.x, &image->x) - || __put_user(img32.y, &image->y) - || __put_user(img32.width, &image->width) - || __put_user(img32.height, &image->height) - || __put_user((const void __user *)(unsigned long)img32.data, - &image->data)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); -} - -typedef struct drm_radeon_vertex2_32 { - int idx; /* Index of vertex buffer */ - int discard; /* Client finished with buffer? */ - int nr_states; - u32 state; - int nr_prims; - u32 prim; -} drm_radeon_vertex2_32_t; - -static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_radeon_vertex2_32_t req32; - drm_radeon_vertex2_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.idx, &request->idx) - || __put_user(req32.discard, &request->discard) - || __put_user(req32.nr_states, &request->nr_states) - || __put_user((void __user *)(unsigned long)req32.state, - &request->state) - || __put_user(req32.nr_prims, &request->nr_prims) - || __put_user((void __user *)(unsigned long)req32.prim, - &request->prim)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); -} - -typedef struct drm_radeon_cmd_buffer32 { - int bufsz; - u32 buf; - int nbox; - u32 boxes; -} drm_radeon_cmd_buffer32_t; - -static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_radeon_cmd_buffer32_t req32; - drm_radeon_cmd_buffer_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.bufsz, &request->bufsz) - || __put_user((void __user *)(unsigned long)req32.buf, - &request->buf) - || __put_user(req32.nbox, &request->nbox) - || __put_user((void __user *)(unsigned long)req32.boxes, - &request->boxes)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); -} - -typedef struct drm_radeon_getparam32 { - int param; - u32 value; -} drm_radeon_getparam32_t; - -static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_radeon_getparam32_t req32; - drm_radeon_getparam_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_GETPARAM, (unsigned long)request); -} - -typedef struct drm_radeon_mem_alloc32 { - int region; - int alignment; - int size; - u32 region_offset; /* offset from start of fb or GART */ -} drm_radeon_mem_alloc32_t; - -static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_radeon_mem_alloc32_t req32; - drm_radeon_mem_alloc_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.region, &request->region) - || __put_user(req32.alignment, &request->alignment) - || __put_user(req32.size, &request->size) - || __put_user((int __user *)(unsigned long)req32.region_offset, - &request->region_offset)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); -} - -typedef struct drm_radeon_irq_emit32 { - u32 irq_seq; -} drm_radeon_irq_emit32_t; - -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); -} - -/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */ -#if defined (CONFIG_X86_64) || defined(CONFIG_IA64) -typedef struct drm_radeon_setparam32 { - int param; - u64 value; -} __attribute__((packed)) drm_radeon_setparam32_t; - -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); -} -#else -#define compat_radeon_cp_setparam NULL -#endif /* X86_64 || IA64 */ - -static drm_ioctl_compat_t *radeon_compat_ioctls[] = { - [DRM_RADEON_CP_INIT] = compat_radeon_cp_init, - [DRM_RADEON_CLEAR] = compat_radeon_cp_clear, - [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple, - [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture, - [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2, - [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf, - [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam, - [DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam, - [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc, - [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit, -}; - -/** - * 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 radeon_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 + ARRAY_SIZE(radeon_compat_ioctls)) - fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; - - if (fn != NULL) - ret = (*fn) (filp, cmd, arg); - else - ret = drm_ioctl(filp, cmd, arg); - - return ret; -} - -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 = radeon_drm_ioctl(filp, cmd, arg); - - return ret; -} diff --git a/include/drm/drm_ioctl.h b/include/drm/drm_ioctl.h index ee03b3c44b3b..add42809642a 100644 --- a/include/drm/drm_ioctl.h +++ b/include/drm/drm_ioctl.h @@ -172,6 +172,7 @@ struct drm_ioctl_desc { int drm_ioctl_permit(u32 flags, struct drm_file *file_priv); long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +long drm_ioctl_kernel(struct file *, drm_ioctl_t, void *, u32); #ifdef CONFIG_COMPAT long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); #else |