diff options
author | Changbin Du <changbin.du@intel.com> | 2017-11-13 14:58:31 +0800 |
---|---|---|
committer | Zhenyu Wang <zhenyuw@linux.intel.com> | 2017-11-28 17:22:48 +0800 |
commit | 679fd3ebabc23dec33d42525b19479f16f355e61 (patch) | |
tree | 10a26f7d5a3eb6cfd2e049764c1f83e92e3cf48b /drivers/gpu/drm/i915 | |
parent | ac29fc66855b79c2960c63a4a66952d5b721d698 (diff) | |
download | lwn-679fd3ebabc23dec33d42525b19479f16f355e61.tar.gz lwn-679fd3ebabc23dec33d42525b19479f16f355e61.zip |
drm/i915/gvt: Fix unsafe locking caused by spin_unlock_bh
The caller of shadow_context_status_change may disable irqs. So it is not
safe to use spin_unlock_bh in such context. Let's switch to irqsave version
for safety.
------------[ cut here ]------------
WARNING: CPU: 2 PID: 4504 at kernel/softirq.c:161 __local_bh_enable_ip+0x46/0x60
[ 168.797710] Hardware name: Dell Inc. OptiPlex 7040/0Y7WYT, BIOS 1.2.8 01/26/2016
[ 168.797712] task: ffff8c693d22db80 task.stack: ffffb51b482bc000
[ 168.797718] RIP: 0010:__local_bh_enable_ip+0x46/0x60
[ 168.797721] RSP: 0018:ffffb51b482bfa10 EFLAGS: 00010046
[ 168.797724] RAX: 0000000000000046 RBX: ffff8c6900278000 RCX: 00000000ffffffff
[ 168.797726] RDX: 0000000000000001 RSI: 0000000000000200 RDI: ffffffffc06a0330
[ 168.797728] RBP: ffffb51b482bfa10 R08: 0000000000000000 R09: ffff8c690027cb90
[ 168.797730] R10: ffffb51b482bfa40 R11: 00000004072f0001 R12: 0000000000000000
[ 168.797732] R13: 0000000000000000 R14: ffff8c690027ca9c R15: 0000000000000000
[ 168.797735] FS: 00007ff187c56700(0000) GS:ffff8c6959d00000(0000) knlGS:0000000000000000
[ 168.797738] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 168.797740] CR2: 0000562bc0c3991f CR3: 0000000430614006 CR4: 00000000003606e0
[ 168.797742] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 168.797744] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 168.797745] Call Trace:
[ 168.797755] _raw_spin_unlock_bh+0x1e/0x20
[ 168.797826] shadow_context_status_change+0x120/0x1e0 [i915]
[ 168.797831] notifier_call_chain+0x4a/0x70
[ 168.797834] atomic_notifier_call_chain+0x1a/0x20
[ 168.797896] execlists_cancel_port_requests+0x4f/0x80 [i915]
[ 168.797956] reset_common_ring+0x30/0x100 [i915]
[ 168.798007] i915_gem_reset_engine+0x114/0x330 [i915]
[ 168.798060] ? i915_gem_retire_requests+0x75/0x180 [i915]
[ 168.798111] i915_gem_reset+0x3e/0xb0 [i915]
[ 168.798149] i915_reset+0x10b/0x1c0 [i915]
[ 168.798187] i915_reset_device+0x209/0x220 [i915]
[ 168.798225] ? gen8_gt_irq_ack+0x170/0x170 [i915]
[ 168.798229] ? __queue_work+0x430/0x430
[ 168.798270] i915_handle_error+0x285/0x420 [i915]
[ 168.798275] ? mntput+0x24/0x40
[ 168.798281] ? terminate_walk+0x8e/0xf0
[ 168.798328] i915_wedged_set+0x84/0xc0 [i915]
[ 168.798333] simple_attr_write+0xab/0xc0
[ 168.798337] full_proxy_write+0x54/0x90
[ 168.798343] __vfs_write+0x37/0x170
[ 168.798349] ? common_file_perm+0x4c/0x100
[ 168.798355] ? apparmor_file_permission+0x1a/0x20
[ 168.798361] ? security_file_permission+0x3b/0xc0
[ 168.798365] vfs_write+0xb8/0x1b0
[ 168.798370] SyS_write+0x55/0xc0
[ 168.798376] entry_SYSCALL_64_fastpath+0x1e/0xa9
Fixes: 0e86cc9 ("drm/i915/gvt: implement per-vm mmio switching optimization")
Signed-off-by: Changbin Du <changbin.du@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/gvt/scheduler.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index f6ded475bb2c..f031234290f6 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -140,9 +140,10 @@ static int shadow_context_status_change(struct notifier_block *nb, struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; enum intel_engine_id ring_id = req->engine->id; struct intel_vgpu_workload *workload; + unsigned long flags; if (!is_gvt_request(req)) { - spin_lock_bh(&scheduler->mmio_context_lock); + spin_lock_irqsave(&scheduler->mmio_context_lock, flags); if (action == INTEL_CONTEXT_SCHEDULE_IN && scheduler->engine_owner[ring_id]) { /* Switch ring from vGPU to host. */ @@ -150,7 +151,7 @@ static int shadow_context_status_change(struct notifier_block *nb, NULL, ring_id); scheduler->engine_owner[ring_id] = NULL; } - spin_unlock_bh(&scheduler->mmio_context_lock); + spin_unlock_irqrestore(&scheduler->mmio_context_lock, flags); return NOTIFY_OK; } @@ -161,7 +162,7 @@ static int shadow_context_status_change(struct notifier_block *nb, switch (action) { case INTEL_CONTEXT_SCHEDULE_IN: - spin_lock_bh(&scheduler->mmio_context_lock); + spin_lock_irqsave(&scheduler->mmio_context_lock, flags); if (workload->vgpu != scheduler->engine_owner[ring_id]) { /* Switch ring from host to vGPU or vGPU to vGPU. */ intel_gvt_switch_mmio(scheduler->engine_owner[ring_id], @@ -170,7 +171,7 @@ static int shadow_context_status_change(struct notifier_block *nb, } else gvt_dbg_sched("skip ring %d mmio switch for vgpu%d\n", ring_id, workload->vgpu->id); - spin_unlock_bh(&scheduler->mmio_context_lock); + spin_unlock_irqrestore(&scheduler->mmio_context_lock, flags); atomic_set(&workload->shadow_ctx_active, 1); break; case INTEL_CONTEXT_SCHEDULE_OUT: |