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);