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