From 679fd3ebabc23dec33d42525b19479f16f355e61 Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Mon, 13 Nov 2017 14:58:31 +0800 Subject: 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 Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/scheduler.c | 9 +++++---- 1 file 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: -- cgit From bf3a26b3cba59e2eee91cec3de6fdb4e8e670295 Mon Sep 17 00:00:00 2001 From: Weinan Li Date: Tue, 21 Nov 2017 10:54:41 +0800 Subject: drm/i915/gvt: remove skl_misc_ctl_write handler With different settings of compressed data hash mode between VMs and host may cause gpu issues. Commit: 1999f108c ("drm/i915/gvt: Disable compression workaround for Gen9") disable compression workaround of guest in gvt host to align with host. Commit: 93564044f ("drm/i915: Switch over to the LLC/eLLC hotspot avoidance hash mode for CCS") add compression workaround, then we can remove the skl_misc_ctl_write hanlder. Better solution should be always keeping same settings as host, and bypass the write request from VMs, but it need to fetch data from host's "Context". Cc: Zhi Wang Signed-off-by: Weinan Li Signed-off-by: Xiong Zhang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/handlers.c | 45 +++++-------------------------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index a5bed2e71b92..44cd5ff5e97d 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1381,40 +1381,6 @@ static int skl_power_well_ctl_write(struct intel_vgpu *vgpu, return intel_vgpu_default_mmio_write(vgpu, offset, &v, bytes); } -static int skl_misc_ctl_write(struct intel_vgpu *vgpu, unsigned int offset, - void *p_data, unsigned int bytes) -{ - struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; - u32 v = *(u32 *)p_data; - - if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)) - return intel_vgpu_default_mmio_write(vgpu, - offset, p_data, bytes); - - switch (offset) { - case 0x4ddc: - /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */ - vgpu_vreg(vgpu, offset) = v & ~(1 << 31); - break; - case 0x42080: - /* bypass WaCompressedResourceDisplayNewHashMode */ - vgpu_vreg(vgpu, offset) = v & ~(1 << 15); - break; - case 0xe194: - /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */ - vgpu_vreg(vgpu, offset) = v & ~(1 << 8); - break; - case 0x7014: - /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */ - vgpu_vreg(vgpu, offset) = v & ~(1 << 13); - break; - default: - return -EINVAL; - } - - return 0; -} - static int skl_lcpll_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { @@ -1671,8 +1637,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_DFH(GAM_ECOCHK, D_ALL, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); - MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, - skl_misc_ctl_write); + MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, + NULL, NULL); MMIO_DFH(0x9030, D_ALL, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(0x20a0, D_ALL, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(0x2420, D_ALL, F_CMD_ACCESS, NULL, NULL); @@ -2564,8 +2530,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt) MMIO_D(0x6e570, D_BDW_PLUS); MMIO_D(0x65f10, D_BDW_PLUS); - MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, - skl_misc_ctl_write); + MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); MMIO_DFH(0xe188, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); MMIO_DFH(HALF_SLICE_CHICKEN2, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); @@ -2615,8 +2580,8 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS); MMIO_DFH(GEN9_GAMT_ECO_REG_RW_IA, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); - MMIO_DH(0x4ddc, D_SKL_PLUS, NULL, skl_misc_ctl_write); - MMIO_DH(0x42080, D_SKL_PLUS, NULL, skl_misc_ctl_write); + MMIO_DH(0x4ddc, D_SKL_PLUS, NULL, NULL); + MMIO_DH(0x42080, D_SKL_PLUS, NULL, NULL); MMIO_D(0x45504, D_SKL_PLUS); MMIO_D(0x45520, D_SKL_PLUS); MMIO_D(0x46000, D_SKL_PLUS); -- cgit From c3c80f0736bb2767fab983d1ae53252b2ddd405d Mon Sep 17 00:00:00 2001 From: fred gao Date: Tue, 14 Nov 2017 17:09:35 +0800 Subject: drm/i915/gvt: Move request alloc to dispatch_workload path only Previously the performance is improved through the workload auditing and shadowing ahead of vGPU scheduling, however, there is the case that more requests are allocated in submit_context before the previous request is added, the timeline will hold its seqno which is later. This patch is to move the request alloc to dispatch_workload function, where is the same place as request is added. It will fix the issue of kernel BUG for (timeline->seqno != request->fence.seqno) check when add_request. Fixes: 89ea20b930cb ("drm/i915/gvt: Factor out scan and shadow from workload dispatch") Signed-off-by: Chuanxiao Dong Signed-off-by: fred gao Signed-off-by: Zhenyu Wang (cherry picked from commit f2880e04f3a5419366926182fc97a3c2e4fd8f2a) --- drivers/gpu/drm/i915/gvt/execlist.c | 6 ++++++ drivers/gpu/drm/i915/gvt/scheduler.c | 24 ++++++++++++++++++++---- drivers/gpu/drm/i915/gvt/scheduler.h | 3 +++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 4427be18e4a9..940cdaaa3f24 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -496,6 +496,12 @@ static int prepare_execlist_workload(struct intel_vgpu_workload *workload) goto err_unpin_mm; } + ret = intel_gvt_generate_request(workload); + if (ret) { + gvt_vgpu_err("fail to generate request\n"); + goto err_unpin_mm; + } + ret = prepare_shadow_batch_buffer(workload); if (ret) { gvt_vgpu_err("fail to prepare_shadow_batch_buffer\n"); diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index f031234290f6..3ac1dc97a7a0 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -254,7 +254,6 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; struct intel_engine_cs *engine = dev_priv->engine[ring_id]; - struct drm_i915_gem_request *rq; struct intel_vgpu *vgpu = workload->vgpu; struct intel_ring *ring; int ret; @@ -300,6 +299,26 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) ret = populate_shadow_context(workload); if (ret) goto err_unpin; + workload->shadowed = true; + return 0; + +err_unpin: + engine->context_unpin(engine, shadow_ctx); +err_shadow: + release_shadow_wa_ctx(&workload->wa_ctx); +err_scan: + return ret; +} + +int intel_gvt_generate_request(struct intel_vgpu_workload *workload) +{ + int ring_id = workload->ring_id; + struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; + struct intel_engine_cs *engine = dev_priv->engine[ring_id]; + struct drm_i915_gem_request *rq; + struct intel_vgpu *vgpu = workload->vgpu; + struct i915_gem_context *shadow_ctx = vgpu->shadow_ctx; + int ret; rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); if (IS_ERR(rq)) { @@ -314,14 +333,11 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) ret = copy_workload_to_ring_buffer(workload); if (ret) goto err_unpin; - workload->shadowed = true; return 0; err_unpin: engine->context_unpin(engine, shadow_ctx); -err_shadow: release_shadow_wa_ctx(&workload->wa_ctx); -err_scan: return ret; } diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index 2d694f6c0907..b9f872204d7e 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h @@ -142,4 +142,7 @@ int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu); void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu); void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx); + +int intel_gvt_generate_request(struct intel_vgpu_workload *workload); + #endif -- cgit From 7e60590208942de856fd43956ccebd19e71d686f Mon Sep 17 00:00:00 2001 From: Xiaolin Zhang Date: Thu, 16 Nov 2017 16:54:23 +0800 Subject: drm/i915/gvt: enabled pipe A default on creating vgpu when i915 driver unloading, it will shutdown all CRTCs and it will introudce kernel panic when conducting igt drv_module_reload test case under guest environment (bug reported by XENGT-468) as below: BUG: unable to handle kernel NULL pointer dereference at 0000000000000070 IP: intel_edp_backlight_off+0xe/0x7c [i915] RIP: 0010:intel_edp_backlight_off+0xe/0x7c [i915] Call Trace: intel_disable_ddi+0xb3/0xbc [i915] intel_modeset_setup_hw_state+0x654/0xb4c [i915] intel_modeset_init+0x9f1/0xe69 [i915] ? intel_i2c_reset+0x3d/0x40 [i915] ? intel_setup_gmbus+0xba/0x249 [i915] i915_driver_load+0xae5/0xcc0 [i915] i915_pci_probe+0x3a/0x3c [i915] local_pci_probe+0x38/0x7b pci_device_probe+0xec/0x12b driver_probe_device+0x134/0x294 __driver_attach+0x6a/0x8c ? driver_probe_device+0x294/0x294 bus_for_each_dev+0x68/0x80 driver_attach+0x19/0x1b bus_add_driver+0xea/0x1d3 ? 0xffffffffa03cd000 driver_register+0x85/0xc1 ? 0xffffffffa03cd000 __pci_register_driver+0x55/0x57 i915_init+0x57/0x5a [i915] do_one_initcall+0x8a/0x12e ? __vunmap+0x8d/0x93 ? kmem_cache_alloc_trace+0x96/0x11c do_init_module+0x5a/0x1e1 in this case, active connector detected but no active pipe available, so it will hang to disable connector. to fix, on vgpu creating, to report active pipe available for guest. Signed-off-by: Xiaolin Zhang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 3c318439a659..355120865efd 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -282,6 +282,7 @@ static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num) static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num, int type, unsigned int resolution) { + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num); if (WARN_ON(resolution >= GVT_EDID_NUM)) @@ -307,6 +308,7 @@ static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num, port->type = type; emulate_monitor_status_change(vgpu); + vgpu_vreg(vgpu, PIPECONF(PIPE_A)) |= PIPECONF_ENABLE; return 0; } -- cgit From b721b65af4eb46df6a1d9e34b14003225e403565 Mon Sep 17 00:00:00 2001 From: Xiong Zhang Date: Tue, 28 Nov 2017 07:29:54 +0800 Subject: drm/i915/gvt: Correct ADDR_4K/2M/1G_MASK definition For ADDR_4K_MASK, bit[45..12] should be 1, all other bits should be 0. The current definition wrongly set bit[46] as 1 also. This path fixes this. v2: Add commit message, fixes and cc stable.(Zhenyu) Fixes: 2707e4446688("drm/i915/gvt: vGPU graphics memory virtualization") Signed-off-by: Xiong Zhang Cc: stable@vger.kernel.org Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gtt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 2801d70579d8..8e331142badb 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -311,9 +311,9 @@ static inline int gtt_set_entry64(void *pt, #define GTT_HAW 46 -#define ADDR_1G_MASK (((1UL << (GTT_HAW - 30 + 1)) - 1) << 30) -#define ADDR_2M_MASK (((1UL << (GTT_HAW - 21 + 1)) - 1) << 21) -#define ADDR_4K_MASK (((1UL << (GTT_HAW - 12 + 1)) - 1) << 12) +#define ADDR_1G_MASK (((1UL << (GTT_HAW - 30)) - 1) << 30) +#define ADDR_2M_MASK (((1UL << (GTT_HAW - 21)) - 1) << 21) +#define ADDR_4K_MASK (((1UL << (GTT_HAW - 12)) - 1) << 12) static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e) { -- cgit