Commit 255fc1703e42 ("drm/i915/gem: Calculate object page offset for
partial memory mapping") introduced a new offset that affects
r.sgt.curr value. This field is used in remap_sg() function, in
set_pte_at() call and changing its value causes page table entry to
also be affected (see set_ptes() description).
Example:
 1) upon entering remap_sg() r.sgt.curr could have already been changed to
  a value equal to or greater than r.sgt.max,
 2) set_pte_at() uses r.sgt.curr to map a page entry from another segment
  to the current one,
 3) r->sgt pointer is moved to the next entry returned from __sg_iter()
  only once,
 3) the memory of the mismapped page might become unavailabe (accessing
  some addresses causes -EFAULT).

This patch moves current r->sgt pointer as many segments, as initial
r.sgt.curr is still larger than r.sgt.max.

Signed-off-by: Krzysztof Karas <[email protected]>
---
 drivers/gpu/drm/i915/i915_mm.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_mm.c b/drivers/gpu/drm/i915/i915_mm.c
index f5c97a620962..9a140840214b 100644
--- a/drivers/gpu/drm/i915/i915_mm.c
+++ b/drivers/gpu/drm/i915/i915_mm.c
@@ -51,10 +51,22 @@ static inline unsigned long sgt_pfn(const struct remap_pfn 
*r)
 static int remap_sg(pte_t *pte, unsigned long addr, void *data)
 {
        struct remap_pfn *r = data;
+       unsigned int sgt_offset;
 
        if (GEM_WARN_ON(!r->sgt.sgp))
                return -EINVAL;
 
+       if (r->sgt.curr == r->sgt.max) {
+               r->sgt = __sgt_iter(__sg_next(r->sgt.sgp), use_dma(r->iobase));
+       } else if (r->sgt.curr > r->sgt.max) {
+               sgt_offset = r->sgt.curr;
+               while (sgt_offset >= r->sgt.max) {
+                       sgt_offset -= r->sgt.max;
+                       r->sgt = __sgt_iter(__sg_next(r->sgt.sgp), 
use_dma(r->iobase));
+               }
+               r->sgt.curr = sgt_offset;
+       }
+
        /* Special PTE are not associated with any struct page */
        set_pte_at(r->mm, addr, pte,
                   pte_mkspecial(pfn_pte(sgt_pfn(r), r->prot)));
-- 
2.43.0

Reply via email to