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 
32 #include "drmP.h"
33 #include "drm_core.h"
34 
35 #define DRM_IOCTL_VERSION32		DRM_IOWR(0x00, drm_version32_t)
36 #define DRM_IOCTL_GET_UNIQUE32		DRM_IOWR(0x01, drm_unique32_t)
37 #define DRM_IOCTL_GET_MAP32		DRM_IOWR(0x04, drm_map32_t)
38 #define DRM_IOCTL_GET_CLIENT32		DRM_IOWR(0x05, drm_client32_t)
39 #define DRM_IOCTL_GET_STATS32		DRM_IOR( 0x06, drm_stats32_t)
40 
41 #define DRM_IOCTL_SET_UNIQUE32		DRM_IOW( 0x10, drm_unique32_t)
42 #define DRM_IOCTL_ADD_MAP32		DRM_IOWR(0x15, drm_map32_t)
43 #define DRM_IOCTL_ADD_BUFS32		DRM_IOWR(0x16, drm_buf_desc32_t)
44 #define DRM_IOCTL_MARK_BUFS32		DRM_IOW( 0x17, drm_buf_desc32_t)
45 #define DRM_IOCTL_INFO_BUFS32		DRM_IOWR(0x18, drm_buf_info32_t)
46 #define DRM_IOCTL_MAP_BUFS32		DRM_IOWR(0x19, drm_buf_map32_t)
47 #define DRM_IOCTL_FREE_BUFS32		DRM_IOW( 0x1a, drm_buf_free32_t)
48 
49 #define DRM_IOCTL_RM_MAP32		DRM_IOW( 0x1b, drm_map32_t)
50 
51 #define DRM_IOCTL_SET_SAREA_CTX32	DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
52 #define DRM_IOCTL_GET_SAREA_CTX32	DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
53 
54 #define DRM_IOCTL_RES_CTX32		DRM_IOWR(0x26, drm_ctx_res32_t)
55 #define DRM_IOCTL_DMA32			DRM_IOWR(0x29, drm_dma32_t)
56 
57 #define DRM_IOCTL_AGP_ENABLE32		DRM_IOW( 0x32, drm_agp_mode32_t)
58 #define DRM_IOCTL_AGP_INFO32		DRM_IOR( 0x33, drm_agp_info32_t)
59 #define DRM_IOCTL_AGP_ALLOC32		DRM_IOWR(0x34, drm_agp_buffer32_t)
60 #define DRM_IOCTL_AGP_FREE32		DRM_IOW( 0x35, drm_agp_buffer32_t)
61 #define DRM_IOCTL_AGP_BIND32		DRM_IOW( 0x36, drm_agp_binding32_t)
62 #define DRM_IOCTL_AGP_UNBIND32		DRM_IOW( 0x37, drm_agp_binding32_t)
63 
64 #define DRM_IOCTL_SG_ALLOC32		DRM_IOW( 0x38, drm_scatter_gather32_t)
65 #define DRM_IOCTL_SG_FREE32		DRM_IOW( 0x39, drm_scatter_gather32_t)
66 
67 #define DRM_IOCTL_UPDATE_DRAW32		DRM_IOW( 0x3f, drm_update_draw32_t)
68 
69 #define DRM_IOCTL_WAIT_VBLANK32		DRM_IOWR(0x3a, drm_wait_vblank32_t)
70 
71 typedef struct drm_version_32 {
72 	int version_major;	  /**< Major version */
73 	int version_minor;	  /**< Minor version */
74 	int version_patchlevel;	   /**< Patch level */
75 	u32 name_len;		  /**< Length of name buffer */
76 	u32 name;		  /**< Name of driver */
77 	u32 date_len;		  /**< Length of date buffer */
78 	u32 date;		  /**< User-space buffer to hold date */
79 	u32 desc_len;		  /**< Length of desc buffer */
80 	u32 desc;		  /**< User-space buffer to hold desc */
81 } drm_version32_t;
82 
compat_drm_version(struct file * file,unsigned int cmd,unsigned long arg)83 static int compat_drm_version(struct file *file, unsigned int cmd,
84 			      unsigned long arg)
85 {
86 	drm_version32_t v32;
87 	struct drm_version __user *version;
88 	int err;
89 
90 	if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
91 		return -EFAULT;
92 
93 	version = compat_alloc_user_space(sizeof(*version));
94 	if (!access_ok(VERIFY_WRITE, version, sizeof(*version)))
95 		return -EFAULT;
96 	if (__put_user(v32.name_len, &version->name_len)
97 	    || __put_user((void __user *)(unsigned long)v32.name,
98 			  &version->name)
99 	    || __put_user(v32.date_len, &version->date_len)
100 	    || __put_user((void __user *)(unsigned long)v32.date,
101 			  &version->date)
102 	    || __put_user(v32.desc_len, &version->desc_len)
103 	    || __put_user((void __user *)(unsigned long)v32.desc,
104 			  &version->desc))
105 		return -EFAULT;
106 
107 	err = drm_ioctl(file,
108 			DRM_IOCTL_VERSION, (unsigned long)version);
109 	if (err)
110 		return err;
111 
112 	if (__get_user(v32.version_major, &version->version_major)
113 	    || __get_user(v32.version_minor, &version->version_minor)
114 	    || __get_user(v32.version_patchlevel, &version->version_patchlevel)
115 	    || __get_user(v32.name_len, &version->name_len)
116 	    || __get_user(v32.date_len, &version->date_len)
117 	    || __get_user(v32.desc_len, &version->desc_len))
118 		return -EFAULT;
119 
120 	if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
121 		return -EFAULT;
122 	return 0;
123 }
124 
125 typedef struct drm_unique32 {
126 	u32 unique_len;	/**< Length of unique */
127 	u32 unique;	/**< Unique name for driver instantiation */
128 } drm_unique32_t;
129 
compat_drm_getunique(struct file * file,unsigned int cmd,unsigned long arg)130 static int compat_drm_getunique(struct file *file, unsigned int cmd,
131 				unsigned long arg)
132 {
133 	drm_unique32_t uq32;
134 	struct drm_unique __user *u;
135 	int err;
136 
137 	if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
138 		return -EFAULT;
139 
140 	u = compat_alloc_user_space(sizeof(*u));
141 	if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
142 		return -EFAULT;
143 	if (__put_user(uq32.unique_len, &u->unique_len)
144 	    || __put_user((void __user *)(unsigned long)uq32.unique,
145 			  &u->unique))
146 		return -EFAULT;
147 
148 	err = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
149 	if (err)
150 		return err;
151 
152 	if (__get_user(uq32.unique_len, &u->unique_len))
153 		return -EFAULT;
154 	if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
155 		return -EFAULT;
156 	return 0;
157 }
158 
compat_drm_setunique(struct file * file,unsigned int cmd,unsigned long arg)159 static int compat_drm_setunique(struct file *file, unsigned int cmd,
160 				unsigned long arg)
161 {
162 	drm_unique32_t uq32;
163 	struct drm_unique __user *u;
164 
165 	if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
166 		return -EFAULT;
167 
168 	u = compat_alloc_user_space(sizeof(*u));
169 	if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
170 		return -EFAULT;
171 	if (__put_user(uq32.unique_len, &u->unique_len)
172 	    || __put_user((void __user *)(unsigned long)uq32.unique,
173 			  &u->unique))
174 		return -EFAULT;
175 
176 	return drm_ioctl(file, DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
177 }
178 
179 typedef struct drm_map32 {
180 	u32 offset;		/**< Requested physical address (0 for SAREA)*/
181 	u32 size;		/**< Requested physical size (bytes) */
182 	enum drm_map_type type;	/**< Type of memory to map */
183 	enum drm_map_flags flags;	/**< Flags */
184 	u32 handle;		/**< User-space: "Handle" to pass to mmap() */
185 	int mtrr;		/**< MTRR slot used */
186 } drm_map32_t;
187 
compat_drm_getmap(struct file * file,unsigned int cmd,unsigned long arg)188 static int compat_drm_getmap(struct file *file, unsigned int cmd,
189 			     unsigned long arg)
190 {
191 	drm_map32_t __user *argp = (void __user *)arg;
192 	drm_map32_t m32;
193 	struct drm_map __user *map;
194 	int idx, err;
195 	void *handle;
196 
197 	if (get_user(idx, &argp->offset))
198 		return -EFAULT;
199 
200 	map = compat_alloc_user_space(sizeof(*map));
201 	if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
202 		return -EFAULT;
203 	if (__put_user(idx, &map->offset))
204 		return -EFAULT;
205 
206 	err = drm_ioctl(file, DRM_IOCTL_GET_MAP, (unsigned long)map);
207 	if (err)
208 		return err;
209 
210 	if (__get_user(m32.offset, &map->offset)
211 	    || __get_user(m32.size, &map->size)
212 	    || __get_user(m32.type, &map->type)
213 	    || __get_user(m32.flags, &map->flags)
214 	    || __get_user(handle, &map->handle)
215 	    || __get_user(m32.mtrr, &map->mtrr))
216 		return -EFAULT;
217 
218 	m32.handle = (unsigned long)handle;
219 	if (copy_to_user(argp, &m32, sizeof(m32)))
220 		return -EFAULT;
221 	return 0;
222 
223 }
224 
compat_drm_addmap(struct file * file,unsigned int cmd,unsigned long arg)225 static int compat_drm_addmap(struct file *file, unsigned int cmd,
226 			     unsigned long arg)
227 {
228 	drm_map32_t __user *argp = (void __user *)arg;
229 	drm_map32_t m32;
230 	struct drm_map __user *map;
231 	int err;
232 	void *handle;
233 
234 	if (copy_from_user(&m32, argp, sizeof(m32)))
235 		return -EFAULT;
236 
237 	map = compat_alloc_user_space(sizeof(*map));
238 	if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
239 		return -EFAULT;
240 	if (__put_user(m32.offset, &map->offset)
241 	    || __put_user(m32.size, &map->size)
242 	    || __put_user(m32.type, &map->type)
243 	    || __put_user(m32.flags, &map->flags))
244 		return -EFAULT;
245 
246 	err = drm_ioctl(file, DRM_IOCTL_ADD_MAP, (unsigned long)map);
247 	if (err)
248 		return err;
249 
250 	if (__get_user(m32.offset, &map->offset)
251 	    || __get_user(m32.mtrr, &map->mtrr)
252 	    || __get_user(handle, &map->handle))
253 		return -EFAULT;
254 
255 	m32.handle = (unsigned long)handle;
256 	if (m32.handle != (unsigned long)handle && printk_ratelimit())
257 		printk(KERN_ERR "compat_drm_addmap truncated handle"
258 		       " %p for type %d offset %x\n",
259 		       handle, m32.type, m32.offset);
260 
261 	if (copy_to_user(argp, &m32, sizeof(m32)))
262 		return -EFAULT;
263 
264 	return 0;
265 }
266 
compat_drm_rmmap(struct file * file,unsigned int cmd,unsigned long arg)267 static int compat_drm_rmmap(struct file *file, unsigned int cmd,
268 			    unsigned long arg)
269 {
270 	drm_map32_t __user *argp = (void __user *)arg;
271 	struct drm_map __user *map;
272 	u32 handle;
273 
274 	if (get_user(handle, &argp->handle))
275 		return -EFAULT;
276 
277 	map = compat_alloc_user_space(sizeof(*map));
278 	if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
279 		return -EFAULT;
280 	if (__put_user((void *)(unsigned long)handle, &map->handle))
281 		return -EFAULT;
282 
283 	return drm_ioctl(file, DRM_IOCTL_RM_MAP, (unsigned long)map);
284 }
285 
286 typedef struct drm_client32 {
287 	int idx;	/**< Which client desired? */
288 	int auth;	/**< Is client authenticated? */
289 	u32 pid;	/**< Process ID */
290 	u32 uid;	/**< User ID */
291 	u32 magic;	/**< Magic */
292 	u32 iocs;	/**< Ioctl count */
293 } drm_client32_t;
294 
compat_drm_getclient(struct file * file,unsigned int cmd,unsigned long arg)295 static int compat_drm_getclient(struct file *file, unsigned int cmd,
296 				unsigned long arg)
297 {
298 	drm_client32_t c32;
299 	drm_client32_t __user *argp = (void __user *)arg;
300 	struct drm_client __user *client;
301 	int idx, err;
302 
303 	if (get_user(idx, &argp->idx))
304 		return -EFAULT;
305 
306 	client = compat_alloc_user_space(sizeof(*client));
307 	if (!access_ok(VERIFY_WRITE, client, sizeof(*client)))
308 		return -EFAULT;
309 	if (__put_user(idx, &client->idx))
310 		return -EFAULT;
311 
312 	err = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, (unsigned long)client);
313 	if (err)
314 		return err;
315 
316 	if (__get_user(c32.auth, &client->auth)
317 	    || __get_user(c32.pid, &client->pid)
318 	    || __get_user(c32.uid, &client->uid)
319 	    || __get_user(c32.magic, &client->magic)
320 	    || __get_user(c32.iocs, &client->iocs))
321 		return -EFAULT;
322 
323 	if (copy_to_user(argp, &c32, sizeof(c32)))
324 		return -EFAULT;
325 	return 0;
326 }
327 
328 typedef struct drm_stats32 {
329 	u32 count;
330 	struct {
331 		u32 value;
332 		enum drm_stat_type type;
333 	} data[15];
334 } drm_stats32_t;
335 
compat_drm_getstats(struct file * file,unsigned int cmd,unsigned long arg)336 static int compat_drm_getstats(struct file *file, unsigned int cmd,
337 			       unsigned long arg)
338 {
339 	drm_stats32_t s32;
340 	drm_stats32_t __user *argp = (void __user *)arg;
341 	struct drm_stats __user *stats;
342 	int i, err;
343 
344 	stats = compat_alloc_user_space(sizeof(*stats));
345 	if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
346 		return -EFAULT;
347 
348 	err = drm_ioctl(file, DRM_IOCTL_GET_STATS, (unsigned long)stats);
349 	if (err)
350 		return err;
351 
352 	if (__get_user(s32.count, &stats->count))
353 		return -EFAULT;
354 	for (i = 0; i < 15; ++i)
355 		if (__get_user(s32.data[i].value, &stats->data[i].value)
356 		    || __get_user(s32.data[i].type, &stats->data[i].type))
357 			return -EFAULT;
358 
359 	if (copy_to_user(argp, &s32, sizeof(s32)))
360 		return -EFAULT;
361 	return 0;
362 }
363 
364 typedef struct drm_buf_desc32 {
365 	int count;		 /**< Number of buffers of this size */
366 	int size;		 /**< Size in bytes */
367 	int low_mark;		 /**< Low water mark */
368 	int high_mark;		 /**< High water mark */
369 	int flags;
370 	u32 agp_start;		 /**< Start address in the AGP aperture */
371 } drm_buf_desc32_t;
372 
compat_drm_addbufs(struct file * file,unsigned int cmd,unsigned long arg)373 static int compat_drm_addbufs(struct file *file, unsigned int cmd,
374 			      unsigned long arg)
375 {
376 	drm_buf_desc32_t __user *argp = (void __user *)arg;
377 	struct drm_buf_desc __user *buf;
378 	int err;
379 	unsigned long agp_start;
380 
381 	buf = compat_alloc_user_space(sizeof(*buf));
382 	if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf))
383 	    || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)))
384 		return -EFAULT;
385 
386 	if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start))
387 	    || __get_user(agp_start, &argp->agp_start)
388 	    || __put_user(agp_start, &buf->agp_start))
389 		return -EFAULT;
390 
391 	err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
392 	if (err)
393 		return err;
394 
395 	if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start))
396 	    || __get_user(agp_start, &buf->agp_start)
397 	    || __put_user(agp_start, &argp->agp_start))
398 		return -EFAULT;
399 
400 	return 0;
401 }
402 
compat_drm_markbufs(struct file * file,unsigned int cmd,unsigned long arg)403 static int compat_drm_markbufs(struct file *file, unsigned int cmd,
404 			       unsigned long arg)
405 {
406 	drm_buf_desc32_t b32;
407 	drm_buf_desc32_t __user *argp = (void __user *)arg;
408 	struct drm_buf_desc __user *buf;
409 
410 	if (copy_from_user(&b32, argp, sizeof(b32)))
411 		return -EFAULT;
412 
413 	buf = compat_alloc_user_space(sizeof(*buf));
414 	if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)))
415 		return -EFAULT;
416 
417 	if (__put_user(b32.size, &buf->size)
418 	    || __put_user(b32.low_mark, &buf->low_mark)
419 	    || __put_user(b32.high_mark, &buf->high_mark))
420 		return -EFAULT;
421 
422 	return drm_ioctl(file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
423 }
424 
425 typedef struct drm_buf_info32 {
426 	int count;		/**< Entries in list */
427 	u32 list;
428 } drm_buf_info32_t;
429 
compat_drm_infobufs(struct file * file,unsigned int cmd,unsigned long arg)430 static int compat_drm_infobufs(struct file *file, unsigned int cmd,
431 			       unsigned long arg)
432 {
433 	drm_buf_info32_t req32;
434 	drm_buf_info32_t __user *argp = (void __user *)arg;
435 	drm_buf_desc32_t __user *to;
436 	struct drm_buf_info __user *request;
437 	struct drm_buf_desc __user *list;
438 	size_t nbytes;
439 	int i, err;
440 	int count, actual;
441 
442 	if (copy_from_user(&req32, argp, sizeof(req32)))
443 		return -EFAULT;
444 
445 	count = req32.count;
446 	to = (drm_buf_desc32_t __user *) (unsigned long)req32.list;
447 	if (count < 0)
448 		count = 0;
449 	if (count > 0
450 	    && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
451 		return -EFAULT;
452 
453 	nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
454 	request = compat_alloc_user_space(nbytes);
455 	if (!access_ok(VERIFY_WRITE, request, nbytes))
456 		return -EFAULT;
457 	list = (struct drm_buf_desc *) (request + 1);
458 
459 	if (__put_user(count, &request->count)
460 	    || __put_user(list, &request->list))
461 		return -EFAULT;
462 
463 	err = drm_ioctl(file, DRM_IOCTL_INFO_BUFS, (unsigned long)request);
464 	if (err)
465 		return err;
466 
467 	if (__get_user(actual, &request->count))
468 		return -EFAULT;
469 	if (count >= actual)
470 		for (i = 0; i < actual; ++i)
471 			if (__copy_in_user(&to[i], &list[i],
472 					   offsetof(struct drm_buf_desc, flags)))
473 				return -EFAULT;
474 
475 	if (__put_user(actual, &argp->count))
476 		return -EFAULT;
477 
478 	return 0;
479 }
480 
481 typedef struct drm_buf_pub32 {
482 	int idx;		/**< Index into the master buffer list */
483 	int total;		/**< Buffer size */
484 	int used;		/**< Amount of buffer in use (for DMA) */
485 	u32 address;		/**< Address of buffer */
486 } drm_buf_pub32_t;
487 
488 typedef struct drm_buf_map32 {
489 	int count;		/**< Length of the buffer list */
490 	u32 virtual;		/**< Mmap'd area in user-virtual */
491 	u32 list;		/**< Buffer information */
492 } drm_buf_map32_t;
493 
compat_drm_mapbufs(struct file * file,unsigned int cmd,unsigned long arg)494 static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
495 			      unsigned long arg)
496 {
497 	drm_buf_map32_t __user *argp = (void __user *)arg;
498 	drm_buf_map32_t req32;
499 	drm_buf_pub32_t __user *list32;
500 	struct drm_buf_map __user *request;
501 	struct drm_buf_pub __user *list;
502 	int i, err;
503 	int count, actual;
504 	size_t nbytes;
505 	void __user *addr;
506 
507 	if (copy_from_user(&req32, argp, sizeof(req32)))
508 		return -EFAULT;
509 	count = req32.count;
510 	list32 = (void __user *)(unsigned long)req32.list;
511 
512 	if (count < 0)
513 		return -EINVAL;
514 	nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
515 	request = compat_alloc_user_space(nbytes);
516 	if (!access_ok(VERIFY_WRITE, request, nbytes))
517 		return -EFAULT;
518 	list = (struct drm_buf_pub *) (request + 1);
519 
520 	if (__put_user(count, &request->count)
521 	    || __put_user(list, &request->list))
522 		return -EFAULT;
523 
524 	err = drm_ioctl(file, DRM_IOCTL_MAP_BUFS, (unsigned long)request);
525 	if (err)
526 		return err;
527 
528 	if (__get_user(actual, &request->count))
529 		return -EFAULT;
530 	if (count >= actual)
531 		for (i = 0; i < actual; ++i)
532 			if (__copy_in_user(&list32[i], &list[i],
533 					   offsetof(struct drm_buf_pub, address))
534 			    || __get_user(addr, &list[i].address)
535 			    || __put_user((unsigned long)addr,
536 					  &list32[i].address))
537 				return -EFAULT;
538 
539 	if (__put_user(actual, &argp->count)
540 	    || __get_user(addr, &request->virtual)
541 	    || __put_user((unsigned long)addr, &argp->virtual))
542 		return -EFAULT;
543 
544 	return 0;
545 }
546 
547 typedef struct drm_buf_free32 {
548 	int count;
549 	u32 list;
550 } drm_buf_free32_t;
551 
compat_drm_freebufs(struct file * file,unsigned int cmd,unsigned long arg)552 static int compat_drm_freebufs(struct file *file, unsigned int cmd,
553 			       unsigned long arg)
554 {
555 	drm_buf_free32_t req32;
556 	struct drm_buf_free __user *request;
557 	drm_buf_free32_t __user *argp = (void __user *)arg;
558 
559 	if (copy_from_user(&req32, argp, sizeof(req32)))
560 		return -EFAULT;
561 
562 	request = compat_alloc_user_space(sizeof(*request));
563 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
564 		return -EFAULT;
565 	if (__put_user(req32.count, &request->count)
566 	    || __put_user((int __user *)(unsigned long)req32.list,
567 			  &request->list))
568 		return -EFAULT;
569 
570 	return drm_ioctl(file, DRM_IOCTL_FREE_BUFS, (unsigned long)request);
571 }
572 
573 typedef struct drm_ctx_priv_map32 {
574 	unsigned int ctx_id;	 /**< Context requesting private mapping */
575 	u32 handle;		/**< Handle of map */
576 } drm_ctx_priv_map32_t;
577 
compat_drm_setsareactx(struct file * file,unsigned int cmd,unsigned long arg)578 static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
579 				  unsigned long arg)
580 {
581 	drm_ctx_priv_map32_t req32;
582 	struct drm_ctx_priv_map __user *request;
583 	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
584 
585 	if (copy_from_user(&req32, argp, sizeof(req32)))
586 		return -EFAULT;
587 
588 	request = compat_alloc_user_space(sizeof(*request));
589 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
590 		return -EFAULT;
591 	if (__put_user(req32.ctx_id, &request->ctx_id)
592 	    || __put_user((void *)(unsigned long)req32.handle,
593 			  &request->handle))
594 		return -EFAULT;
595 
596 	return drm_ioctl(file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
597 }
598 
compat_drm_getsareactx(struct file * file,unsigned int cmd,unsigned long arg)599 static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
600 				  unsigned long arg)
601 {
602 	struct drm_ctx_priv_map __user *request;
603 	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
604 	int err;
605 	unsigned int ctx_id;
606 	void *handle;
607 
608 	if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp))
609 	    || __get_user(ctx_id, &argp->ctx_id))
610 		return -EFAULT;
611 
612 	request = compat_alloc_user_space(sizeof(*request));
613 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
614 		return -EFAULT;
615 	if (__put_user(ctx_id, &request->ctx_id))
616 		return -EFAULT;
617 
618 	err = drm_ioctl(file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
619 	if (err)
620 		return err;
621 
622 	if (__get_user(handle, &request->handle)
623 	    || __put_user((unsigned long)handle, &argp->handle))
624 		return -EFAULT;
625 
626 	return 0;
627 }
628 
629 typedef struct drm_ctx_res32 {
630 	int count;
631 	u32 contexts;
632 } drm_ctx_res32_t;
633 
compat_drm_resctx(struct file * file,unsigned int cmd,unsigned long arg)634 static int compat_drm_resctx(struct file *file, unsigned int cmd,
635 			     unsigned long arg)
636 {
637 	drm_ctx_res32_t __user *argp = (void __user *)arg;
638 	drm_ctx_res32_t res32;
639 	struct drm_ctx_res __user *res;
640 	int err;
641 
642 	if (copy_from_user(&res32, argp, sizeof(res32)))
643 		return -EFAULT;
644 
645 	res = compat_alloc_user_space(sizeof(*res));
646 	if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
647 		return -EFAULT;
648 	if (__put_user(res32.count, &res->count)
649 	    || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts,
650 			  &res->contexts))
651 		return -EFAULT;
652 
653 	err = drm_ioctl(file, DRM_IOCTL_RES_CTX, (unsigned long)res);
654 	if (err)
655 		return err;
656 
657 	if (__get_user(res32.count, &res->count)
658 	    || __put_user(res32.count, &argp->count))
659 		return -EFAULT;
660 
661 	return 0;
662 }
663 
664 typedef struct drm_dma32 {
665 	int context;		  /**< Context handle */
666 	int send_count;		  /**< Number of buffers to send */
667 	u32 send_indices;	  /**< List of handles to buffers */
668 	u32 send_sizes;		  /**< Lengths of data to send */
669 	enum drm_dma_flags flags;		  /**< Flags */
670 	int request_count;	  /**< Number of buffers requested */
671 	int request_size;	  /**< Desired size for buffers */
672 	u32 request_indices;	  /**< Buffer information */
673 	u32 request_sizes;
674 	int granted_count;	  /**< Number of buffers granted */
675 } drm_dma32_t;
676 
compat_drm_dma(struct file * file,unsigned int cmd,unsigned long arg)677 static int compat_drm_dma(struct file *file, unsigned int cmd,
678 			  unsigned long arg)
679 {
680 	drm_dma32_t d32;
681 	drm_dma32_t __user *argp = (void __user *)arg;
682 	struct drm_dma __user *d;
683 	int err;
684 
685 	if (copy_from_user(&d32, argp, sizeof(d32)))
686 		return -EFAULT;
687 
688 	d = compat_alloc_user_space(sizeof(*d));
689 	if (!access_ok(VERIFY_WRITE, d, sizeof(*d)))
690 		return -EFAULT;
691 
692 	if (__put_user(d32.context, &d->context)
693 	    || __put_user(d32.send_count, &d->send_count)
694 	    || __put_user((int __user *)(unsigned long)d32.send_indices,
695 			  &d->send_indices)
696 	    || __put_user((int __user *)(unsigned long)d32.send_sizes,
697 			  &d->send_sizes)
698 	    || __put_user(d32.flags, &d->flags)
699 	    || __put_user(d32.request_count, &d->request_count)
700 	    || __put_user((int __user *)(unsigned long)d32.request_indices,
701 			  &d->request_indices)
702 	    || __put_user((int __user *)(unsigned long)d32.request_sizes,
703 			  &d->request_sizes))
704 		return -EFAULT;
705 
706 	err = drm_ioctl(file, DRM_IOCTL_DMA, (unsigned long)d);
707 	if (err)
708 		return err;
709 
710 	if (__get_user(d32.request_size, &d->request_size)
711 	    || __get_user(d32.granted_count, &d->granted_count)
712 	    || __put_user(d32.request_size, &argp->request_size)
713 	    || __put_user(d32.granted_count, &argp->granted_count))
714 		return -EFAULT;
715 
716 	return 0;
717 }
718 
719 #if __OS_HAS_AGP
720 typedef struct drm_agp_mode32 {
721 	u32 mode;	/**< AGP mode */
722 } drm_agp_mode32_t;
723 
compat_drm_agp_enable(struct file * file,unsigned int cmd,unsigned long arg)724 static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
725 				 unsigned long arg)
726 {
727 	drm_agp_mode32_t __user *argp = (void __user *)arg;
728 	drm_agp_mode32_t m32;
729 	struct drm_agp_mode __user *mode;
730 
731 	if (get_user(m32.mode, &argp->mode))
732 		return -EFAULT;
733 
734 	mode = compat_alloc_user_space(sizeof(*mode));
735 	if (put_user(m32.mode, &mode->mode))
736 		return -EFAULT;
737 
738 	return drm_ioctl(file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
739 }
740 
741 typedef struct drm_agp_info32 {
742 	int agp_version_major;
743 	int agp_version_minor;
744 	u32 mode;
745 	u32 aperture_base;	/* physical address */
746 	u32 aperture_size;	/* bytes */
747 	u32 memory_allowed;	/* bytes */
748 	u32 memory_used;
749 
750 	/* PCI information */
751 	unsigned short id_vendor;
752 	unsigned short id_device;
753 } drm_agp_info32_t;
754 
compat_drm_agp_info(struct file * file,unsigned int cmd,unsigned long arg)755 static int compat_drm_agp_info(struct file *file, unsigned int cmd,
756 			       unsigned long arg)
757 {
758 	drm_agp_info32_t __user *argp = (void __user *)arg;
759 	drm_agp_info32_t i32;
760 	struct drm_agp_info __user *info;
761 	int err;
762 
763 	info = compat_alloc_user_space(sizeof(*info));
764 	if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
765 		return -EFAULT;
766 
767 	err = drm_ioctl(file, DRM_IOCTL_AGP_INFO, (unsigned long)info);
768 	if (err)
769 		return err;
770 
771 	if (__get_user(i32.agp_version_major, &info->agp_version_major)
772 	    || __get_user(i32.agp_version_minor, &info->agp_version_minor)
773 	    || __get_user(i32.mode, &info->mode)
774 	    || __get_user(i32.aperture_base, &info->aperture_base)
775 	    || __get_user(i32.aperture_size, &info->aperture_size)
776 	    || __get_user(i32.memory_allowed, &info->memory_allowed)
777 	    || __get_user(i32.memory_used, &info->memory_used)
778 	    || __get_user(i32.id_vendor, &info->id_vendor)
779 	    || __get_user(i32.id_device, &info->id_device))
780 		return -EFAULT;
781 
782 	if (copy_to_user(argp, &i32, sizeof(i32)))
783 		return -EFAULT;
784 
785 	return 0;
786 }
787 
788 typedef struct drm_agp_buffer32 {
789 	u32 size;	/**< In bytes -- will round to page boundary */
790 	u32 handle;	/**< Used for binding / unbinding */
791 	u32 type;	/**< Type of memory to allocate */
792 	u32 physical;	/**< Physical used by i810 */
793 } drm_agp_buffer32_t;
794 
compat_drm_agp_alloc(struct file * file,unsigned int cmd,unsigned long arg)795 static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
796 				unsigned long arg)
797 {
798 	drm_agp_buffer32_t __user *argp = (void __user *)arg;
799 	drm_agp_buffer32_t req32;
800 	struct drm_agp_buffer __user *request;
801 	int err;
802 
803 	if (copy_from_user(&req32, argp, sizeof(req32)))
804 		return -EFAULT;
805 
806 	request = compat_alloc_user_space(sizeof(*request));
807 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
808 	    || __put_user(req32.size, &request->size)
809 	    || __put_user(req32.type, &request->type))
810 		return -EFAULT;
811 
812 	err = drm_ioctl(file, DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
813 	if (err)
814 		return err;
815 
816 	if (__get_user(req32.handle, &request->handle)
817 	    || __get_user(req32.physical, &request->physical)
818 	    || copy_to_user(argp, &req32, sizeof(req32))) {
819 		drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
820 		return -EFAULT;
821 	}
822 
823 	return 0;
824 }
825 
compat_drm_agp_free(struct file * file,unsigned int cmd,unsigned long arg)826 static int compat_drm_agp_free(struct file *file, unsigned int cmd,
827 			       unsigned long arg)
828 {
829 	drm_agp_buffer32_t __user *argp = (void __user *)arg;
830 	struct drm_agp_buffer __user *request;
831 	u32 handle;
832 
833 	request = compat_alloc_user_space(sizeof(*request));
834 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
835 	    || get_user(handle, &argp->handle)
836 	    || __put_user(handle, &request->handle))
837 		return -EFAULT;
838 
839 	return drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
840 }
841 
842 typedef struct drm_agp_binding32 {
843 	u32 handle;	/**< From drm_agp_buffer */
844 	u32 offset;	/**< In bytes -- will round to page boundary */
845 } drm_agp_binding32_t;
846 
compat_drm_agp_bind(struct file * file,unsigned int cmd,unsigned long arg)847 static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
848 			       unsigned long arg)
849 {
850 	drm_agp_binding32_t __user *argp = (void __user *)arg;
851 	drm_agp_binding32_t req32;
852 	struct drm_agp_binding __user *request;
853 
854 	if (copy_from_user(&req32, argp, sizeof(req32)))
855 		return -EFAULT;
856 
857 	request = compat_alloc_user_space(sizeof(*request));
858 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
859 	    || __put_user(req32.handle, &request->handle)
860 	    || __put_user(req32.offset, &request->offset))
861 		return -EFAULT;
862 
863 	return drm_ioctl(file, DRM_IOCTL_AGP_BIND, (unsigned long)request);
864 }
865 
compat_drm_agp_unbind(struct file * file,unsigned int cmd,unsigned long arg)866 static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
867 				 unsigned long arg)
868 {
869 	drm_agp_binding32_t __user *argp = (void __user *)arg;
870 	struct drm_agp_binding __user *request;
871 	u32 handle;
872 
873 	request = compat_alloc_user_space(sizeof(*request));
874 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
875 	    || get_user(handle, &argp->handle)
876 	    || __put_user(handle, &request->handle))
877 		return -EFAULT;
878 
879 	return drm_ioctl(file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
880 }
881 #endif				/* __OS_HAS_AGP */
882 
883 typedef struct drm_scatter_gather32 {
884 	u32 size;	/**< In bytes -- will round to page boundary */
885 	u32 handle;	/**< Used for mapping / unmapping */
886 } drm_scatter_gather32_t;
887 
compat_drm_sg_alloc(struct file * file,unsigned int cmd,unsigned long arg)888 static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
889 			       unsigned long arg)
890 {
891 	drm_scatter_gather32_t __user *argp = (void __user *)arg;
892 	struct drm_scatter_gather __user *request;
893 	int err;
894 	unsigned long x;
895 
896 	request = compat_alloc_user_space(sizeof(*request));
897 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
898 	    || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
899 	    || __get_user(x, &argp->size)
900 	    || __put_user(x, &request->size))
901 		return -EFAULT;
902 
903 	err = drm_ioctl(file, DRM_IOCTL_SG_ALLOC, (unsigned long)request);
904 	if (err)
905 		return err;
906 
907 	/* XXX not sure about the handle conversion here... */
908 	if (__get_user(x, &request->handle)
909 	    || __put_user(x >> PAGE_SHIFT, &argp->handle))
910 		return -EFAULT;
911 
912 	return 0;
913 }
914 
compat_drm_sg_free(struct file * file,unsigned int cmd,unsigned long arg)915 static int compat_drm_sg_free(struct file *file, unsigned int cmd,
916 			      unsigned long arg)
917 {
918 	drm_scatter_gather32_t __user *argp = (void __user *)arg;
919 	struct drm_scatter_gather __user *request;
920 	unsigned long x;
921 
922 	request = compat_alloc_user_space(sizeof(*request));
923 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
924 	    || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
925 	    || __get_user(x, &argp->handle)
926 	    || __put_user(x << PAGE_SHIFT, &request->handle))
927 		return -EFAULT;
928 
929 	return drm_ioctl(file, DRM_IOCTL_SG_FREE, (unsigned long)request);
930 }
931 
932 #if defined(CONFIG_X86) || defined(CONFIG_IA64)
933 typedef struct drm_update_draw32 {
934 	drm_drawable_t handle;
935 	unsigned int type;
936 	unsigned int num;
937 	/* 64-bit version has a 32-bit pad here */
938 	u64 data;	/**< Pointer */
939 } __attribute__((packed)) drm_update_draw32_t;
940 
compat_drm_update_draw(struct file * file,unsigned int cmd,unsigned long arg)941 static int compat_drm_update_draw(struct file *file, unsigned int cmd,
942 				  unsigned long arg)
943 {
944 	drm_update_draw32_t update32;
945 	struct drm_update_draw __user *request;
946 	int err;
947 
948 	if (copy_from_user(&update32, (void __user *)arg, sizeof(update32)))
949 		return -EFAULT;
950 
951 	request = compat_alloc_user_space(sizeof(*request));
952 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) ||
953 	    __put_user(update32.handle, &request->handle) ||
954 	    __put_user(update32.type, &request->type) ||
955 	    __put_user(update32.num, &request->num) ||
956 	    __put_user(update32.data, &request->data))
957 		return -EFAULT;
958 
959 	err = drm_ioctl(file, DRM_IOCTL_UPDATE_DRAW, (unsigned long)request);
960 	return err;
961 }
962 #endif
963 
964 struct drm_wait_vblank_request32 {
965 	enum drm_vblank_seq_type type;
966 	unsigned int sequence;
967 	u32 signal;
968 };
969 
970 struct drm_wait_vblank_reply32 {
971 	enum drm_vblank_seq_type type;
972 	unsigned int sequence;
973 	s32 tval_sec;
974 	s32 tval_usec;
975 };
976 
977 typedef union drm_wait_vblank32 {
978 	struct drm_wait_vblank_request32 request;
979 	struct drm_wait_vblank_reply32 reply;
980 } drm_wait_vblank32_t;
981 
compat_drm_wait_vblank(struct file * file,unsigned int cmd,unsigned long arg)982 static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
983 				  unsigned long arg)
984 {
985 	drm_wait_vblank32_t __user *argp = (void __user *)arg;
986 	drm_wait_vblank32_t req32;
987 	union drm_wait_vblank __user *request;
988 	int err;
989 
990 	if (copy_from_user(&req32, argp, sizeof(req32)))
991 		return -EFAULT;
992 
993 	request = compat_alloc_user_space(sizeof(*request));
994 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
995 	    || __put_user(req32.request.type, &request->request.type)
996 	    || __put_user(req32.request.sequence, &request->request.sequence)
997 	    || __put_user(req32.request.signal, &request->request.signal))
998 		return -EFAULT;
999 
1000 	err = drm_ioctl(file, DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
1001 	if (err)
1002 		return err;
1003 
1004 	if (__get_user(req32.reply.type, &request->reply.type)
1005 	    || __get_user(req32.reply.sequence, &request->reply.sequence)
1006 	    || __get_user(req32.reply.tval_sec, &request->reply.tval_sec)
1007 	    || __get_user(req32.reply.tval_usec, &request->reply.tval_usec))
1008 		return -EFAULT;
1009 
1010 	if (copy_to_user(argp, &req32, sizeof(req32)))
1011 		return -EFAULT;
1012 
1013 	return 0;
1014 }
1015 
1016 drm_ioctl_compat_t *drm_compat_ioctls[] = {
1017 	[DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
1018 	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
1019 	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap,
1020 	[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient,
1021 	[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats,
1022 	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique,
1023 	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap,
1024 	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs,
1025 	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs,
1026 	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs,
1027 	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs,
1028 	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs,
1029 	[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap,
1030 	[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx,
1031 	[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx,
1032 	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx,
1033 	[DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma,
1034 #if __OS_HAS_AGP
1035 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable,
1036 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info,
1037 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc,
1038 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free,
1039 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind,
1040 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind,
1041 #endif
1042 	[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
1043 	[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
1044 #if defined(CONFIG_X86) || defined(CONFIG_IA64)
1045 	[DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw,
1046 #endif
1047 	[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
1048 };
1049 
1050 /**
1051  * Called whenever a 32-bit process running under a 64-bit kernel
1052  * performs an ioctl on /dev/drm.
1053  *
1054  * \param file_priv DRM file private.
1055  * \param cmd command.
1056  * \param arg user argument.
1057  * \return zero on success or negative number on failure.
1058  */
drm_compat_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)1059 long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1060 {
1061 	unsigned int nr = DRM_IOCTL_NR(cmd);
1062 	drm_ioctl_compat_t *fn;
1063 	int ret;
1064 
1065 	/* Assume that ioctls without an explicit compat routine will just
1066 	 * work.  This may not always be a good assumption, but it's better
1067 	 * than always failing.
1068 	 */
1069 	if (nr >= ARRAY_SIZE(drm_compat_ioctls))
1070 		return drm_ioctl(filp, cmd, arg);
1071 
1072 	fn = drm_compat_ioctls[nr];
1073 
1074 	if (fn != NULL)
1075 		ret = (*fn) (filp, cmd, arg);
1076 	else
1077 		ret = drm_ioctl(filp, cmd, arg);
1078 
1079 	return ret;
1080 }
1081 
1082 EXPORT_SYMBOL(drm_compat_ioctl);
1083