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