drm/i915/gvt: Missed to cancel dma map for ggtt entries
authorChangbin Du <changbin.du@intel.com>
Tue, 27 Mar 2018 07:35:14 +0000 (15:35 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Fri, 30 Mar 2018 06:47:17 +0000 (14:47 +0800)
We have canceled dma map for ppgtt entries. Also we need to do it for
ggtt entries when them are invalidated.

This can fix task hung issue as:
[13517.791767] INFO: task gvt_service_thr:1081 blocked for more than 120 seconds.
[13517.792584] Not tainted 4.14.15+ #3
[13517.793417] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[13517.794267] gvt_service_thr D 0 1081 2 0x80000000
[13517.795132] Call Trace:
[13517.795996] ? __schedule+0x493/0x77b
[13517.796859] schedule+0x79/0x82
[13517.797740] schedule_preempt_disabled+0x5/0x6
[13517.798614] __mutex_lock.isra.0+0x2b5/0x445
[13517.799504] ? __switch_to_asm+0x24/0x60
[13517.800381] ? intel_gvt_cleanup+0x10/0x10
[13517.801261] ? intel_gvt_schedule+0x19/0x2b9
[13517.802107] intel_gvt_schedule+0x19/0x2b9
[13517.802954] ? intel_gvt_cleanup+0x10/0x10
[13517.803824] gvt_service_thread+0xe3/0x10d
[13517.804704] ? wait_woken+0x68/0x68
[13517.805588] kthread+0x118/0x120
[13517.806478] ? kthread_create_on_node+0x3a/0x3a
[13517.807381] ? call_usermodehelper_exec_async+0x113/0x11a
[13517.808307] ret_from_fork+0x35/0x40

v3: split out ggtt reset case.
v2: also unmap ggtt during reset.

Signed-off-by: Changbin Du <changbin.du@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
drivers/gpu/drm/i915/gvt/gtt.c

index d292812315077469848dc536a36fb7fa086d003d..8c9477c272be4fc676846e71b24ceb40b5c6567a 100644 (file)
@@ -530,6 +530,16 @@ static void ggtt_set_guest_entry(struct intel_vgpu_mm *mm,
                           false, 0, mm->vgpu);
 }
 
+static void ggtt_get_host_entry(struct intel_vgpu_mm *mm,
+               struct intel_gvt_gtt_entry *entry, unsigned long index)
+{
+       struct intel_gvt_gtt_pte_ops *pte_ops = mm->vgpu->gvt->gtt.pte_ops;
+
+       GEM_BUG_ON(mm->type != INTEL_GVT_MM_GGTT);
+
+       pte_ops->get_entry(NULL, entry, index, false, 0, mm->vgpu);
+}
+
 static void ggtt_set_host_entry(struct intel_vgpu_mm *mm,
                struct intel_gvt_gtt_entry *entry, unsigned long index)
 {
@@ -1818,6 +1828,18 @@ int intel_vgpu_emulate_ggtt_mmio_read(struct intel_vgpu *vgpu, unsigned int off,
        return ret;
 }
 
+static void ggtt_invalidate_pte(struct intel_vgpu *vgpu,
+               struct intel_gvt_gtt_entry *entry)
+{
+       struct intel_gvt_gtt_pte_ops *pte_ops = vgpu->gvt->gtt.pte_ops;
+       unsigned long pfn;
+
+       pfn = pte_ops->get_pfn(entry);
+       if (pfn != vgpu->gvt->gtt.scratch_mfn)
+               intel_gvt_hypervisor_dma_unmap_guest_page(vgpu,
+                                               pfn << PAGE_SHIFT);
+}
+
 static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
        void *p_data, unsigned int bytes)
 {
@@ -1844,10 +1866,10 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
 
        memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data,
                        bytes);
-       m = e;
 
        if (ops->test_present(&e)) {
                gfn = ops->get_pfn(&e);
+               m = e;
 
                /* one PTE update may be issued in multiple writes and the
                 * first write may not construct a valid gfn
@@ -1868,8 +1890,12 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
                        ops->set_pfn(&m, gvt->gtt.scratch_mfn);
                } else
                        ops->set_pfn(&m, dma_addr >> PAGE_SHIFT);
-       } else
+       } else {
+               ggtt_get_host_entry(ggtt_mm, &m, g_gtt_index);
+               ggtt_invalidate_pte(vgpu, &m);
                ops->set_pfn(&m, gvt->gtt.scratch_mfn);
+               ops->clear_present(&m);
+       }
 
 out:
        ggtt_set_host_entry(ggtt_mm, &m, g_gtt_index);