From f42259ef810ce83f3e1a8ea4ce12dfda873fbe44 Mon Sep 17 00:00:00 2001 From: Hang Yuan Date: Wed, 19 Sep 2018 14:42:09 +0800 Subject: drm/i915/gvt: invalidate old ggtt page when update ggtt entry Previously only cancelled dma map of a ggtt page when the ggtt entry was cleared. This patch will cancel dma map of an old ggtt page as well when the ggtt entry is updated with new page address. Fixes: 7598e8700e9a(drm/i915/gvt: Missed to cancel dma map for ggtt entries) Signed-off-by: Hang Yuan Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gtt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/gvt') diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 00aad8164dec..c11e353ca904 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -2259,16 +2259,18 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, } else ops->set_pfn(&m, dma_addr >> PAGE_SHIFT); } 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_guest_entry(ggtt_mm, &e, g_gtt_index); + + ggtt_get_host_entry(ggtt_mm, &e, g_gtt_index); + ggtt_invalidate_pte(vgpu, &e); + ggtt_set_host_entry(ggtt_mm, &m, g_gtt_index); ggtt_invalidate(gvt->dev_priv); - ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index); return 0; } -- cgit v1.2.3 From bc0686ff5fad7a842cc88377439e78be87fedc80 Mon Sep 17 00:00:00 2001 From: Hang Yuan Date: Wed, 19 Sep 2018 14:42:10 +0800 Subject: drm/i915/gvt: support inconsecutive partial gtt entry write Previously we assumed two 4-byte writes to the same PTE coming in sequence. But recently we observed inconsecutive partial write happening as well. So this patch enhances the previous solution. It now uses a list to save more partial writes. If one partial write can be combined with another one in the list to construct a full PTE, update its shadow entry. Otherwise, save the partial write in the list. v2: invalidate old entry and flush ggtt (Zhenyu) v3: split old ggtt page unmap to another patch (Zhenyu) v4: refine codes (Zhenyu) Signed-off-by: Hang Yuan Cc: Yan Zhao Cc: Xiaolin Zhang Cc: Zhenyu Wang Reviewed-by: Xiaolin Zhang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gtt.c | 107 ++++++++++++++++++++--------------------- drivers/gpu/drm/i915/gvt/gtt.h | 9 +++- 2 files changed, 60 insertions(+), 56 deletions(-) (limited to 'drivers/gpu/drm/i915/gvt') diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index c11e353ca904..919de5a1bafb 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1901,7 +1901,6 @@ static struct intel_vgpu_mm *intel_vgpu_create_ggtt_mm(struct intel_vgpu *vgpu) vgpu_free_mm(mm); return ERR_PTR(-ENOMEM); } - mm->ggtt_mm.last_partial_off = -1UL; return mm; } @@ -1926,7 +1925,6 @@ void _intel_vgpu_mm_release(struct kref *mm_ref) invalidate_ppgtt_mm(mm); } else { vfree(mm->ggtt_mm.virtual_ggtt); - mm->ggtt_mm.last_partial_off = -1UL; } vgpu_free_mm(mm); @@ -2164,6 +2162,8 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, struct intel_gvt_gtt_entry e, m; dma_addr_t dma_addr; int ret; + struct intel_gvt_partial_pte *partial_pte, *pos, *n; + bool partial_update = false; if (bytes != 4 && bytes != 8) return -EINVAL; @@ -2174,68 +2174,57 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, if (!vgpu_gmadr_is_valid(vgpu, gma)) return 0; - ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index); - + e.type = GTT_TYPE_GGTT_PTE; memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data, bytes); /* If ggtt entry size is 8 bytes, and it's split into two 4 bytes - * write, we assume the two 4 bytes writes are consecutive. - * Otherwise, we abort and report error + * write, save the first 4 bytes in a list and update virtual + * PTE. Only update shadow PTE when the second 4 bytes comes. */ if (bytes < info->gtt_entry_size) { - if (ggtt_mm->ggtt_mm.last_partial_off == -1UL) { - /* the first partial part*/ - ggtt_mm->ggtt_mm.last_partial_off = off; - ggtt_mm->ggtt_mm.last_partial_data = e.val64; - return 0; - } else if ((g_gtt_index == - (ggtt_mm->ggtt_mm.last_partial_off >> - info->gtt_entry_size_shift)) && - (off != ggtt_mm->ggtt_mm.last_partial_off)) { - /* the second partial part */ - - int last_off = ggtt_mm->ggtt_mm.last_partial_off & - (info->gtt_entry_size - 1); - - memcpy((void *)&e.val64 + last_off, - (void *)&ggtt_mm->ggtt_mm.last_partial_data + - last_off, bytes); - - ggtt_mm->ggtt_mm.last_partial_off = -1UL; - } else { - int last_offset; - - gvt_vgpu_err("failed to populate guest ggtt entry: abnormal ggtt entry write sequence, last_partial_off=%lx, offset=%x, bytes=%d, ggtt entry size=%d\n", - ggtt_mm->ggtt_mm.last_partial_off, off, - bytes, info->gtt_entry_size); - - /* set host ggtt entry to scratch page and clear - * virtual ggtt entry as not present for last - * partially write offset - */ - last_offset = ggtt_mm->ggtt_mm.last_partial_off & - (~(info->gtt_entry_size - 1)); - - ggtt_get_host_entry(ggtt_mm, &m, last_offset); - ggtt_invalidate_pte(vgpu, &m); - ops->set_pfn(&m, gvt->gtt.scratch_mfn); - ops->clear_present(&m); - ggtt_set_host_entry(ggtt_mm, &m, last_offset); - ggtt_invalidate(gvt->dev_priv); - - ggtt_get_guest_entry(ggtt_mm, &e, last_offset); - ops->clear_present(&e); - ggtt_set_guest_entry(ggtt_mm, &e, last_offset); - - ggtt_mm->ggtt_mm.last_partial_off = off; - ggtt_mm->ggtt_mm.last_partial_data = e.val64; + bool found = false; + + list_for_each_entry_safe(pos, n, + &ggtt_mm->ggtt_mm.partial_pte_list, list) { + if (g_gtt_index == pos->offset >> + info->gtt_entry_size_shift) { + if (off != pos->offset) { + /* the second partial part*/ + int last_off = pos->offset & + (info->gtt_entry_size - 1); + + memcpy((void *)&e.val64 + last_off, + (void *)&pos->data + last_off, + bytes); + + list_del(&pos->list); + kfree(pos); + found = true; + break; + } + + /* update of the first partial part */ + pos->data = e.val64; + ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index); + return 0; + } + } - return 0; + if (!found) { + /* the first partial part */ + partial_pte = kzalloc(sizeof(*partial_pte), GFP_KERNEL); + if (!partial_pte) + return -ENOMEM; + partial_pte->offset = off; + partial_pte->data = e.val64; + list_add_tail(&partial_pte->list, + &ggtt_mm->ggtt_mm.partial_pte_list); + partial_update = true; } } - if (ops->test_present(&e)) { + if (!partial_update && (ops->test_present(&e))) { gfn = ops->get_pfn(&e); m = e; @@ -2428,6 +2417,8 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) intel_vgpu_reset_ggtt(vgpu, false); + INIT_LIST_HEAD(>t->ggtt_mm->ggtt_mm.partial_pte_list); + return create_scratch_page_tree(vgpu); } @@ -2452,6 +2443,14 @@ static void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu) static void intel_vgpu_destroy_ggtt_mm(struct intel_vgpu *vgpu) { + struct intel_gvt_partial_pte *pos; + + list_for_each_entry(pos, + &vgpu->gtt.ggtt_mm->ggtt_mm.partial_pte_list, list) { + gvt_dbg_mm("partial PTE update on hold 0x%lx : 0x%llx\n", + pos->offset, pos->data); + kfree(pos); + } intel_vgpu_destroy_mm(vgpu->gtt.ggtt_mm); vgpu->gtt.ggtt_mm = NULL; } diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h index 7a9b36176efb..a11bfee1e0c8 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.h +++ b/drivers/gpu/drm/i915/gvt/gtt.h @@ -133,6 +133,12 @@ enum intel_gvt_mm_type { #define GVT_RING_CTX_NR_PDPS GEN8_3LVL_PDPES +struct intel_gvt_partial_pte { + unsigned long offset; + u64 data; + struct list_head list; +}; + struct intel_vgpu_mm { enum intel_gvt_mm_type type; struct intel_vgpu *vgpu; @@ -157,8 +163,7 @@ struct intel_vgpu_mm { } ppgtt_mm; struct { void *virtual_ggtt; - unsigned long last_partial_off; - u64 last_partial_data; + struct list_head partial_pte_list; } ggtt_mm; }; }; -- cgit v1.2.3 From 606a745944bc0ebd14f77dfc61ac7d6cb685cefe Mon Sep 17 00:00:00 2001 From: Xinyun Liu Date: Wed, 19 Sep 2018 15:28:53 +0800 Subject: drm/i915/gvt: correct mask setting for CSFE_CHICKEN1 CSFE_CHICKEN1(0x20d4) needs access with mask. This is caught in AcrnGT conformance check test: [drm:intel_gvt_vgpu_conformance_check] *ERROR* gvt: vgpu1 unconformance mmio 0x20d4:0x40004,0x4 Signed-off-by: Xinyun Liu Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/mmio_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/gvt') diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index e872f4847fbe..088a62ab2bc8 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c @@ -144,7 +144,7 @@ static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = { {RCS, GAMT_CHKN_BIT_REG, 0x0, false}, /* 0x4ab8 */ {RCS, GEN9_GAMT_ECO_REG_RW_IA, 0x0, false}, /* 0x4ab0 */ - {RCS, GEN9_CSFE_CHICKEN1_RCS, 0x0, false}, /* 0x20d4 */ + {RCS, GEN9_CSFE_CHICKEN1_RCS, 0xffff, false}, /* 0x20d4 */ {RCS, GEN8_GARBCNTL, 0x0, false}, /* 0xb004 */ {RCS, GEN7_FF_THREAD_MODE, 0x0, false}, /* 0x20a0 */ -- cgit v1.2.3 From 5e7154ff5e8e21dc9acac4f8dba7533552365374 Mon Sep 17 00:00:00 2001 From: Longhe Zheng Date: Tue, 30 Oct 2018 16:12:10 +0800 Subject: drm/i915/gvt: Handle values of EDP_PSR_IMR and EDP_PSR_IIR GVT-g only simulates DP port for guest and leaves EDP_PSR_IMR and EDP_PSR_IIR registers as default MMIO read/write. So guest won't get expected initial values of these registers when initializing the gpu driver, which results in following warning and logs. -------- Interrupt register 0x64838 is not zero: 0xffffffff WARNING: CPU: 1 PID: 157 at drivers/gpu/drm/i915/i915_irq.c:177 gen3_assert_iir_is_zero+0x38/0xa0 Call Trace: gen8_de_irq_postinstall+0xa7/0x400 gen8_irq_postinstall+0x27/0x80 drm_irq_install+0xbc/0x140 i915_driver_load+0xa9d/0xd50 -------- Because GVT-g does not handle EDP(embedded DP) simulation for guests, always set EDP_PSR_IMR and EDP_PSR_IIR to value 0. Signed-off-by: Longhe Zheng Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/handlers.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/gvt') diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 94c1089ecf59..f9002cb1f2a3 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1608,7 +1608,7 @@ static int bxt_gt_disp_pwron_write(struct intel_vgpu *vgpu, return 0; } -static int bxt_edp_psr_imr_iir_write(struct intel_vgpu *vgpu, +static int edp_psr_imr_iir_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { vgpu_vreg(vgpu, offset) = 0; @@ -2613,6 +2613,9 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_DFH(_MMIO(0x1a178), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(_MMIO(0x1a17c), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(_MMIO(0x2217c), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); + + MMIO_DH(EDP_PSR_IMR, D_BDW_PLUS, NULL, edp_psr_imr_iir_write); + MMIO_DH(EDP_PSR_IIR, D_BDW_PLUS, NULL, edp_psr_imr_iir_write); return 0; } @@ -3216,9 +3219,6 @@ static int init_bxt_mmio_info(struct intel_gvt *gvt) MMIO_D(HSW_TVIDEO_DIP_GCP(TRANSCODER_B), D_BXT); MMIO_D(HSW_TVIDEO_DIP_GCP(TRANSCODER_C), D_BXT); - MMIO_DH(EDP_PSR_IMR, D_BXT, NULL, bxt_edp_psr_imr_iir_write); - MMIO_DH(EDP_PSR_IIR, D_BXT, NULL, bxt_edp_psr_imr_iir_write); - MMIO_D(RC6_CTX_BASE, D_BXT); MMIO_D(GEN8_PUSHBUS_CONTROL, D_BXT); -- cgit v1.2.3