···316316typedef int drm_ioctl_t( struct inode *inode, struct file *filp,317317 unsigned int cmd, unsigned long arg );318318319319+typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,320320+ unsigned long arg);321321+319322typedef struct drm_ioctl_desc {320323 drm_ioctl_t *func;321324 int auth_needed;···777774extern int drm_version(struct inode *inode, struct file *filp,778775 unsigned int cmd, unsigned long arg);779776extern int drm_ioctl(struct inode *inode, struct file *filp,777777+ unsigned int cmd, unsigned long arg);778778+extern long drm_compat_ioctl(struct file *filp,780779 unsigned int cmd, unsigned long arg);781780extern int drm_takedown(drm_device_t * dev);782781
+18-7
drivers/char/drm/drm_bufs.c
···6060}6161EXPORT_SYMBOL(drm_order);62626363+#ifdef CONFIG_COMPAT6464+/*6565+ * Used to allocate 32-bit handles for _DRM_SHM regions6666+ * The 0x10000000 value is chosen to be out of the way of6767+ * FB/register and GART physical addresses.6868+ */6969+static unsigned int map32_handle = 0x10000000;7070+#endif7171+6372/**6473 * Ioctl to specify a range of memory that is available for mapping by a non-root process.6574 *···196187197188 down(&dev->struct_sem);198189 list_add(&list->head, &dev->maplist->head);190190+#ifdef CONFIG_COMPAT191191+ /* Assign a 32-bit handle for _DRM_SHM mappings */192192+ /* We do it here so that dev->struct_sem protects the increment */193193+ if (map->type == _DRM_SHM)194194+ map->offset = map32_handle += PAGE_SIZE;195195+#endif199196 up(&dev->struct_sem);200197201198 if ( copy_to_user( argp, map, sizeof(*map) ) )202199 return -EFAULT;203203- if ( map->type != _DRM_SHM ) {204204- if ( copy_to_user( &argp->handle,205205- &map->offset,206206- sizeof(map->offset) ) )207207- return -EFAULT;208208- }200200+ if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset)))201201+ return -EFAULT;209202 return 0;210203}211204···251240 r_list = list_entry(list, drm_map_list_t, head);252241253242 if(r_list->map &&254254- r_list->map->handle == request.handle &&243243+ r_list->map->offset == (unsigned long) request.handle &&255244 r_list->map->flags & _DRM_REMOVABLE) break;256245 }257246
···317317extern int radeon_postinit( struct drm_device *dev, unsigned long flags );318318extern int radeon_postcleanup( struct drm_device *dev );319319320320+extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,321321+ unsigned long arg);322322+320323/* Flags for stats.boxes321324 */322325#define RADEON_BOX_DMA_IDLE 0x1
+395
drivers/char/drm/radeon_ioc32.c
···11+/**22+ * \file radeon_ioc32.c33+ *44+ * 32-bit ioctl compatibility routines for the Radeon DRM.55+ *66+ * \author Paul Mackerras <paulus@samba.org>77+ *88+ * Copyright (C) Paul Mackerras 200599+ * All Rights Reserved.1010+ *1111+ * Permission is hereby granted, free of charge, to any person obtaining a1212+ * copy of this software and associated documentation files (the "Software"),1313+ * to deal in the Software without restriction, including without limitation1414+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,1515+ * and/or sell copies of the Software, and to permit persons to whom the1616+ * Software is furnished to do so, subject to the following conditions:1717+ *1818+ * The above copyright notice and this permission notice (including the next1919+ * paragraph) shall be included in all copies or substantial portions of the2020+ * Software.2121+ *2222+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR2323+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,2424+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL2525+ * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,2626+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,2727+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS2828+ * IN THE SOFTWARE.2929+ */3030+#include <linux/compat.h>3131+#include <linux/ioctl32.h>3232+3333+#include "drmP.h"3434+#include "drm.h"3535+#include "radeon_drm.h"3636+#include "radeon_drv.h"3737+3838+typedef struct drm_radeon_init32 {3939+ int func;4040+ u32 sarea_priv_offset;4141+ int is_pci;4242+ int cp_mode;4343+ int gart_size;4444+ int ring_size;4545+ int usec_timeout;4646+4747+ unsigned int fb_bpp;4848+ unsigned int front_offset, front_pitch;4949+ unsigned int back_offset, back_pitch;5050+ unsigned int depth_bpp;5151+ unsigned int depth_offset, depth_pitch;5252+5353+ u32 fb_offset;5454+ u32 mmio_offset;5555+ u32 ring_offset;5656+ u32 ring_rptr_offset;5757+ u32 buffers_offset;5858+ u32 gart_textures_offset;5959+} drm_radeon_init32_t;6060+6161+static int compat_radeon_cp_init(struct file *file, unsigned int cmd,6262+ unsigned long arg)6363+{6464+ drm_radeon_init32_t init32;6565+ drm_radeon_init_t __user *init;6666+6767+ if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))6868+ return -EFAULT;6969+7070+ init = compat_alloc_user_space(sizeof(*init));7171+ if (!access_ok(VERIFY_WRITE, init, sizeof(*init))7272+ || __put_user(init32.func, &init->func)7373+ || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)7474+ || __put_user(init32.is_pci, &init->is_pci)7575+ || __put_user(init32.cp_mode, &init->cp_mode)7676+ || __put_user(init32.gart_size, &init->gart_size)7777+ || __put_user(init32.ring_size, &init->ring_size)7878+ || __put_user(init32.usec_timeout, &init->usec_timeout)7979+ || __put_user(init32.fb_bpp, &init->fb_bpp)8080+ || __put_user(init32.front_offset, &init->front_offset)8181+ || __put_user(init32.front_pitch, &init->front_pitch)8282+ || __put_user(init32.back_offset, &init->back_offset)8383+ || __put_user(init32.back_pitch, &init->back_pitch)8484+ || __put_user(init32.depth_bpp, &init->depth_bpp)8585+ || __put_user(init32.depth_offset, &init->depth_offset)8686+ || __put_user(init32.depth_pitch, &init->depth_pitch)8787+ || __put_user(init32.fb_offset, &init->fb_offset)8888+ || __put_user(init32.mmio_offset, &init->mmio_offset)8989+ || __put_user(init32.ring_offset, &init->ring_offset)9090+ || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)9191+ || __put_user(init32.buffers_offset, &init->buffers_offset)9292+ || __put_user(init32.gart_textures_offset,9393+ &init->gart_textures_offset))9494+ return -EFAULT;9595+9696+ return drm_ioctl(file->f_dentry->d_inode, file,9797+ DRM_IOCTL_RADEON_CP_INIT, (unsigned long) init);9898+}9999+100100+typedef struct drm_radeon_clear32 {101101+ unsigned int flags;102102+ unsigned int clear_color;103103+ unsigned int clear_depth;104104+ unsigned int color_mask;105105+ unsigned int depth_mask; /* misnamed field: should be stencil */106106+ u32 depth_boxes;107107+} drm_radeon_clear32_t;108108+109109+static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,110110+ unsigned long arg)111111+{112112+ drm_radeon_clear32_t clr32;113113+ drm_radeon_clear_t __user *clr;114114+115115+ if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32)))116116+ return -EFAULT;117117+118118+ clr = compat_alloc_user_space(sizeof(*clr));119119+ if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr))120120+ || __put_user(clr32.flags, &clr->flags)121121+ || __put_user(clr32.clear_color, &clr->clear_color)122122+ || __put_user(clr32.clear_depth, &clr->clear_depth)123123+ || __put_user(clr32.color_mask, &clr->color_mask)124124+ || __put_user(clr32.depth_mask, &clr->depth_mask)125125+ || __put_user((void __user *)(unsigned long)clr32.depth_boxes,126126+ &clr->depth_boxes))127127+ return -EFAULT;128128+129129+ return drm_ioctl(file->f_dentry->d_inode, file,130130+ DRM_IOCTL_RADEON_CLEAR, (unsigned long) clr);131131+}132132+133133+typedef struct drm_radeon_stipple32 {134134+ u32 mask;135135+} drm_radeon_stipple32_t;136136+137137+static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,138138+ unsigned long arg)139139+{140140+ drm_radeon_stipple32_t __user *argp = (void __user *) arg;141141+ drm_radeon_stipple_t __user *request;142142+ u32 mask;143143+144144+ if (get_user(mask, &argp->mask))145145+ return -EFAULT;146146+147147+ request = compat_alloc_user_space(sizeof(*request));148148+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))149149+ || __put_user((unsigned int __user *)(unsigned long) mask,150150+ &request->mask))151151+ return -EFAULT;152152+153153+ return drm_ioctl(file->f_dentry->d_inode, file,154154+ DRM_IOCTL_RADEON_STIPPLE, (unsigned long) request);155155+}156156+157157+typedef struct drm_radeon_tex_image32 {158158+ unsigned int x, y; /* Blit coordinates */159159+ unsigned int width, height;160160+ u32 data;161161+} drm_radeon_tex_image32_t;162162+163163+typedef struct drm_radeon_texture32 {164164+ unsigned int offset;165165+ int pitch;166166+ int format;167167+ int width; /* Texture image coordinates */168168+ int height;169169+ u32 image;170170+} drm_radeon_texture32_t;171171+172172+static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,173173+ unsigned long arg)174174+{175175+ drm_radeon_texture32_t req32;176176+ drm_radeon_texture_t __user *request;177177+ drm_radeon_tex_image32_t img32;178178+ drm_radeon_tex_image_t __user *image;179179+180180+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))181181+ return -EFAULT;182182+ if (req32.image == 0)183183+ return -EINVAL;184184+ if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image,185185+ sizeof(img32)))186186+ return -EFAULT;187187+188188+ request = compat_alloc_user_space(sizeof(*request) + sizeof(*image));189189+ if (!access_ok(VERIFY_WRITE, request,190190+ sizeof(*request) + sizeof(*image)))191191+ return -EFAULT;192192+ image = (drm_radeon_tex_image_t __user *) (request + 1);193193+194194+ if (__put_user(req32.offset, &request->offset)195195+ || __put_user(req32.pitch, &request->pitch)196196+ || __put_user(req32.format, &request->format)197197+ || __put_user(req32.width, &request->width)198198+ || __put_user(req32.height, &request->height)199199+ || __put_user(image, &request->image)200200+ || __put_user(img32.x, &image->x)201201+ || __put_user(img32.y, &image->y)202202+ || __put_user(img32.width, &image->width)203203+ || __put_user(img32.height, &image->height)204204+ || __put_user((const void __user *)(unsigned long)img32.data,205205+ &image->data))206206+ return -EFAULT;207207+208208+ return drm_ioctl(file->f_dentry->d_inode, file,209209+ DRM_IOCTL_RADEON_TEXTURE, (unsigned long) request);210210+}211211+212212+typedef struct drm_radeon_vertex2_32 {213213+ int idx; /* Index of vertex buffer */214214+ int discard; /* Client finished with buffer? */215215+ int nr_states;216216+ u32 state;217217+ int nr_prims;218218+ u32 prim;219219+} drm_radeon_vertex2_32_t;220220+221221+static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,222222+ unsigned long arg)223223+{224224+ drm_radeon_vertex2_32_t req32;225225+ drm_radeon_vertex2_t __user *request;226226+227227+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))228228+ return -EFAULT;229229+230230+ request = compat_alloc_user_space(sizeof(*request));231231+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))232232+ || __put_user(req32.idx, &request->idx)233233+ || __put_user(req32.discard, &request->discard)234234+ || __put_user(req32.nr_states, &request->nr_states)235235+ || __put_user((void __user *)(unsigned long)req32.state,236236+ &request->state)237237+ || __put_user(req32.nr_prims, &request->nr_prims)238238+ || __put_user((void __user *)(unsigned long)req32.prim,239239+ &request->prim))240240+ return -EFAULT;241241+242242+ return drm_ioctl(file->f_dentry->d_inode, file,243243+ DRM_IOCTL_RADEON_VERTEX2, (unsigned long) request);244244+}245245+246246+typedef struct drm_radeon_cmd_buffer32 {247247+ int bufsz;248248+ u32 buf;249249+ int nbox;250250+ u32 boxes;251251+} drm_radeon_cmd_buffer32_t;252252+253253+static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,254254+ unsigned long arg)255255+{256256+ drm_radeon_cmd_buffer32_t req32;257257+ drm_radeon_cmd_buffer_t __user *request;258258+259259+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))260260+ return -EFAULT;261261+262262+ request = compat_alloc_user_space(sizeof(*request));263263+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))264264+ || __put_user(req32.bufsz, &request->bufsz)265265+ || __put_user((void __user *)(unsigned long)req32.buf,266266+ &request->buf)267267+ || __put_user(req32.nbox, &request->nbox)268268+ || __put_user((void __user *)(unsigned long)req32.boxes,269269+ &request->boxes))270270+ return -EFAULT;271271+272272+ return drm_ioctl(file->f_dentry->d_inode, file,273273+ DRM_IOCTL_RADEON_CMDBUF, (unsigned long) request);274274+}275275+276276+typedef struct drm_radeon_getparam32 {277277+ int param;278278+ u32 value;279279+} drm_radeon_getparam32_t;280280+281281+static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,282282+ unsigned long arg)283283+{284284+ drm_radeon_getparam32_t req32;285285+ drm_radeon_getparam_t __user *request;286286+287287+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))288288+ return -EFAULT;289289+290290+ request = compat_alloc_user_space(sizeof(*request));291291+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))292292+ || __put_user(req32.param, &request->param)293293+ || __put_user((void __user *)(unsigned long)req32.value,294294+ &request->value))295295+ return -EFAULT;296296+297297+ return drm_ioctl(file->f_dentry->d_inode, file,298298+ DRM_IOCTL_RADEON_GETPARAM, (unsigned long) request);299299+}300300+301301+typedef struct drm_radeon_mem_alloc32 {302302+ int region;303303+ int alignment;304304+ int size;305305+ u32 region_offset; /* offset from start of fb or GART */306306+} drm_radeon_mem_alloc32_t;307307+308308+static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,309309+ unsigned long arg)310310+{311311+ drm_radeon_mem_alloc32_t req32;312312+ drm_radeon_mem_alloc_t __user *request;313313+314314+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))315315+ return -EFAULT;316316+317317+ request = compat_alloc_user_space(sizeof(*request));318318+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))319319+ || __put_user(req32.region, &request->region)320320+ || __put_user(req32.alignment, &request->alignment)321321+ || __put_user(req32.size, &request->size)322322+ || __put_user((int __user *)(unsigned long)req32.region_offset,323323+ &request->region_offset))324324+ return -EFAULT;325325+326326+ return drm_ioctl(file->f_dentry->d_inode, file,327327+ DRM_IOCTL_RADEON_ALLOC, (unsigned long) request);328328+}329329+330330+typedef struct drm_radeon_irq_emit32 {331331+ u32 irq_seq;332332+} drm_radeon_irq_emit32_t;333333+334334+static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,335335+ unsigned long arg)336336+{337337+ drm_radeon_irq_emit32_t req32;338338+ drm_radeon_irq_emit_t __user *request;339339+340340+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))341341+ return -EFAULT;342342+343343+ request = compat_alloc_user_space(sizeof(*request));344344+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))345345+ || __put_user((int __user *)(unsigned long)req32.irq_seq,346346+ &request->irq_seq))347347+ return -EFAULT;348348+349349+ return drm_ioctl(file->f_dentry->d_inode, file,350350+ DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request);351351+}352352+353353+drm_ioctl_compat_t *radeon_compat_ioctls[] = {354354+ [DRM_RADEON_CP_INIT] = compat_radeon_cp_init,355355+ [DRM_RADEON_CLEAR] = compat_radeon_cp_clear,356356+ [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple,357357+ [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture,358358+ [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,359359+ [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,360360+ [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,361361+ [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,362362+ [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,363363+};364364+365365+/**366366+ * Called whenever a 32-bit process running under a 64-bit kernel367367+ * performs an ioctl on /dev/dri/card<n>.368368+ *369369+ * \param filp file pointer.370370+ * \param cmd command.371371+ * \param arg user argument.372372+ * \return zero on success or negative number on failure.373373+ */374374+long radeon_compat_ioctl(struct file *filp, unsigned int cmd,375375+ unsigned long arg)376376+{377377+ unsigned int nr = DRM_IOCTL_NR(cmd);378378+ drm_ioctl_compat_t *fn = NULL;379379+ int ret;380380+381381+ if (nr < DRM_COMMAND_BASE)382382+ return drm_compat_ioctl(filp, cmd, arg);383383+384384+ if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls))385385+ fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE];386386+387387+ lock_kernel(); /* XXX for now */388388+ if (fn != NULL)389389+ ret = (*fn)(filp, cmd, arg);390390+ else391391+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);392392+ unlock_kernel();393393+394394+ return ret;395395+}