[PATCH] drm/i915/gvt: handle partial GGTT PTE update
hang.yuan at intel.com
hang.yuan at intel.com
Mon Dec 18 08:01:16 UTC 2017
From: Hang Yuan <hang.yuan at intel.com>
GVT may receive two 4-byte writes on one GGTT PTE update. Mark incomplete
PTE update. For incomplete update, will not translate GFN to MFN and return
error when try to get gpa from this PTE.
Signed-off-by: Hang Yuan <hang.yuan at intel.com>
---
drivers/gpu/drm/i915/gvt/gtt.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 71a0f2b..2d989ff 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -1788,6 +1788,11 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
gma_ops->gma_to_ggtt_pte_index(gma));
if (ret)
goto err;
+
+ /* incomplete PTE indicated by SW defined BIT[2..1] */
+ if (e.val64 & (BIT(2) | BIT(1)))
+ goto err;
+
gpa = (pte_ops->get_pfn(&e) << I915_GTT_PAGE_SHIFT)
+ (gma & ~I915_GTT_PAGE_MASK);
@@ -1906,6 +1911,7 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
unsigned long gma;
struct intel_gvt_gtt_entry e, m;
int ret;
+ unsigned long access_mask;
if (bytes != 4 && bytes != 8)
return -EINVAL;
@@ -1918,9 +1924,31 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index);
+ /* Two 4-bytes may be issued to write one PTE. PTE BIT 2 and BIT 1 is
+ * ignored in HW. Use these two bits to indicate partial write.
+ */
+ access_mask = e.val64 & (BIT(2) | BIT(1));
+
memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data,
bytes);
+ if (bytes < info->gtt_entry_size)
+ if (off % info->gtt_entry_size)
+ access_mask |= BIT(2);
+ else
+ access_mask |= BIT(1);
+ else
+ access_mask = BIT(2) | BIT(1);
+
+ if (access_mask != (BIT(2) | BIT(1))) {
+ /* partial write case */
+ e.val64 |= access_mask;
+ ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index);
+ return 0;
+ }
+
+ e.val64 &= ~access_mask;
+
if (ops->test_present(&e)) {
ret = gtt_entry_p2m(vgpu, &e, &m);
if (ret) {
--
2.7.4
More information about the intel-gvt-dev
mailing list