cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

drm_ioc32.c (27893B)


      1/*
      2 * \file drm_ioc32.c
      3 *
      4 * 32-bit ioctl compatibility routines for the DRM.
      5 *
      6 * \author Paul Mackerras <paulus@samba.org>
      7 *
      8 * Copyright (C) Paul Mackerras 2005.
      9 * All Rights Reserved.
     10 *
     11 * Permission is hereby granted, free of charge, to any person obtaining a
     12 * copy of this software and associated documentation files (the "Software"),
     13 * to deal in the Software without restriction, including without limitation
     14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     15 * and/or sell copies of the Software, and to permit persons to whom the
     16 * Software is furnished to do so, subject to the following conditions:
     17 *
     18 * The above copyright notice and this permission notice (including the next
     19 * paragraph) shall be included in all copies or substantial portions of the
     20 * Software.
     21 *
     22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     25 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     28 * IN THE SOFTWARE.
     29 */
     30#include <linux/compat.h>
     31#include <linux/ratelimit.h>
     32#include <linux/export.h>
     33
     34#include <drm/drm_file.h>
     35#include <drm/drm_print.h>
     36
     37#include "drm_crtc_internal.h"
     38#include "drm_internal.h"
     39#include "drm_legacy.h"
     40
     41#define DRM_IOCTL_VERSION32		DRM_IOWR(0x00, drm_version32_t)
     42#define DRM_IOCTL_GET_UNIQUE32		DRM_IOWR(0x01, drm_unique32_t)
     43#define DRM_IOCTL_GET_MAP32		DRM_IOWR(0x04, drm_map32_t)
     44#define DRM_IOCTL_GET_CLIENT32		DRM_IOWR(0x05, drm_client32_t)
     45#define DRM_IOCTL_GET_STATS32		DRM_IOR( 0x06, drm_stats32_t)
     46
     47#define DRM_IOCTL_SET_UNIQUE32		DRM_IOW( 0x10, drm_unique32_t)
     48#define DRM_IOCTL_ADD_MAP32		DRM_IOWR(0x15, drm_map32_t)
     49#define DRM_IOCTL_ADD_BUFS32		DRM_IOWR(0x16, drm_buf_desc32_t)
     50#define DRM_IOCTL_MARK_BUFS32		DRM_IOW( 0x17, drm_buf_desc32_t)
     51#define DRM_IOCTL_INFO_BUFS32		DRM_IOWR(0x18, drm_buf_info32_t)
     52#define DRM_IOCTL_MAP_BUFS32		DRM_IOWR(0x19, drm_buf_map32_t)
     53#define DRM_IOCTL_FREE_BUFS32		DRM_IOW( 0x1a, drm_buf_free32_t)
     54
     55#define DRM_IOCTL_RM_MAP32		DRM_IOW( 0x1b, drm_map32_t)
     56
     57#define DRM_IOCTL_SET_SAREA_CTX32	DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
     58#define DRM_IOCTL_GET_SAREA_CTX32	DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
     59
     60#define DRM_IOCTL_RES_CTX32		DRM_IOWR(0x26, drm_ctx_res32_t)
     61#define DRM_IOCTL_DMA32			DRM_IOWR(0x29, drm_dma32_t)
     62
     63#define DRM_IOCTL_AGP_ENABLE32		DRM_IOW( 0x32, drm_agp_mode32_t)
     64#define DRM_IOCTL_AGP_INFO32		DRM_IOR( 0x33, drm_agp_info32_t)
     65#define DRM_IOCTL_AGP_ALLOC32		DRM_IOWR(0x34, drm_agp_buffer32_t)
     66#define DRM_IOCTL_AGP_FREE32		DRM_IOW( 0x35, drm_agp_buffer32_t)
     67#define DRM_IOCTL_AGP_BIND32		DRM_IOW( 0x36, drm_agp_binding32_t)
     68#define DRM_IOCTL_AGP_UNBIND32		DRM_IOW( 0x37, drm_agp_binding32_t)
     69
     70#define DRM_IOCTL_SG_ALLOC32		DRM_IOW( 0x38, drm_scatter_gather32_t)
     71#define DRM_IOCTL_SG_FREE32		DRM_IOW( 0x39, drm_scatter_gather32_t)
     72
     73#define DRM_IOCTL_UPDATE_DRAW32		DRM_IOW( 0x3f, drm_update_draw32_t)
     74
     75#define DRM_IOCTL_WAIT_VBLANK32		DRM_IOWR(0x3a, drm_wait_vblank32_t)
     76
     77#define DRM_IOCTL_MODE_ADDFB232		DRM_IOWR(0xb8, drm_mode_fb_cmd232_t)
     78
     79typedef struct drm_version_32 {
     80	int version_major;	  /* Major version */
     81	int version_minor;	  /* Minor version */
     82	int version_patchlevel;	   /* Patch level */
     83	u32 name_len;		  /* Length of name buffer */
     84	u32 name;		  /* Name of driver */
     85	u32 date_len;		  /* Length of date buffer */
     86	u32 date;		  /* User-space buffer to hold date */
     87	u32 desc_len;		  /* Length of desc buffer */
     88	u32 desc;		  /* User-space buffer to hold desc */
     89} drm_version32_t;
     90
     91static int compat_drm_version(struct file *file, unsigned int cmd,
     92			      unsigned long arg)
     93{
     94	drm_version32_t v32;
     95	struct drm_version v;
     96	int err;
     97
     98	if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
     99		return -EFAULT;
    100
    101	memset(&v, 0, sizeof(v));
    102
    103	v = (struct drm_version) {
    104		.name_len = v32.name_len,
    105		.name = compat_ptr(v32.name),
    106		.date_len = v32.date_len,
    107		.date = compat_ptr(v32.date),
    108		.desc_len = v32.desc_len,
    109		.desc = compat_ptr(v32.desc),
    110	};
    111	err = drm_ioctl_kernel(file, drm_version, &v,
    112			       DRM_RENDER_ALLOW);
    113	if (err)
    114		return err;
    115
    116	v32.version_major = v.version_major;
    117	v32.version_minor = v.version_minor;
    118	v32.version_patchlevel = v.version_patchlevel;
    119	v32.name_len = v.name_len;
    120	v32.date_len = v.date_len;
    121	v32.desc_len = v.desc_len;
    122	if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
    123		return -EFAULT;
    124	return 0;
    125}
    126
    127typedef struct drm_unique32 {
    128	u32 unique_len;	/* Length of unique */
    129	u32 unique;	/* Unique name for driver instantiation */
    130} drm_unique32_t;
    131
    132static int compat_drm_getunique(struct file *file, unsigned int cmd,
    133				unsigned long arg)
    134{
    135	drm_unique32_t uq32;
    136	struct drm_unique uq;
    137	int err;
    138
    139	if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
    140		return -EFAULT;
    141
    142	memset(&uq, 0, sizeof(uq));
    143
    144	uq = (struct drm_unique){
    145		.unique_len = uq32.unique_len,
    146		.unique = compat_ptr(uq32.unique),
    147	};
    148
    149	err = drm_ioctl_kernel(file, drm_getunique, &uq, 0);
    150	if (err)
    151		return err;
    152
    153	uq32.unique_len = uq.unique_len;
    154	if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
    155		return -EFAULT;
    156	return 0;
    157}
    158
    159static int compat_drm_setunique(struct file *file, unsigned int cmd,
    160				unsigned long arg)
    161{
    162	/* it's dead */
    163	return -EINVAL;
    164}
    165
    166#if IS_ENABLED(CONFIG_DRM_LEGACY)
    167typedef struct drm_map32 {
    168	u32 offset;		/* Requested physical address (0 for SAREA) */
    169	u32 size;		/* Requested physical size (bytes) */
    170	enum drm_map_type type;	/* Type of memory to map */
    171	enum drm_map_flags flags;	/* Flags */
    172	u32 handle;		/* User-space: "Handle" to pass to mmap() */
    173	int mtrr;		/* MTRR slot used */
    174} drm_map32_t;
    175
    176static int compat_drm_getmap(struct file *file, unsigned int cmd,
    177			     unsigned long arg)
    178{
    179	drm_map32_t __user *argp = (void __user *)arg;
    180	drm_map32_t m32;
    181	struct drm_map map;
    182	int err;
    183
    184	if (copy_from_user(&m32, argp, sizeof(m32)))
    185		return -EFAULT;
    186
    187	map.offset = m32.offset;
    188	err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, 0);
    189	if (err)
    190		return err;
    191
    192	m32.offset = map.offset;
    193	m32.size = map.size;
    194	m32.type = map.type;
    195	m32.flags = map.flags;
    196	m32.handle = ptr_to_compat((void __user *)map.handle);
    197	m32.mtrr = map.mtrr;
    198	if (copy_to_user(argp, &m32, sizeof(m32)))
    199		return -EFAULT;
    200	return 0;
    201
    202}
    203
    204static int compat_drm_addmap(struct file *file, unsigned int cmd,
    205			     unsigned long arg)
    206{
    207	drm_map32_t __user *argp = (void __user *)arg;
    208	drm_map32_t m32;
    209	struct drm_map map;
    210	int err;
    211
    212	if (copy_from_user(&m32, argp, sizeof(m32)))
    213		return -EFAULT;
    214
    215	map.offset = m32.offset;
    216	map.size = m32.size;
    217	map.type = m32.type;
    218	map.flags = m32.flags;
    219
    220	err = drm_ioctl_kernel(file, drm_legacy_addmap_ioctl, &map,
    221				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    222	if (err)
    223		return err;
    224
    225	m32.offset = map.offset;
    226	m32.mtrr = map.mtrr;
    227	m32.handle = ptr_to_compat((void __user *)map.handle);
    228	if (map.handle != compat_ptr(m32.handle))
    229		pr_err_ratelimited("compat_drm_addmap truncated handle %p for type %d offset %x\n",
    230				   map.handle, m32.type, m32.offset);
    231
    232	if (copy_to_user(argp, &m32, sizeof(m32)))
    233		return -EFAULT;
    234
    235	return 0;
    236}
    237
    238static int compat_drm_rmmap(struct file *file, unsigned int cmd,
    239			    unsigned long arg)
    240{
    241	drm_map32_t __user *argp = (void __user *)arg;
    242	struct drm_map map;
    243	u32 handle;
    244
    245	if (get_user(handle, &argp->handle))
    246		return -EFAULT;
    247	map.handle = compat_ptr(handle);
    248	return drm_ioctl_kernel(file, drm_legacy_rmmap_ioctl, &map, DRM_AUTH);
    249}
    250#endif
    251
    252typedef struct drm_client32 {
    253	int idx;	/* Which client desired? */
    254	int auth;	/* Is client authenticated? */
    255	u32 pid;	/* Process ID */
    256	u32 uid;	/* User ID */
    257	u32 magic;	/* Magic */
    258	u32 iocs;	/* Ioctl count */
    259} drm_client32_t;
    260
    261static int compat_drm_getclient(struct file *file, unsigned int cmd,
    262				unsigned long arg)
    263{
    264	drm_client32_t c32;
    265	drm_client32_t __user *argp = (void __user *)arg;
    266	struct drm_client client;
    267	int err;
    268
    269	if (copy_from_user(&c32, argp, sizeof(c32)))
    270		return -EFAULT;
    271
    272	memset(&client, 0, sizeof(client));
    273
    274	client.idx = c32.idx;
    275
    276	err = drm_ioctl_kernel(file, drm_getclient, &client, 0);
    277	if (err)
    278		return err;
    279
    280	c32.idx = client.idx;
    281	c32.auth = client.auth;
    282	c32.pid = client.pid;
    283	c32.uid = client.uid;
    284	c32.magic = client.magic;
    285	c32.iocs = client.iocs;
    286
    287	if (copy_to_user(argp, &c32, sizeof(c32)))
    288		return -EFAULT;
    289	return 0;
    290}
    291
    292typedef struct drm_stats32 {
    293	u32 count;
    294	struct {
    295		u32 value;
    296		enum drm_stat_type type;
    297	} data[15];
    298} drm_stats32_t;
    299
    300static int compat_drm_getstats(struct file *file, unsigned int cmd,
    301			       unsigned long arg)
    302{
    303	drm_stats32_t __user *argp = (void __user *)arg;
    304
    305	/* getstats is defunct, just clear */
    306	if (clear_user(argp, sizeof(drm_stats32_t)))
    307		return -EFAULT;
    308	return 0;
    309}
    310
    311#if IS_ENABLED(CONFIG_DRM_LEGACY)
    312typedef struct drm_buf_desc32 {
    313	int count;		 /* Number of buffers of this size */
    314	int size;		 /* Size in bytes */
    315	int low_mark;		 /* Low water mark */
    316	int high_mark;		 /* High water mark */
    317	int flags;
    318	u32 agp_start;		 /* Start address in the AGP aperture */
    319} drm_buf_desc32_t;
    320
    321static int compat_drm_addbufs(struct file *file, unsigned int cmd,
    322			      unsigned long arg)
    323{
    324	drm_buf_desc32_t __user *argp = (void __user *)arg;
    325	drm_buf_desc32_t desc32;
    326	struct drm_buf_desc desc;
    327	int err;
    328
    329	if (copy_from_user(&desc32, argp, sizeof(drm_buf_desc32_t)))
    330		return -EFAULT;
    331
    332	desc = (struct drm_buf_desc){
    333		desc32.count, desc32.size, desc32.low_mark, desc32.high_mark,
    334		desc32.flags, desc32.agp_start
    335	};
    336
    337	err = drm_ioctl_kernel(file, drm_legacy_addbufs, &desc,
    338				   DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    339	if (err)
    340		return err;
    341
    342	desc32 = (drm_buf_desc32_t){
    343		desc.count, desc.size, desc.low_mark, desc.high_mark,
    344		desc.flags, desc.agp_start
    345	};
    346	if (copy_to_user(argp, &desc32, sizeof(drm_buf_desc32_t)))
    347		return -EFAULT;
    348
    349	return 0;
    350}
    351
    352static int compat_drm_markbufs(struct file *file, unsigned int cmd,
    353			       unsigned long arg)
    354{
    355	drm_buf_desc32_t b32;
    356	drm_buf_desc32_t __user *argp = (void __user *)arg;
    357	struct drm_buf_desc buf;
    358
    359	if (copy_from_user(&b32, argp, sizeof(b32)))
    360		return -EFAULT;
    361
    362	buf.size = b32.size;
    363	buf.low_mark = b32.low_mark;
    364	buf.high_mark = b32.high_mark;
    365
    366	return drm_ioctl_kernel(file, drm_legacy_markbufs, &buf,
    367				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    368}
    369
    370typedef struct drm_buf_info32 {
    371	int count;		/**< Entries in list */
    372	u32 list;
    373} drm_buf_info32_t;
    374
    375static int copy_one_buf32(void *data, int count, struct drm_buf_entry *from)
    376{
    377	drm_buf_info32_t *request = data;
    378	drm_buf_desc32_t __user *to = compat_ptr(request->list);
    379	drm_buf_desc32_t v = {.count = from->buf_count,
    380			      .size = from->buf_size,
    381			      .low_mark = from->low_mark,
    382			      .high_mark = from->high_mark};
    383
    384	if (copy_to_user(to + count, &v, offsetof(drm_buf_desc32_t, flags)))
    385		return -EFAULT;
    386	return 0;
    387}
    388
    389static int drm_legacy_infobufs32(struct drm_device *dev, void *data,
    390			struct drm_file *file_priv)
    391{
    392	drm_buf_info32_t *request = data;
    393
    394	return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf32);
    395}
    396
    397static int compat_drm_infobufs(struct file *file, unsigned int cmd,
    398			       unsigned long arg)
    399{
    400	drm_buf_info32_t req32;
    401	drm_buf_info32_t __user *argp = (void __user *)arg;
    402	int err;
    403
    404	if (copy_from_user(&req32, argp, sizeof(req32)))
    405		return -EFAULT;
    406
    407	if (req32.count < 0)
    408		req32.count = 0;
    409
    410	err = drm_ioctl_kernel(file, drm_legacy_infobufs32, &req32, DRM_AUTH);
    411	if (err)
    412		return err;
    413
    414	if (put_user(req32.count, &argp->count))
    415		return -EFAULT;
    416
    417	return 0;
    418}
    419
    420typedef struct drm_buf_pub32 {
    421	int idx;		/**< Index into the master buffer list */
    422	int total;		/**< Buffer size */
    423	int used;		/**< Amount of buffer in use (for DMA) */
    424	u32 address;		/**< Address of buffer */
    425} drm_buf_pub32_t;
    426
    427typedef struct drm_buf_map32 {
    428	int count;		/**< Length of the buffer list */
    429	u32 virtual;		/**< Mmap'd area in user-virtual */
    430	u32 list;		/**< Buffer information */
    431} drm_buf_map32_t;
    432
    433static int map_one_buf32(void *data, int idx, unsigned long virtual,
    434			struct drm_buf *buf)
    435{
    436	drm_buf_map32_t *request = data;
    437	drm_buf_pub32_t __user *to = compat_ptr(request->list) + idx;
    438	drm_buf_pub32_t v;
    439
    440	v.idx = buf->idx;
    441	v.total = buf->total;
    442	v.used = 0;
    443	v.address = virtual + buf->offset;
    444	if (copy_to_user(to, &v, sizeof(v)))
    445		return -EFAULT;
    446	return 0;
    447}
    448
    449static int drm_legacy_mapbufs32(struct drm_device *dev, void *data,
    450		       struct drm_file *file_priv)
    451{
    452	drm_buf_map32_t *request = data;
    453	void __user *v;
    454	int err = __drm_legacy_mapbufs(dev, data, &request->count,
    455				    &v, map_one_buf32,
    456				    file_priv);
    457	request->virtual = ptr_to_compat(v);
    458	return err;
    459}
    460
    461static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
    462			      unsigned long arg)
    463{
    464	drm_buf_map32_t __user *argp = (void __user *)arg;
    465	drm_buf_map32_t req32;
    466	int err;
    467
    468	if (copy_from_user(&req32, argp, sizeof(req32)))
    469		return -EFAULT;
    470	if (req32.count < 0)
    471		return -EINVAL;
    472
    473	err = drm_ioctl_kernel(file, drm_legacy_mapbufs32, &req32, DRM_AUTH);
    474	if (err)
    475		return err;
    476
    477	if (put_user(req32.count, &argp->count)
    478	    || put_user(req32.virtual, &argp->virtual))
    479		return -EFAULT;
    480
    481	return 0;
    482}
    483
    484typedef struct drm_buf_free32 {
    485	int count;
    486	u32 list;
    487} drm_buf_free32_t;
    488
    489static int compat_drm_freebufs(struct file *file, unsigned int cmd,
    490			       unsigned long arg)
    491{
    492	drm_buf_free32_t req32;
    493	struct drm_buf_free request;
    494	drm_buf_free32_t __user *argp = (void __user *)arg;
    495
    496	if (copy_from_user(&req32, argp, sizeof(req32)))
    497		return -EFAULT;
    498
    499	request.count = req32.count;
    500	request.list = compat_ptr(req32.list);
    501	return drm_ioctl_kernel(file, drm_legacy_freebufs, &request, DRM_AUTH);
    502}
    503
    504typedef struct drm_ctx_priv_map32 {
    505	unsigned int ctx_id;	 /**< Context requesting private mapping */
    506	u32 handle;		/**< Handle of map */
    507} drm_ctx_priv_map32_t;
    508
    509static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
    510				  unsigned long arg)
    511{
    512	drm_ctx_priv_map32_t req32;
    513	struct drm_ctx_priv_map request;
    514	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
    515
    516	if (copy_from_user(&req32, argp, sizeof(req32)))
    517		return -EFAULT;
    518
    519	request.ctx_id = req32.ctx_id;
    520	request.handle = compat_ptr(req32.handle);
    521	return drm_ioctl_kernel(file, drm_legacy_setsareactx, &request,
    522				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    523}
    524
    525static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
    526				  unsigned long arg)
    527{
    528	struct drm_ctx_priv_map req;
    529	drm_ctx_priv_map32_t req32;
    530	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
    531	int err;
    532
    533	if (copy_from_user(&req32, argp, sizeof(req32)))
    534		return -EFAULT;
    535
    536	req.ctx_id = req32.ctx_id;
    537	err = drm_ioctl_kernel(file, drm_legacy_getsareactx, &req, DRM_AUTH);
    538	if (err)
    539		return err;
    540
    541	req32.handle = ptr_to_compat((void __user *)req.handle);
    542	if (copy_to_user(argp, &req32, sizeof(req32)))
    543		return -EFAULT;
    544
    545	return 0;
    546}
    547
    548typedef struct drm_ctx_res32 {
    549	int count;
    550	u32 contexts;
    551} drm_ctx_res32_t;
    552
    553static int compat_drm_resctx(struct file *file, unsigned int cmd,
    554			     unsigned long arg)
    555{
    556	drm_ctx_res32_t __user *argp = (void __user *)arg;
    557	drm_ctx_res32_t res32;
    558	struct drm_ctx_res res;
    559	int err;
    560
    561	if (copy_from_user(&res32, argp, sizeof(res32)))
    562		return -EFAULT;
    563
    564	res.count = res32.count;
    565	res.contexts = compat_ptr(res32.contexts);
    566	err = drm_ioctl_kernel(file, drm_legacy_resctx, &res, DRM_AUTH);
    567	if (err)
    568		return err;
    569
    570	res32.count = res.count;
    571	if (copy_to_user(argp, &res32, sizeof(res32)))
    572		return -EFAULT;
    573
    574	return 0;
    575}
    576
    577typedef struct drm_dma32 {
    578	int context;		  /**< Context handle */
    579	int send_count;		  /**< Number of buffers to send */
    580	u32 send_indices;	  /**< List of handles to buffers */
    581	u32 send_sizes;		  /**< Lengths of data to send */
    582	enum drm_dma_flags flags;		  /**< Flags */
    583	int request_count;	  /**< Number of buffers requested */
    584	int request_size;	  /**< Desired size for buffers */
    585	u32 request_indices;	  /**< Buffer information */
    586	u32 request_sizes;
    587	int granted_count;	  /**< Number of buffers granted */
    588} drm_dma32_t;
    589
    590static int compat_drm_dma(struct file *file, unsigned int cmd,
    591			  unsigned long arg)
    592{
    593	drm_dma32_t d32;
    594	drm_dma32_t __user *argp = (void __user *)arg;
    595	struct drm_dma d;
    596	int err;
    597
    598	if (copy_from_user(&d32, argp, sizeof(d32)))
    599		return -EFAULT;
    600
    601	d.context = d32.context;
    602	d.send_count = d32.send_count;
    603	d.send_indices = compat_ptr(d32.send_indices);
    604	d.send_sizes = compat_ptr(d32.send_sizes);
    605	d.flags = d32.flags;
    606	d.request_count = d32.request_count;
    607	d.request_indices = compat_ptr(d32.request_indices);
    608	d.request_sizes = compat_ptr(d32.request_sizes);
    609	err = drm_ioctl_kernel(file, drm_legacy_dma_ioctl, &d, DRM_AUTH);
    610	if (err)
    611		return err;
    612
    613	if (put_user(d.request_size, &argp->request_size)
    614	    || put_user(d.granted_count, &argp->granted_count))
    615		return -EFAULT;
    616
    617	return 0;
    618}
    619#endif
    620
    621#if IS_ENABLED(CONFIG_DRM_LEGACY)
    622#if IS_ENABLED(CONFIG_AGP)
    623typedef struct drm_agp_mode32 {
    624	u32 mode;	/**< AGP mode */
    625} drm_agp_mode32_t;
    626
    627static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
    628				 unsigned long arg)
    629{
    630	drm_agp_mode32_t __user *argp = (void __user *)arg;
    631	struct drm_agp_mode mode;
    632
    633	if (get_user(mode.mode, &argp->mode))
    634		return -EFAULT;
    635
    636	return drm_ioctl_kernel(file,  drm_legacy_agp_enable_ioctl, &mode,
    637				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    638}
    639
    640typedef struct drm_agp_info32 {
    641	int agp_version_major;
    642	int agp_version_minor;
    643	u32 mode;
    644	u32 aperture_base;	/* physical address */
    645	u32 aperture_size;	/* bytes */
    646	u32 memory_allowed;	/* bytes */
    647	u32 memory_used;
    648
    649	/* PCI information */
    650	unsigned short id_vendor;
    651	unsigned short id_device;
    652} drm_agp_info32_t;
    653
    654static int compat_drm_agp_info(struct file *file, unsigned int cmd,
    655			       unsigned long arg)
    656{
    657	drm_agp_info32_t __user *argp = (void __user *)arg;
    658	drm_agp_info32_t i32;
    659	struct drm_agp_info info;
    660	int err;
    661
    662	err = drm_ioctl_kernel(file, drm_legacy_agp_info_ioctl, &info, DRM_AUTH);
    663	if (err)
    664		return err;
    665
    666	i32.agp_version_major = info.agp_version_major;
    667	i32.agp_version_minor = info.agp_version_minor;
    668	i32.mode = info.mode;
    669	i32.aperture_base = info.aperture_base;
    670	i32.aperture_size = info.aperture_size;
    671	i32.memory_allowed = info.memory_allowed;
    672	i32.memory_used = info.memory_used;
    673	i32.id_vendor = info.id_vendor;
    674	i32.id_device = info.id_device;
    675	if (copy_to_user(argp, &i32, sizeof(i32)))
    676		return -EFAULT;
    677
    678	return 0;
    679}
    680
    681typedef struct drm_agp_buffer32 {
    682	u32 size;	/**< In bytes -- will round to page boundary */
    683	u32 handle;	/**< Used for binding / unbinding */
    684	u32 type;	/**< Type of memory to allocate */
    685	u32 physical;	/**< Physical used by i810 */
    686} drm_agp_buffer32_t;
    687
    688static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
    689				unsigned long arg)
    690{
    691	drm_agp_buffer32_t __user *argp = (void __user *)arg;
    692	drm_agp_buffer32_t req32;
    693	struct drm_agp_buffer request;
    694	int err;
    695
    696	if (copy_from_user(&req32, argp, sizeof(req32)))
    697		return -EFAULT;
    698
    699	request.size = req32.size;
    700	request.type = req32.type;
    701	err = drm_ioctl_kernel(file, drm_legacy_agp_alloc_ioctl, &request,
    702				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    703	if (err)
    704		return err;
    705
    706	req32.handle = request.handle;
    707	req32.physical = request.physical;
    708	if (copy_to_user(argp, &req32, sizeof(req32))) {
    709		drm_ioctl_kernel(file, drm_legacy_agp_free_ioctl, &request,
    710				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    711		return -EFAULT;
    712	}
    713
    714	return 0;
    715}
    716
    717static int compat_drm_agp_free(struct file *file, unsigned int cmd,
    718			       unsigned long arg)
    719{
    720	drm_agp_buffer32_t __user *argp = (void __user *)arg;
    721	struct drm_agp_buffer request;
    722
    723	if (get_user(request.handle, &argp->handle))
    724		return -EFAULT;
    725
    726	return drm_ioctl_kernel(file, drm_legacy_agp_free_ioctl, &request,
    727				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    728}
    729
    730typedef struct drm_agp_binding32 {
    731	u32 handle;	/**< From drm_agp_buffer */
    732	u32 offset;	/**< In bytes -- will round to page boundary */
    733} drm_agp_binding32_t;
    734
    735static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
    736			       unsigned long arg)
    737{
    738	drm_agp_binding32_t __user *argp = (void __user *)arg;
    739	drm_agp_binding32_t req32;
    740	struct drm_agp_binding request;
    741
    742	if (copy_from_user(&req32, argp, sizeof(req32)))
    743		return -EFAULT;
    744
    745	request.handle = req32.handle;
    746	request.offset = req32.offset;
    747	return drm_ioctl_kernel(file, drm_legacy_agp_bind_ioctl, &request,
    748				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    749}
    750
    751static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
    752				 unsigned long arg)
    753{
    754	drm_agp_binding32_t __user *argp = (void __user *)arg;
    755	struct drm_agp_binding request;
    756
    757	if (get_user(request.handle, &argp->handle))
    758		return -EFAULT;
    759
    760	return drm_ioctl_kernel(file, drm_legacy_agp_unbind_ioctl, &request,
    761				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    762}
    763#endif /* CONFIG_AGP */
    764
    765typedef struct drm_scatter_gather32 {
    766	u32 size;	/**< In bytes -- will round to page boundary */
    767	u32 handle;	/**< Used for mapping / unmapping */
    768} drm_scatter_gather32_t;
    769
    770static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
    771			       unsigned long arg)
    772{
    773	drm_scatter_gather32_t __user *argp = (void __user *)arg;
    774	struct drm_scatter_gather request;
    775	int err;
    776
    777	if (get_user(request.size, &argp->size))
    778		return -EFAULT;
    779
    780	err = drm_ioctl_kernel(file, drm_legacy_sg_alloc, &request,
    781				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    782	if (err)
    783		return err;
    784
    785	/* XXX not sure about the handle conversion here... */
    786	if (put_user(request.handle >> PAGE_SHIFT, &argp->handle))
    787		return -EFAULT;
    788
    789	return 0;
    790}
    791
    792static int compat_drm_sg_free(struct file *file, unsigned int cmd,
    793			      unsigned long arg)
    794{
    795	drm_scatter_gather32_t __user *argp = (void __user *)arg;
    796	struct drm_scatter_gather request;
    797	unsigned long x;
    798
    799	if (get_user(x, &argp->handle))
    800		return -EFAULT;
    801	request.handle = x << PAGE_SHIFT;
    802	return drm_ioctl_kernel(file, drm_legacy_sg_free, &request,
    803				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
    804}
    805#endif
    806#if defined(CONFIG_X86)
    807typedef struct drm_update_draw32 {
    808	drm_drawable_t handle;
    809	unsigned int type;
    810	unsigned int num;
    811	/* 64-bit version has a 32-bit pad here */
    812	u64 data;	/**< Pointer */
    813} __attribute__((packed)) drm_update_draw32_t;
    814
    815static int compat_drm_update_draw(struct file *file, unsigned int cmd,
    816				  unsigned long arg)
    817{
    818	/* update_draw is defunct */
    819	return 0;
    820}
    821#endif
    822
    823struct drm_wait_vblank_request32 {
    824	enum drm_vblank_seq_type type;
    825	unsigned int sequence;
    826	u32 signal;
    827};
    828
    829struct drm_wait_vblank_reply32 {
    830	enum drm_vblank_seq_type type;
    831	unsigned int sequence;
    832	s32 tval_sec;
    833	s32 tval_usec;
    834};
    835
    836typedef union drm_wait_vblank32 {
    837	struct drm_wait_vblank_request32 request;
    838	struct drm_wait_vblank_reply32 reply;
    839} drm_wait_vblank32_t;
    840
    841static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
    842				  unsigned long arg)
    843{
    844	drm_wait_vblank32_t __user *argp = (void __user *)arg;
    845	drm_wait_vblank32_t req32;
    846	union drm_wait_vblank req;
    847	int err;
    848
    849	if (copy_from_user(&req32, argp, sizeof(req32)))
    850		return -EFAULT;
    851
    852	memset(&req, 0, sizeof(req));
    853
    854	req.request.type = req32.request.type;
    855	req.request.sequence = req32.request.sequence;
    856	req.request.signal = req32.request.signal;
    857	err = drm_ioctl_kernel(file, drm_wait_vblank_ioctl, &req, DRM_UNLOCKED);
    858
    859	req32.reply.type = req.reply.type;
    860	req32.reply.sequence = req.reply.sequence;
    861	req32.reply.tval_sec = req.reply.tval_sec;
    862	req32.reply.tval_usec = req.reply.tval_usec;
    863	if (copy_to_user(argp, &req32, sizeof(req32)))
    864		return -EFAULT;
    865
    866	return err;
    867}
    868
    869#if defined(CONFIG_X86)
    870typedef struct drm_mode_fb_cmd232 {
    871	u32 fb_id;
    872	u32 width;
    873	u32 height;
    874	u32 pixel_format;
    875	u32 flags;
    876	u32 handles[4];
    877	u32 pitches[4];
    878	u32 offsets[4];
    879	u64 modifier[4];
    880} __attribute__((packed)) drm_mode_fb_cmd232_t;
    881
    882static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd,
    883				  unsigned long arg)
    884{
    885	struct drm_mode_fb_cmd232 __user *argp = (void __user *)arg;
    886	struct drm_mode_fb_cmd2 req64;
    887	int err;
    888
    889	memset(&req64, 0, sizeof(req64));
    890
    891	if (copy_from_user(&req64, argp,
    892			   offsetof(drm_mode_fb_cmd232_t, modifier)))
    893		return -EFAULT;
    894
    895	if (copy_from_user(&req64.modifier, &argp->modifier,
    896			   sizeof(req64.modifier)))
    897		return -EFAULT;
    898
    899	err = drm_ioctl_kernel(file, drm_mode_addfb2, &req64, 0);
    900	if (err)
    901		return err;
    902
    903	if (put_user(req64.fb_id, &argp->fb_id))
    904		return -EFAULT;
    905
    906	return 0;
    907}
    908#endif
    909
    910static struct {
    911	drm_ioctl_compat_t *fn;
    912	char *name;
    913} drm_compat_ioctls[] = {
    914#define DRM_IOCTL32_DEF(n, f) [DRM_IOCTL_NR(n##32)] = {.fn = f, .name = #n}
    915	DRM_IOCTL32_DEF(DRM_IOCTL_VERSION, compat_drm_version),
    916	DRM_IOCTL32_DEF(DRM_IOCTL_GET_UNIQUE, compat_drm_getunique),
    917#if IS_ENABLED(CONFIG_DRM_LEGACY)
    918	DRM_IOCTL32_DEF(DRM_IOCTL_GET_MAP, compat_drm_getmap),
    919#endif
    920	DRM_IOCTL32_DEF(DRM_IOCTL_GET_CLIENT, compat_drm_getclient),
    921	DRM_IOCTL32_DEF(DRM_IOCTL_GET_STATS, compat_drm_getstats),
    922	DRM_IOCTL32_DEF(DRM_IOCTL_SET_UNIQUE, compat_drm_setunique),
    923#if IS_ENABLED(CONFIG_DRM_LEGACY)
    924	DRM_IOCTL32_DEF(DRM_IOCTL_ADD_MAP, compat_drm_addmap),
    925	DRM_IOCTL32_DEF(DRM_IOCTL_ADD_BUFS, compat_drm_addbufs),
    926	DRM_IOCTL32_DEF(DRM_IOCTL_MARK_BUFS, compat_drm_markbufs),
    927	DRM_IOCTL32_DEF(DRM_IOCTL_INFO_BUFS, compat_drm_infobufs),
    928	DRM_IOCTL32_DEF(DRM_IOCTL_MAP_BUFS, compat_drm_mapbufs),
    929	DRM_IOCTL32_DEF(DRM_IOCTL_FREE_BUFS, compat_drm_freebufs),
    930	DRM_IOCTL32_DEF(DRM_IOCTL_RM_MAP, compat_drm_rmmap),
    931	DRM_IOCTL32_DEF(DRM_IOCTL_SET_SAREA_CTX, compat_drm_setsareactx),
    932	DRM_IOCTL32_DEF(DRM_IOCTL_GET_SAREA_CTX, compat_drm_getsareactx),
    933	DRM_IOCTL32_DEF(DRM_IOCTL_RES_CTX, compat_drm_resctx),
    934	DRM_IOCTL32_DEF(DRM_IOCTL_DMA, compat_drm_dma),
    935#if IS_ENABLED(CONFIG_AGP)
    936	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ENABLE, compat_drm_agp_enable),
    937	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_INFO, compat_drm_agp_info),
    938	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ALLOC, compat_drm_agp_alloc),
    939	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_FREE, compat_drm_agp_free),
    940	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_BIND, compat_drm_agp_bind),
    941	DRM_IOCTL32_DEF(DRM_IOCTL_AGP_UNBIND, compat_drm_agp_unbind),
    942#endif
    943#endif
    944#if IS_ENABLED(CONFIG_DRM_LEGACY)
    945	DRM_IOCTL32_DEF(DRM_IOCTL_SG_ALLOC, compat_drm_sg_alloc),
    946	DRM_IOCTL32_DEF(DRM_IOCTL_SG_FREE, compat_drm_sg_free),
    947#endif
    948#if defined(CONFIG_X86) || defined(CONFIG_IA64)
    949	DRM_IOCTL32_DEF(DRM_IOCTL_UPDATE_DRAW, compat_drm_update_draw),
    950#endif
    951	DRM_IOCTL32_DEF(DRM_IOCTL_WAIT_VBLANK, compat_drm_wait_vblank),
    952#if defined(CONFIG_X86) || defined(CONFIG_IA64)
    953	DRM_IOCTL32_DEF(DRM_IOCTL_MODE_ADDFB2, compat_drm_mode_addfb2),
    954#endif
    955};
    956
    957/**
    958 * drm_compat_ioctl - 32bit IOCTL compatibility handler for DRM drivers
    959 * @filp: file this ioctl is called on
    960 * @cmd: ioctl cmd number
    961 * @arg: user argument
    962 *
    963 * Compatibility handler for 32 bit userspace running on 64 kernels. All actual
    964 * IOCTL handling is forwarded to drm_ioctl(), while marshalling structures as
    965 * appropriate. Note that this only handles DRM core IOCTLs, if the driver has
    966 * botched IOCTL itself, it must handle those by wrapping this function.
    967 *
    968 * Returns:
    969 * Zero on success, negative error code on failure.
    970 */
    971long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    972{
    973	unsigned int nr = DRM_IOCTL_NR(cmd);
    974	struct drm_file *file_priv = filp->private_data;
    975	drm_ioctl_compat_t *fn;
    976	int ret;
    977
    978	/* Assume that ioctls without an explicit compat routine will just
    979	 * work.  This may not always be a good assumption, but it's better
    980	 * than always failing.
    981	 */
    982	if (nr >= ARRAY_SIZE(drm_compat_ioctls))
    983		return drm_ioctl(filp, cmd, arg);
    984
    985	fn = drm_compat_ioctls[nr].fn;
    986	if (!fn)
    987		return drm_ioctl(filp, cmd, arg);
    988
    989	DRM_DEBUG("comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, %s\n",
    990		  current->comm, task_pid_nr(current),
    991		  (long)old_encode_dev(file_priv->minor->kdev->devt),
    992		  file_priv->authenticated,
    993		  drm_compat_ioctls[nr].name);
    994	ret = (*fn)(filp, cmd, arg);
    995	if (ret)
    996		DRM_DEBUG("ret = %d\n", ret);
    997	return ret;
    998}
    999EXPORT_SYMBOL(drm_compat_ioctl);