Grab vmobjlocks with RW_DUPOK in vm_obj_wire() to silence WITNESS
authorkn <kn@openbsd.org>
Mon, 21 Feb 2022 16:08:36 +0000 (16:08 +0000)
committerkn <kn@openbsd.org>
Mon, 21 Feb 2022 16:08:36 +0000 (16:08 +0000)
The drm subsystem implements graphics buffers as uvm objects backed by
anonymous memory, thus drm locks and aobj locks share the same "vmobjlock"
type.

uvm_obj_wire() is only called from sys/dev/pci/drm/, so instead of changing
drm's lock init/alloc routines to mark allow duplicate locks in general,
enter uvm's vmobjlock with RW_DUPOK in this function to allow duplicate
lock types per thread in this specific call path alone.

Fixes the following WITNESS report when booting/starting X (as seen already
in other unrelated bugs@ reports):

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.

Input kettenis
OK mpi

sys/uvm/uvm_object.c

index 4de508e..1516637 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_object.c,v 1.24 2022/01/17 13:55:32 mpi Exp $     */
+/*     $OpenBSD: uvm_object.c,v 1.25 2022/02/21 16:08:36 kn Exp $      */
 
 /*
  * Copyright (c) 2006, 2010, 2019 The NetBSD Foundation, Inc.
@@ -133,7 +133,7 @@ uvm_obj_wire(struct uvm_object *uobj, voff_t start, voff_t end,
 
        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, voff_t start, voff_t end,
                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, voff_t start, voff_t end)
        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);