On Wed, Feb 16, 2022 at 11:39:19PM +0100, Mark Kettenis wrote:
> > Date: Wed, 16 Feb 2022 21:13:03 +0000
> > From: Klemens Nanni <[email protected]>
> > 
> > Unmodified -current with WITNESS enabled booting into X on my X230:
> > 
> > wsdisplay0: screen 1-5 added (std, vt100 emulation)
> > witness: acquiring duplicate lock of same type: "&uobj->vmobjlock"
> >  1st uobjlk
> >  2nd uobjlk
> > Starting stack trace...
> > witness_checkorder(fffffd83b625f9b0,9,0) at witness_checkorder+0x8ac
> > rw_enter(fffffd83b625f9a0,1) at rw_enter+0x68
> > uvm_obj_wire(fffffd843c39e948,0,40000,ffff800033b70428) at uvm_obj_wire+0x46
> > shmem_get_pages(ffff800008008500) at shmem_get_pages+0xb8
> > __i915_gem_object_get_pages(ffff800008008500) at 
> > __i915_gem_object_get_pages+0x6d
> > i915_gem_fault(ffff800008008500,ffff800033b707c0,10009b000,a43d6b1c000,ffff800033b70740,1,35ba896911df1241,ffff8000000aa078,ffff8000000aa178)
> >  at i915_gem_fault+0x203
> > drm_fault(ffff800033b707c0,a43d6b1c000,ffff800033b70740,1,0,0,7eca45006f70ee0,ffff800033b707c0)
> >  at drm_fault+0x156
> > uvm_fault(fffffd843a7cf480,a43d6b1c000,0,2) at uvm_fault+0x179
> > upageflttrap(ffff800033b70920,a43d6b1c000) at upageflttrap+0x62
> > usertrap(ffff800033b70920) at usertrap+0x129
> > recall_trap() at recall_trap+0x8
> > end of kernel
> > end trace frame: 0x7f7ffffdc7c0, count: 246
> > End of stack trace.
> > 
> > The system works fine (unless booted with kern.witness.watch=3), so I'm
> > posting it here for reference -- haven't had time to look into this.
> 
> Yes, this is expected.  The graphics buffers are implented as a uvm
> object and this object is backed by an anonymous memory uvm_object
> (aobj).  So I think the vmobjlock needs a RW_DUPOK flag.

I see, thanks for the hint.

I looked at drm first to see if I could easily add RW_DUPOK to their
init/enter calls only such that RW_DUPOK for objlk is contained within
drm, but that's neither easy nor needed.

uvm_obj_wire() is only called from sys/dev/pci/drm/ anyway, so we can
just treat drm there.

The lock order reversal is about uvm_obj_wire() only and I haven't seen
one in uvm_obj_unwire(), but my diff consequently adds RW_DUPOK to both
as both are being used in drm.

This makes the witness report go away on my X230.

Does that RW_DUPOK deserve a comment?
Feedback? Objections? OK?

> > wsdisplay0: screen 1-5 added (std, vt100 emulation)
> > witness: acquiring duplicate lock of same type: "&uobj->vmobjlock"
> >  1st uobjlk
> >  2nd uobjlk
> > Starting stack trace...
> > witness_checkorder(fffffd83b625f9b0,9,0) at witness_checkorder+0x8ac
> > rw_enter(fffffd83b625f9a0,1) at rw_enter+0x68
> > uvm_obj_wire(fffffd843c39e948,0,40000,ffff800033b70428) at uvm_obj_wire+0x46
> > shmem_get_pages(ffff800008008500) at shmem_get_pages+0xb8
> > __i915_gem_object_get_pages(ffff800008008500) at 
> > __i915_gem_object_get_pages+0x6d
> > i915_gem_fault(ffff800008008500,ffff800033b707c0,10009b000,a43d6b1c000,ffff800033b70740,1,35ba896911df1241,ffff8000000aa078,ffff8000000aa178)
> >  at i915_gem_fault+0x203
> > drm_fault(ffff800033b707c0,a43d6b1c000,ffff800033b70740,1,0,0,7eca45006f70ee0,ffff800033b707c0)
> >  at drm_fault+0x156
> > uvm_fault(fffffd843a7cf480,a43d6b1c000,0,2) at uvm_fault+0x179
> > upageflttrap(ffff800033b70920,a43d6b1c000) at upageflttrap+0x62
> > usertrap(ffff800033b70920) at usertrap+0x129
> > recall_trap() at recall_trap+0x8
> > end of kernel
> > end trace frame: 0x7f7ffffdc7c0, count: 246
> > End of stack trace.


Index: uvm_object.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_object.c,v
retrieving revision 1.24
diff -u -p -r1.24 uvm_object.c
--- uvm_object.c        17 Jan 2022 13:55:32 -0000      1.24
+++ uvm_object.c        17 Feb 2022 16:12:54 -0000
@@ -133,7 +133,7 @@ uvm_obj_wire(struct uvm_object *uobj, vo
 
        left = (end - start) >> PAGE_SHIFT;
 
-       rw_enter(uobj->vmobjlock, RW_WRITE);
+       rw_enter(uobj->vmobjlock, RW_WRITE | RW_DUPOK);
        while (left) {
 
                npages = MIN(FETCH_PAGECOUNT, left);
@@ -147,7 +147,7 @@ uvm_obj_wire(struct uvm_object *uobj, vo
                if (error)
                        goto error;
 
-               rw_enter(uobj->vmobjlock, RW_WRITE);
+               rw_enter(uobj->vmobjlock, RW_WRITE | RW_DUPOK);
                for (i = 0; i < npages; i++) {
 
                        KASSERT(pgs[i] != NULL);
@@ -197,7 +197,7 @@ uvm_obj_unwire(struct uvm_object *uobj, 
        struct vm_page *pg;
        off_t offset;
 
-       rw_enter(uobj->vmobjlock, RW_WRITE);
+       rw_enter(uobj->vmobjlock, RW_WRITE | RW_DUPOK);
        uvm_lock_pageq();
        for (offset = start; offset < end; offset += PAGE_SIZE) {
                pg = uvm_pagelookup(uobj, offset);

Reply via email to