mesa-drm/linux-core
Mike Isely ae1bb96a7e drm: Fix race that can lockup the kernel
The i915_vblank_swap() function schedules an automatic buffer swap
upon receipt of the vertical sync interrupt.  Such an operation is
lengthy so it can't be allowed to happen in normal interrupt context,
thus the DRM implements this by scheduling the work in a kernel
softirq-scheduled tasklet.  In order for the buffer swap to work
safely, the DRM's central lock must be taken, via a call to
drm_lock_take() located in drivers/char/drm/drm_irq.c within the
function drm_locked_tasklet_func().  The lock-taking logic uses a
non-interrupt-blocking spinlock to implement the manipulations needed
to take the lock.  This semantic would be safe if all attempts to use
the spinlock only happen from process context.  However this buffer
swap happens from softirq context which is really a form of interrupt
context.  Thus we have an unsafe situation, in that
drm_locked_tasklet_func() can block on a spinlock already taken by a
thread in process context which will never get scheduled again because
of the blocked softirq tasklet.  This wedges the kernel hard.

To trigger this bug, run a dual-head cloned mode configuration which
uses the i915 drm, then execute an opengl application which
synchronizes buffer swaps against the vertical sync interrupt.  In my
testing, a lockup always results after running anywhere from 5 minutes
to an hour and a half.  I believe dual-head is needed to really
trigger the problem because then the vertical sync interrupt handling
is no longer predictable (due to being interrupt-sourced from two
different heads running at different speeds).  This raises the
probability of the tasklet trying to run while the userspace DRI is
doing things to the GPU (and manipulating the DRM lock).

The fix is to change the relevant spinlock semantics to be the
interrupt-blocking form.  After this change I am no longer able to
trigger the lockup; the longest test run so far was 20 hours (test
stopped after that point).

Note: I have examined the places where this spinlock is being
employed; all are reasonably short bounded sequences and should be
suitable for interrupts being blocked without impacting overall kernel
interrupt response latency.

Signed-off-by: Mike Isely <isely@pobox.com>
2008-03-14 09:53:05 +10:00
..
.gitignore linux-core: Make git ignore generated module symbol version files. 2007-01-02 10:02:44 +01:00
ati_pcigart.c drm: Fix for non-coherent DMA PowerPC 2008-03-05 19:25:03 +10:00
Config.in Added via driver to drm/linux/Config.in Reported by: Terry Barnaby 2004-03-26 13:42:48 +00:00
Doxyfile Update Doxygen configuration & comments. 2004-10-18 14:16:41 +00:00
drm.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
drm_agpsupport.c drm: reorganise minor number handling using code from modesetting branch 2008-03-06 05:21:50 +10:00
drm_auth.c drm: major whitespace/coding style realignment with kernel 2007-11-22 16:10:36 +10:00
drm_bo.c Dont allow !sysadmin clients to alter the memory type of 2008-03-12 10:19:36 +01:00
drm_bo_lock.c drm: reorganise minor number handling using code from modesetting branch 2008-03-06 05:21:50 +10:00
drm_bo_move.c Make sure other TTM memory types than TT is really unbound when evicted. 2008-03-12 09:56:06 +01:00
drm_bufs.c drm: major whitespace/coding style realignment with kernel 2007-11-22 16:10:36 +10:00
drm_compat.c Merge branch 'intel-post-reloc' 2008-03-12 11:34:29 +01:00
drm_compat.h Merge branch 'intel-post-reloc' 2008-03-12 11:34:29 +01:00
drm_context.c drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
drm_core.h Add support for secondary vertical blank interrupt to DRM core. 2006-09-29 12:55:08 +02:00
drm_dma.c drm: major whitespace/coding style realignment with kernel 2007-11-22 16:10:36 +10:00
drm_drawable.c Replace DRM_IOCTL_ARGS with (dev, data, file_priv) and remove DRM_DEVICE. 2007-07-20 18:16:42 -07:00
drm_drv.c drm/ttm: add ioctl to get back memory managed area sized 2008-03-06 05:31:50 +10:00
drm_fence.c Add error message 2008-03-12 10:11:49 +01:00
drm_fops.c drm: Fix race that can lockup the kernel 2008-03-14 09:53:05 +10:00
drm_hashtab.c drm: major whitespace/coding style realignment with kernel 2007-11-22 16:10:36 +10:00
drm_hashtab.h drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
drm_internal.h Add new shared header file drm_internal.h. 2007-11-14 14:28:34 -05:00
drm_ioc32.c Fix ioc32 compat layer 2007-09-18 11:03:08 -07:00
drm_ioctl.c drm: more cleanups 2007-11-29 09:38:21 +10:00
drm_irq.c Don't free irq resources until after we've unregistered the handler. 2008-02-21 15:31:48 -05:00
drm_lock.c drm: Fix race that can lockup the kernel 2008-03-14 09:53:05 +10:00
drm_memory.c Fix for debug memory routines 2008-03-12 10:13:22 +01:00
drm_memory.h drm: major whitespace/coding style realignment with kernel 2007-11-22 16:10:36 +10:00
drm_memory_debug.c Replace DRM_IOCTL_ARGS with (dev, data, file_priv) and remove DRM_DEVICE. 2007-07-20 18:16:42 -07:00
drm_memory_debug.h Replace DRM_IOCTL_ARGS with (dev, data, file_priv) and remove DRM_DEVICE. 2007-07-20 18:16:42 -07:00
drm_mm.c drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
drm_object.c drm: reorganise minor number handling using code from modesetting branch 2008-03-06 05:21:50 +10:00
drm_objects.h ttm: make sure userspace can't destroy kernel create memory managers 2008-03-06 05:37:54 +10:00
drm_os_linux.h drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
drm_pci.c drm: major whitespace/coding style realignment with kernel 2007-11-22 16:10:36 +10:00
drm_proc.c Add an emergency pinnable memory quota for root-only processes. 2008-03-12 10:10:03 +01:00
drm_regman.c drm: cleanup drm_regman.c coding style 2007-11-22 13:29:17 +10:00
drm_sarea.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
drm_scatter.c drm: Fix for non-coherent DMA PowerPC 2008-03-05 19:25:03 +10:00
drm_sman.c drm: major whitespace/coding style realignment with kernel 2007-11-22 16:10:36 +10:00
drm_sman.h drm: remove hashtab/sman and object typedefs 2007-07-16 12:48:44 +10:00
drm_stub.c remove unneeded load call 2008-03-10 18:30:17 +10:00
drm_sysfs.c drm: reorganise minor number handling using code from modesetting branch 2008-03-06 05:21:50 +10:00
drm_ttm.c Bug # 14712 2008-03-12 10:36:40 +01:00
drm_vm.c drm: reorganise minor number handling using code from modesetting branch 2008-03-06 05:21:50 +10:00
drmP.h Add an emergency pinnable memory quota for root-only processes. 2008-03-12 10:10:03 +01:00
ffb_context.c Replace DRM_IOCTL_ARGS with (dev, data, file_priv) and remove DRM_DEVICE. 2007-07-20 18:16:42 -07:00
ffb_drv.c Replace DRM_IOCTL_ARGS with (dev, data, file_priv) and remove DRM_DEVICE. 2007-07-20 18:16:42 -07:00
ffb_drv.h drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
i810_dma.c drm: reorganise minor number handling using code from modesetting branch 2008-03-06 05:21:50 +10:00
i810_drm.h drm: remove XFREE86_VERSION macros 2007-08-28 15:17:36 +10:00
i810_drv.c remove config.h from build no longer exists kbuild does it 2006-10-14 23:38:20 +10:00
i810_drv.h drm: cleanup DRM_DEBUG() parameters 2008-01-03 16:56:04 +10:00
i915_buffer.c i915: fix invalid opcode exception on cpus without clflush 2008-01-17 16:55:44 -08:00
i915_compat.c i915/flush: get the ret the right way around 2008-01-23 16:45:09 +10:00
i915_dma.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
i915_drm.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
i915_drv.c i915: put ARX back into index mode before doing restore 2008-02-22 13:57:38 -08:00
i915_drv.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
i915_execbuf.c Merge branch 'intel-post-reloc' 2008-03-12 11:34:29 +01:00
i915_fence.c i915: Re-report breadcrumbs on poll to the fence manager, 2008-02-05 10:36:49 +01:00
i915_ioc32.c i915: return fence argument from i915_execbuffer ioctl32 routine 2007-12-26 17:13:58 +08:00
i915_irq.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
i915_mem.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
imagine_drv.c remove config.h from build no longer exists kbuild does it 2006-10-14 23:38:20 +10:00
Kconfig Remove old i830 kernel driver. 2007-03-19 11:46:35 +00:00
linux Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mach64_dma.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mach64_drm.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mach64_drv.c Merge branch 'master' into vblank-rework, including mach64 support 2008-01-22 09:42:37 -08:00
mach64_drv.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mach64_irq.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mach64_state.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
Makefile Revert "Remove the pinned buffer from the LRU when pinning." 2007-10-17 10:59:48 +02:00
Makefile.kernel More post-ioctl work. 2008-02-29 13:25:55 +01:00
mga_dma.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mga_drm.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mga_drv.c Merge branch 'master' into vblank-rework, including mach64 support 2008-01-22 09:42:37 -08:00
mga_drv.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mga_ioc32.c drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
mga_irq.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mga_state.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mga_ucode.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
mga_warp.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
nouveau_buffer.c Simplify the fencing code and differentiate between flushes and 2008-01-30 22:06:02 +01:00
nouveau_dma.c nouveau: ouch, add nouveau_dma.[ch] files.. 2007-08-06 22:32:36 +10:00
nouveau_dma.h nouveau: ouch, add nouveau_dma.[ch] files.. 2007-08-06 22:32:36 +10:00
nouveau_drm.h add nouveau symlinks via git 2006-12-20 10:28:55 +11:00
nouveau_drv.c drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
nouveau_drv.h add nouveau symlinks via git 2006-12-20 10:28:55 +11:00
nouveau_fence.c Simplify the fencing code and differentiate between flushes and 2008-01-30 22:06:02 +01:00
nouveau_fifo.c Revert "nouveau: Fill in context_init for nv10-nv3x." 2007-01-10 15:19:47 +11:00
nouveau_ioc32.c remove include of linux ioctl32.h from drm drivers 2007-06-05 18:16:44 +10:00
nouveau_irq.c add nouveau symlinks via git 2006-12-20 10:28:55 +11:00
nouveau_mem.c add nouveau symlinks via git 2006-12-20 10:28:55 +11:00
nouveau_notifier.c nouveau: Nuke DMA_OBJECT_INIT ioctl (bumps interface to 0.0.7) 2007-06-28 03:26:43 +10:00
nouveau_object.c add nouveau symlinks via git 2006-12-20 10:28:55 +11:00
nouveau_reg.h add nouveau symlinks via git 2006-12-20 10:28:55 +11:00
nouveau_sgdma.c nv50: use dummy page in gart tables 2008-01-07 17:09:00 +11:00
nouveau_state.c add nouveau symlinks via git 2006-12-20 10:28:55 +11:00
nouveau_swmthd.c nouveau: mandatory "oops I forgot half of the files" commit 2007-10-12 22:40:08 +02:00
nouveau_swmthd.h nouveau: mandatory "oops I forgot half of the files" commit 2007-10-12 22:40:08 +02:00
nv04_fb.c nouveau: move card initialisation into the drm 2007-03-26 20:59:37 +10:00
nv04_fifo.c nouveau: NV04 PFIFO engtab functions 2007-06-24 18:57:09 +10:00
nv04_graph.c nouveau: add missing nv04_graph.c symlink. 2007-02-03 06:02:12 +01:00
nv04_instmem.c nouveau/nv50: Initial channel/object support 2007-07-09 16:16:44 +10:00
nv04_mc.c nouveau: move card initialisation into the drm 2007-03-26 20:59:37 +10:00
nv04_timer.c nouveau: move card initialisation into the drm 2007-03-26 20:59:37 +10:00
nv10_fb.c nouveau: move card initialisation into the drm 2007-03-26 20:59:37 +10:00
nv10_fifo.c nouveau: NV1X/2X/3X PFIFO engtab functions 2007-06-24 18:58:14 +10:00
nv10_graph.c nouveau: first step to make graph ctx works 2007-01-13 21:44:50 +01:00
nv20_graph.c nouveau: rename nv30_graph.c to nv20_graph.c 2007-09-30 22:16:01 +03:00
nv40_fb.c nouveau: move card initialisation into the drm 2007-03-26 20:59:37 +10:00
nv40_fifo.c nouveau: NV4X PFIFO engtab functions 2007-06-24 18:56:01 +10:00
nv40_graph.c nouveau: Add nv40-specific PGRAPH code, not hooked up yet. 2007-01-02 14:52:43 +11:00
nv40_mc.c nouveau: move card initialisation into the drm 2007-03-26 20:59:37 +10:00
nv50_fifo.c nouveau/nv50: skeletal backend 2007-06-28 03:26:43 +10:00
nv50_graph.c nouveau/nv50: skeletal backend 2007-06-28 03:26:43 +10:00
nv50_instmem.c nouveau/nv50: Initial channel/object support 2007-07-09 16:16:44 +10:00
nv50_mc.c nouveau/nv50: skeletal backend 2007-06-28 03:26:43 +10:00
nv_drv.c remove config.h from build no longer exists kbuild does it 2006-10-14 23:38:20 +10:00
nv_drv.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
r128_cce.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
r128_drm.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
r128_drv.c Merge branch 'master' into vblank-rework, fixup remaining drivers 2007-10-30 12:52:46 -07:00
r128_drv.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
r128_ioc32.c drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
r128_irq.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
r128_state.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
r300_cmdbuf.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
r300_reg.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
radeon_cp.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
radeon_drm.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
radeon_drv.c Merge branch 'master' into vblank-rework, including mach64 support 2008-01-22 09:42:37 -08:00
radeon_drv.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
radeon_ioc32.c drm: major whitespace/coding style realignment with kernel 2007-11-22 16:10:36 +10:00
radeon_irq.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
radeon_mem.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
radeon_state.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
README.drm Fix some outdated URLs, remove others. 2007-02-12 15:45:51 -05:00
savage_bci.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
savage_drm.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
savage_drv.c remove config.h from build no longer exists kbuild does it 2006-10-14 23:38:20 +10:00
savage_drv.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
savage_state.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
sis_drm.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
sis_drv.c Remove DRM_ERR OS macro. 2007-07-20 12:53:52 -07:00
sis_drv.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
sis_mm.c drm: cleanup DRM_DEBUG() parameters 2008-01-03 16:56:04 +10:00
tdfx_drv.c remove config.h from build no longer exists kbuild does it 2006-10-14 23:38:20 +10:00
tdfx_drv.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
via_3d_reg.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
via_buffer.c Rename inappropriately named 'mask' fields to 'proposed_flags' instead. 2007-12-21 12:16:29 -08:00
via_dma.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
via_dmablit.c drm: major whitespace/coding style realignment with kernel 2007-11-22 16:10:36 +10:00
via_dmablit.h drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
via_drm.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
via_drv.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
via_drv.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
via_fence.c Simplify the fencing code and differentiate between flushes and 2008-01-30 22:06:02 +01:00
via_irq.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
via_map.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
via_mm.c drm: cleanup DRM_DEBUG() parameters 2008-01-03 16:56:04 +10:00
via_verifier.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
via_verifier.h Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
via_video.c Track linux-core symlinks in git. 2006-12-01 10:37:55 +01:00
xgi_cmdlist.c drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
xgi_cmdlist.h Implement fence support. 2007-08-15 21:05:26 -07:00
xgi_drm.h Move types shared with user mode to xgi_drm.h. 2007-07-09 16:33:14 -07:00
xgi_drv.c Simplify the fencing code and differentiate between flushes and 2008-01-30 22:06:02 +01:00
xgi_drv.h drm: major whitespace/coding style realignment with kernel 2007-11-22 16:10:36 +10:00
xgi_fb.c drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
xgi_fence.c Simplify the fencing code and differentiate between flushes and 2008-01-30 22:06:02 +01:00
xgi_ioc32.c drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
xgi_misc.c drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
xgi_misc.h drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00
xgi_pcie.c Fix command list submission on big-endian. 2007-10-10 15:25:47 -07:00
xgi_regs.h drm: remove lots of spurious whitespace. 2007-11-05 12:42:22 +10:00

************************************************************
* For the very latest on DRI development, please see:      *
*     http://dri.freedesktop.org/                          *
************************************************************

The Direct Rendering Manager (drm) is a device-independent kernel-level
device driver that provides support for the XFree86 Direct Rendering
Infrastructure (DRI).

The DRM supports the Direct Rendering Infrastructure (DRI) in four major
ways:

    1. The DRM provides synchronized access to the graphics hardware via
       the use of an optimized two-tiered lock.

    2. The DRM enforces the DRI security policy for access to the graphics
       hardware by only allowing authenticated X11 clients access to
       restricted regions of memory.

    3. The DRM provides a generic DMA engine, complete with multiple
       queues and the ability to detect the need for an OpenGL context
       switch.

    4. The DRM is extensible via the use of small device-specific modules
       that rely extensively on the API exported by the DRM module.