aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.c58
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.h2
2 files changed, 60 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 23296547da95..4efec8fa6c1d 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -1592,6 +1592,7 @@ static struct intel_vgpu_mm *intel_vgpu_create_ggtt_mm(struct intel_vgpu *vgpu)
1592 vgpu_free_mm(mm); 1592 vgpu_free_mm(mm);
1593 return ERR_PTR(-ENOMEM); 1593 return ERR_PTR(-ENOMEM);
1594 } 1594 }
1595 mm->ggtt_mm.last_partial_off = -1UL;
1595 1596
1596 return mm; 1597 return mm;
1597} 1598}
@@ -1616,6 +1617,7 @@ void _intel_vgpu_mm_release(struct kref *mm_ref)
1616 invalidate_ppgtt_mm(mm); 1617 invalidate_ppgtt_mm(mm);
1617 } else { 1618 } else {
1618 vfree(mm->ggtt_mm.virtual_ggtt); 1619 vfree(mm->ggtt_mm.virtual_ggtt);
1620 mm->ggtt_mm.last_partial_off = -1UL;
1619 } 1621 }
1620 1622
1621 vgpu_free_mm(mm); 1623 vgpu_free_mm(mm);
@@ -1868,6 +1870,62 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
1868 memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data, 1870 memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data,
1869 bytes); 1871 bytes);
1870 1872
1873 /* If ggtt entry size is 8 bytes, and it's split into two 4 bytes
1874 * write, we assume the two 4 bytes writes are consecutive.
1875 * Otherwise, we abort and report error
1876 */
1877 if (bytes < info->gtt_entry_size) {
1878 if (ggtt_mm->ggtt_mm.last_partial_off == -1UL) {
1879 /* the first partial part*/
1880 ggtt_mm->ggtt_mm.last_partial_off = off;
1881 ggtt_mm->ggtt_mm.last_partial_data = e.val64;
1882 return 0;
1883 } else if ((g_gtt_index ==
1884 (ggtt_mm->ggtt_mm.last_partial_off >>
1885 info->gtt_entry_size_shift)) &&
1886 (off != ggtt_mm->ggtt_mm.last_partial_off)) {
1887 /* the second partial part */
1888
1889 int last_off = ggtt_mm->ggtt_mm.last_partial_off &
1890 (info->gtt_entry_size - 1);
1891
1892 memcpy((void *)&e.val64 + last_off,
1893 (void *)&ggtt_mm->ggtt_mm.last_partial_data +
1894 last_off, bytes);
1895
1896 ggtt_mm->ggtt_mm.last_partial_off = -1UL;
1897 } else {
1898 int last_offset;
1899
1900 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",
1901 ggtt_mm->ggtt_mm.last_partial_off, off,
1902 bytes, info->gtt_entry_size);
1903
1904 /* set host ggtt entry to scratch page and clear
1905 * virtual ggtt entry as not present for last
1906 * partially write offset
1907 */
1908 last_offset = ggtt_mm->ggtt_mm.last_partial_off &
1909 (~(info->gtt_entry_size - 1));
1910
1911 ggtt_get_host_entry(ggtt_mm, &m, last_offset);
1912 ggtt_invalidate_pte(vgpu, &m);
1913 ops->set_pfn(&m, gvt->gtt.scratch_mfn);
1914 ops->clear_present(&m);
1915 ggtt_set_host_entry(ggtt_mm, &m, last_offset);
1916 ggtt_invalidate(gvt->dev_priv);
1917
1918 ggtt_get_guest_entry(ggtt_mm, &e, last_offset);
1919 ops->clear_present(&e);
1920 ggtt_set_guest_entry(ggtt_mm, &e, last_offset);
1921
1922 ggtt_mm->ggtt_mm.last_partial_off = off;
1923 ggtt_mm->ggtt_mm.last_partial_data = e.val64;
1924
1925 return 0;
1926 }
1927 }
1928
1871 if (ops->test_present(&e)) { 1929 if (ops->test_present(&e)) {
1872 gfn = ops->get_pfn(&e); 1930 gfn = ops->get_pfn(&e);
1873 m = e; 1931 m = e;
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
index 3792f2b7f4ff..97e62647418a 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.h
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -150,6 +150,8 @@ struct intel_vgpu_mm {
150 } ppgtt_mm; 150 } ppgtt_mm;
151 struct { 151 struct {
152 void *virtual_ggtt; 152 void *virtual_ggtt;
153 unsigned long last_partial_off;
154 u64 last_partial_data;
153 } ggtt_mm; 155 } ggtt_mm;
154 }; 156 };
155}; 157};