On Thu, Oct 25, 2007 at 03:37:32PM +0400, pluknet wrote:
> Hi all.
> 
> I am getting the following LOR on my 7.0-BETA1:
> 
> lock order reversal: (sleepable after non-sleepable)
> 1st 0xc3c904d8 drm device (drm device) @ 
> /media/src/sys/modules/drm/drm/../../..
> /dev/drm/drm_drv.c:907
> 2nd 0xc4135a3c user map (user map) @ vm/vm_glue.c:183
> KDB: stack backtrace:
> db_trace_self_wrapper(c076f2df,e6716a74,c055fcd6,c077168b,c4135a3c,...) at 
> db_tr
> ace_self_wrapper+0x26
> kdb_backtrace(c077168b,c4135a3c,c078accb,c078accb,c078a7e6,...) at 
> kdb_backtrace
> +0x29
> witness_checkorder(c4135a3c,9,c078a7dd,b7,c4135a3c,...) at 
> witness_checkorder+0x
> 6d6
> _sx_xlock(c4135a3c,0,c078a7dd,b7,e6716ad8,...) at _sx_xlock+0x7d
> _vm_map_lock_read(c41359f8,c078a7dd,b7,c078ac64,8,...) at 
> _vm_map_lock_read+0x50
> useracc(28aab980,8,1,1,c076b1ec,...) at useracc+0x65
> i915_cmdbuffer(c4147100,8018644b,c52e8180,3,c492dc60,...) at 
> i915_cmdbuffer+0x56
> 3
> drm_ioctl(c4147100,8018644b,c52e8180,3,c492dc60,...) at drm_ioctl+0x384
> giant_ioctl(c4147100,8018644b,c52e8180,3,c492dc60,...) at giant_ioctl+0x56
> devfs_ioctl_f(c5c146c0,8018644b,c52e8180,c5536500,c492dc60,...) at 
> devfs_ioctl_f
> +0xd5
> kern_ioctl(c492dc60,5,8018644b,c52e8180,c52e8180,...) at kern_ioctl+0x253
> ioctl(c492dc60,e6716cfc,c,e6716d38,c07a92d0,...) at ioctl+0x13f
> syscall(e6716d38) at syscall+0x2f3
> Xint0x80_syscall() at Xint0x80_syscall+0x20
> --- syscall (54, FreeBSD ELF32, ioctl), eip = 0x28698a53, esp = 0xbf6f6c9c, 
> ebp
> = 0xbf6f6cb8 ---
> 
> It is first observed after update to 7.0-BETA1 (from CURRENT of Oct 11)
> $ ident /media/src/sys/dev/drm/drm_drv.c
> /media/src/sys/dev/drm/drm_drv.c:
>      $FreeBSD: src/sys/dev/drm/drm_drv.c,v 1.6 2006/09/07 23:04:47 anholt Exp 
> $
> $ ident /media/src/sys/vm/vm_glue.c
> /media/src/sys/vm/vm_glue.c:
>      $FreeBSD: src/sys/vm/vm_glue.c,v 1.225 2007/09/21 05:07:07 jeff Exp $
> 
> Note that drm is kldloadable and is not statically compiled in a kernel.
> Thanks.

The folowing patch should fix it. I tried to get review by Eric, but failed.

diff --git a/sys/dev/drm/i915_dma.c b/sys/dev/drm/i915_dma.c
index 16955bd..69854b4 100644
--- a/sys/dev/drm/i915_dma.c
+++ b/sys/dev/drm/i915_dma.c
@@ -366,20 +366,14 @@ static int i915_emit_cmds(drm_device_t * dev, int __user 
* buffer, int dwords)
        for (i = 0; i < dwords;) {
                int cmd, sz;
 
-            if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) {
-
-                       return DRM_ERR(EINVAL);
-             }
+               cmd = buffer[i];
                if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
                        return DRM_ERR(EINVAL);
 
                OUT_RING(cmd);
 
                while (++i, --sz) {
-                       if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
-                                                        sizeof(cmd))) {
-                               return DRM_ERR(EINVAL);
-                       }
+                       cmd = buffer[i];
                        OUT_RING(cmd);
                }
        }
@@ -400,10 +394,7 @@ static int i915_emit_box(drm_device_t * dev,
        drm_clip_rect_t box;
        RING_LOCALS;
 
-       if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
-               return EFAULT;
-       }
-
+       box = boxes[i];
        if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) 
{
                DRM_ERROR("Bad box %d,%d..%d,%d\n",
                          box.x1, box.y1, box.x2, box.y2);
@@ -603,6 +594,7 @@ static int i915_batchbuffer(DRM_IOCTL_ARGS)
        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
            dev_priv->sarea_priv;
        drm_i915_batchbuffer_t batch;
+       size_t cliplen;
        int ret;
 
        if (!dev_priv->allow_batchbuffer) {
@@ -618,14 +610,25 @@ static int i915_batchbuffer(DRM_IOCTL_ARGS)
 
        LOCK_TEST_WITH_RETURN(dev, filp);
 
+       DRM_UNLOCK();
+       cliplen = batch.num_cliprects * sizeof(drm_clip_rect_t);        
        if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
-                                                      batch.num_cliprects *
-                                                      sizeof(drm_clip_rect_t)))
+                                                      cliplen)) {
+               DRM_LOCK();
                return DRM_ERR(EFAULT);
-
+       }
+       ret = vslock(batch.cliprects, cliplen);
+       if (ret) {
+               DRM_ERROR("Fault wiring cliprects\n");
+               DRM_LOCK();
+               return DRM_ERR(EFAULT);
+       }
+       DRM_LOCK();
        ret = i915_dispatch_batchbuffer(dev, &batch);
-
        sarea_priv->last_dispatch = (int)hw_status[5];
+       DRM_UNLOCK();
+       vsunlock(batch.cliprects, cliplen);
+       DRM_LOCK();
        return ret;
 }
 
@@ -637,6 +640,7 @@ static int i915_cmdbuffer(DRM_IOCTL_ARGS)
        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
            dev_priv->sarea_priv;
        drm_i915_cmdbuffer_t cmdbuf;
+       size_t cliplen;
        int ret;
 
        DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_i915_cmdbuffer_t __user *) data,
@@ -647,22 +651,38 @@ static int i915_cmdbuffer(DRM_IOCTL_ARGS)
 
        LOCK_TEST_WITH_RETURN(dev, filp);
 
+       DRM_UNLOCK();
+       cliplen = cmdbuf.num_cliprects * sizeof(drm_clip_rect_t);
        if (cmdbuf.num_cliprects &&
-           DRM_VERIFYAREA_READ(cmdbuf.cliprects,
-                               cmdbuf.num_cliprects *
-                               sizeof(drm_clip_rect_t))) {
+           DRM_VERIFYAREA_READ(cmdbuf.cliprects, cliplen)) {
                DRM_ERROR("Fault accessing cliprects\n");
+               DRM_LOCK();
                return DRM_ERR(EFAULT);
        }
-
-       ret = i915_dispatch_cmdbuffer(dev, &cmdbuf);
+       ret = vslock(cmdbuf.cliprects, cliplen);
        if (ret) {
-               DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
-               return ret;
+               DRM_ERROR("Fault wiring cliprects\n");
+               DRM_LOCK();
+               return DRM_ERR(EFAULT);
        }
-
-       sarea_priv->last_dispatch = (int)hw_status[5];
-       return 0;
+       ret = vslock(cmdbuf.buf, cmdbuf.sz);
+       if (ret) {
+               vsunlock(cmdbuf.cliprects, cliplen);
+               DRM_ERROR("Fault wiring cmds\n");
+               DRM_LOCK();
+               return DRM_ERR(EFAULT);
+       }
+       DRM_LOCK();
+       ret = i915_dispatch_cmdbuffer(dev, &cmdbuf);
+       if (ret == 0)
+               sarea_priv->last_dispatch = (int)hw_status[5];
+       else
+               DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
+       DRM_UNLOCK();
+       vsunlock(cmdbuf.buf, cmdbuf.sz);
+       vsunlock(cmdbuf.cliprects, cliplen);
+       DRM_LOCK();
+       return (ret);
 }
 
 static int i915_do_cleanup_pageflip(drm_device_t * dev)

Attachment: pgpj1T8KJnq5u.pgp
Description: PGP signature

Reply via email to