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