• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
79 typedef 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 
compat_drm_version(struct file * file,unsigned int cmd,unsigned long arg)91 static 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 
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 
compat_drm_getunique(struct file * file,unsigned int cmd,unsigned long arg)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 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 
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 	/* it's dead */
163 	return -EINVAL;
164 }
165 
166 #if IS_ENABLED(CONFIG_DRM_LEGACY)
167 typedef 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 
compat_drm_getmap(struct file * file,unsigned int cmd,unsigned long arg)176 static 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 
compat_drm_addmap(struct file * file,unsigned int cmd,unsigned long arg)204 static 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 
compat_drm_rmmap(struct file * file,unsigned int cmd,unsigned long arg)238 static 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 
252 typedef 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 
compat_drm_getclient(struct file * file,unsigned int cmd,unsigned long arg)261 static 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 
292 typedef 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 
compat_drm_getstats(struct file * file,unsigned int cmd,unsigned long arg)300 static 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)
312 typedef 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 
compat_drm_addbufs(struct file * file,unsigned int cmd,unsigned long arg)321 static 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 
compat_drm_markbufs(struct file * file,unsigned int cmd,unsigned long arg)352 static 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 
370 typedef struct drm_buf_info32 {
371 	int count;		/**< Entries in list */
372 	u32 list;
373 } drm_buf_info32_t;
374 
copy_one_buf32(void * data,int count,struct drm_buf_entry * from)375 static 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 
drm_legacy_infobufs32(struct drm_device * dev,void * data,struct drm_file * file_priv)389 static 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 
compat_drm_infobufs(struct file * file,unsigned int cmd,unsigned long arg)397 static 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 
420 typedef 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 
427 typedef 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 
map_one_buf32(void * data,int idx,unsigned long virtual,struct drm_buf * buf)433 static 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 
drm_legacy_mapbufs32(struct drm_device * dev,void * data,struct drm_file * file_priv)449 static 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 
compat_drm_mapbufs(struct file * file,unsigned int cmd,unsigned long arg)461 static 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 
484 typedef struct drm_buf_free32 {
485 	int count;
486 	u32 list;
487 } drm_buf_free32_t;
488 
compat_drm_freebufs(struct file * file,unsigned int cmd,unsigned long arg)489 static 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 
504 typedef 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 
compat_drm_setsareactx(struct file * file,unsigned int cmd,unsigned long arg)509 static 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 
compat_drm_getsareactx(struct file * file,unsigned int cmd,unsigned long arg)525 static 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 
548 typedef struct drm_ctx_res32 {
549 	int count;
550 	u32 contexts;
551 } drm_ctx_res32_t;
552 
compat_drm_resctx(struct file * file,unsigned int cmd,unsigned long arg)553 static 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 
577 typedef 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 
compat_drm_dma(struct file * file,unsigned int cmd,unsigned long arg)590 static 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)
623 typedef struct drm_agp_mode32 {
624 	u32 mode;	/**< AGP mode */
625 } drm_agp_mode32_t;
626 
compat_drm_agp_enable(struct file * file,unsigned int cmd,unsigned long arg)627 static 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 
640 typedef 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 
compat_drm_agp_info(struct file * file,unsigned int cmd,unsigned long arg)654 static 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 
681 typedef 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 
compat_drm_agp_alloc(struct file * file,unsigned int cmd,unsigned long arg)688 static 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 
compat_drm_agp_free(struct file * file,unsigned int cmd,unsigned long arg)717 static 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 
730 typedef 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 
compat_drm_agp_bind(struct file * file,unsigned int cmd,unsigned long arg)735 static 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 
compat_drm_agp_unbind(struct file * file,unsigned int cmd,unsigned long arg)751 static 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 
765 typedef 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 
compat_drm_sg_alloc(struct file * file,unsigned int cmd,unsigned long arg)770 static 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 
compat_drm_sg_free(struct file * file,unsigned int cmd,unsigned long arg)792 static 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)
807 typedef 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 
compat_drm_update_draw(struct file * file,unsigned int cmd,unsigned long arg)815 static 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 
823 struct drm_wait_vblank_request32 {
824 	enum drm_vblank_seq_type type;
825 	unsigned int sequence;
826 	u32 signal;
827 };
828 
829 struct 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 
836 typedef union drm_wait_vblank32 {
837 	struct drm_wait_vblank_request32 request;
838 	struct drm_wait_vblank_reply32 reply;
839 } drm_wait_vblank32_t;
840 
compat_drm_wait_vblank(struct file * file,unsigned int cmd,unsigned long arg)841 static 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)
870 typedef 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 
compat_drm_mode_addfb2(struct file * file,unsigned int cmd,unsigned long arg)882 static 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 
910 static 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  */
drm_compat_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)971 long 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 }
999 EXPORT_SYMBOL(drm_compat_ioctl);
1000