Bug #8048

panic in drm_gem_unmap with Xorg 1.18

Added by Gordon Ross about 2 months ago. Updated about 1 month ago.

Status:ClosedStart date:2017-04-08
Priority:NormalDue date:
Assignee:Gordon Ross% Done:

0%

Category:-
Target version:-
Difficulty:Medium Tags:needs-triage

Description

An OI user, alarcher, reported that their system panicked whenever X quit.
He provided a crash dump. Rich Lowe did some analysis -- We die here:

ffffff00107f8c20 mutex_enter+0xb()
(missing frame) drm_gem_unmap(dhp=0xffffff03c7e1abf8, pvtp=0xffffff03de516840)
ffffff00107f8c70 devmap_handle_unmap+0x58(ffffff03c7e1abf8)
ffffff00107f8ca0 segdev_free+0x30(ffffff03e250acb8)
ffffff00107f8cd0 seg_free+0x30(ffffff03e250acb8)
ffffff00107f8da0 segdev_unmap+0x712(ffffff03e250acb8, fffffd7ffd6f1000, 800000)
ffffff00107f8e00 as_free+0xc7(ffffff03cf2089c0)
ffffff00107f8e30 relvm+0x220()
ffffff00107f8ec0 proc_exit+0x464(1, 0)
ffffff00107f8ee0 exit+0x15(1, 0)
ffffff00107f8f00 rexit+0x18(0)
ffffff00107f8f10 sys_syscall+0x17a()

This is us tearing down the devmap mapping that X holds on DRM, via
drm_gem_unmap (which is unfortunately elided by mutex_enter not having
a frame of its own. Yuck) The reason we crash is that the
drm_device_t in the drm_gem_object_t is NULL, so we try to take a
mutex offset from NULL:

History

#1 Updated by Gordon Ross about 2 months ago

  • Description updated (diff)

Here's the (interesting) missing frame in that stack backtrace:

... drm_gem_unmap(dhp=0xffffff03c7e1abf8, pvtp=0xffffff03de516840)

Here's a "walk" of the relevant data structures in that stack:

seg = ffffff03e250acb8

> ffffff03e250acb8 ::print "struct seg" 
{
    s_base = 0xfffffd7ffd6f1000
    s_size = 0x800000
    s_szc = 0
    s_flags = 0
    s_as = 0xffffff03cf2089c0
    s_tree = {
        avl_child = [ 0, 0 ]
        avl_pcb = 0xffffff03e2503329
    }
    s_ops = segdev_ops
    s_data = 0xffffff03ea969648        <<< struct segdev_data
    s_pmtx = {
        _opaque = [ 0 ]
    }
    s_phead = {
        p_lnext = 0xffffff03e250ad08
        p_lprev = 0xffffff03e250ad08
    }
}

segdev = ffffff03ea969648 (sdp)
> 0xffffff03ea969648 ::print "struct segdev_data" 
{
    offset = 0xe000
    lock = {
        _opaque = [ 0 ]
    }
    mapfunc = 0
    vp = 0xffffff03cd801600
    pageprot = 0
    prot = 0xb
    maxprot = 0xf
    type = 0x1
    vpage = 0
    hat_attr = 0
    hat_flags = 0
    softlockcnt = 0
    devmap_data = 0xffffff03c7e1abf8        <<< devmap_handle_t
}

devmap = ffffff03c7e1abf8 (dhp)
> 0xffffff03c7e1abf8 ::print devmap_handle_t
{
    dh_roff = 0
    dh_uoff = 0xe000
    dh_len = 0x800000
    dh_dev = 0x6d00000000
    dh_cvaddr = 0xffffff03ed0f1000
    dh_uvaddr = 0xfffffd7ffd6f1000
    dh_lock = {
        _opaque = [ 0 ]
    }
    dh_seg = 0xffffff03e250acb8
    dh_pvtp = 0xffffff03de516840    <<< struct drm_gem_object
    dh_next = 0
    dh_softlock = 0xffffff03dae9de90
    dh_ctx = 0xffffff03d65fbbf8
    dh_cookie = 0xffffff03ccf093f0
    dh_pcookie = 0
    dh_prot = 0xb
    dh_maxprot = 0xf
    dh_mmulevel = 0
    dh_flags = 0x302
    dh_pfn = 0
    dh_hat_attr = 0x100200
    dh_timeout_length = 0             
    dh_callbackops = {
        devmap_rev = 0x1
        devmap_map = drm_gem_map
        devmap_access = drm_gem_map_access
        devmap_dup = 0
        devmap_unmap = drm_gem_unmap
    }
    dh_orig_maxprot = 0xf
}

pvtp = 0xffffff03de516840
> 0xffffff03de516840 ::print "struct drm_gem_object" 
{
    refcount = {
        refcount = 0
    }
    handle_count = 0
    dev = 0
    map_list = {
        head = {
            next = 0
            prev = 0
            contain_ptr = 0xdededede00000000
        }
        map = 0
        user_token = 0x3836377834323031
        master = 0
        file_offset_node = 0
    }
    [... dead memory ...]
}

That gem object has gone "dead".

I suspect we may need to do something like:

    drm_gem_object_reference(obj) 

after the __find_local_map() in
drm_gem_map()? And, of course,
release in drm_gem_unmap, and probably
implement drm_gem_dup to bump ref. counts....

#2 Updated by Gordon Ross about 1 month ago

  • Status changed from New to In Progress

#3 Updated by Gordon Ross about 1 month ago

  • Status changed from In Progress to Resolved
commit e49fc716c30eed65a727e91bbccacaf8745743df
Author: Gordon Ross <gordon.w.ross@gmail.com>
Date:   Sun Apr 16 19:32:43 2017 -0400

    8048 panic in drm_gem_unmap with Xorg 1.18
    Reviewed by: Richard Lowe <richlowe@richlowe.net>
    Reviewed by: Toomas Soome <tsoome@me.com>
    Reviewed by: Aurlien Larcher <aurelien.larcher@gmail.com>

8       0       Makefile
2       1       usr/src/common/libdrm/Makefile.drm
4       0       usr/src/uts/common/io/drm/drm_gem.c
167     49      usr/src/uts/common/io/drm/drm_sunmod.c
1       2       usr/src/uts/intel/io/i915/i915_dma.c
1       1       usr/src/uts/intel/io/i915/i915_drv.c
2       2       usr/src/uts/intel/io/i915/i915_drv.h
2       2       usr/src/uts/intel/io/i915/i915_gem.c
17      6       usr/src/uts/intel/io/i915/i915_gem_gtt.c
0       1       usr/src/uts/intel/io/i915/intel_display.c
0       1       usr/src/uts/intel/io/i915/intel_fb.c

#4 Updated by Gordon Ross about 1 month ago

  • Status changed from Resolved to Closed

Also available in: Atom