Skip to content

Commit 293837b

Browse files
committed
Revert "i915: fix remap_io_sg to verify the pgprot"
This reverts commit b12d691. It turns out this is not ready for primetime yet. The intentions are good, but using remap_pfn_range() requires that there is nothing already mapped in the area, and the i915 code seems to very much intentionally remap the same area multiple times. That will then just trigger the BUG_ON(!pte_none(*pte)); in mm/memory.c: remap_pte_range(). There are also reports of mapping type inconsistencies, resulting in warnings and in screen corruption. Link: https://lore.kernel.org/lkml/20210519024322.GA29704@xsang-OptiPlex-9020/ Link: https://lore.kernel.org/lkml/YKUjvoaKKggAmpIR@sf/ Link: https://lore.kernel.org/lkml/[email protected]/ Reported-by: kernel test robot <[email protected]> Reported-by: Kalle Valo <[email protected]> Reported-by: Hans de Goede <[email protected]> Reported-by: Sergei Trofimovich <[email protected]> Acked-by: Christoph Hellwig <[email protected]> Cc: Chris Wilson <[email protected]> Cc: Daniel Vetter <[email protected]> Cc: Jani Nikula <[email protected]> Cc: Joonas Lahtinen <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Rodrigo Vivi <[email protected]> Cc: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 8ac91e6 commit 293837b

File tree

1 file changed

+50
-23
lines changed

1 file changed

+50
-23
lines changed

drivers/gpu/drm/i915/i915_mm.c

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,46 @@
2828

2929
#include "i915_drv.h"
3030

31-
#define EXPECTED_FLAGS (VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP)
31+
struct remap_pfn {
32+
struct mm_struct *mm;
33+
unsigned long pfn;
34+
pgprot_t prot;
35+
36+
struct sgt_iter sgt;
37+
resource_size_t iobase;
38+
};
3239

3340
#define use_dma(io) ((io) != -1)
3441

42+
static inline unsigned long sgt_pfn(const struct remap_pfn *r)
43+
{
44+
if (use_dma(r->iobase))
45+
return (r->sgt.dma + r->sgt.curr + r->iobase) >> PAGE_SHIFT;
46+
else
47+
return r->sgt.pfn + (r->sgt.curr >> PAGE_SHIFT);
48+
}
49+
50+
static int remap_sg(pte_t *pte, unsigned long addr, void *data)
51+
{
52+
struct remap_pfn *r = data;
53+
54+
if (GEM_WARN_ON(!r->sgt.sgp))
55+
return -EINVAL;
56+
57+
/* Special PTE are not associated with any struct page */
58+
set_pte_at(r->mm, addr, pte,
59+
pte_mkspecial(pfn_pte(sgt_pfn(r), r->prot)));
60+
r->pfn++; /* track insertions in case we need to unwind later */
61+
62+
r->sgt.curr += PAGE_SIZE;
63+
if (r->sgt.curr >= r->sgt.max)
64+
r->sgt = __sgt_iter(__sg_next(r->sgt.sgp), use_dma(r->iobase));
65+
66+
return 0;
67+
}
68+
69+
#define EXPECTED_FLAGS (VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP)
70+
3571
/**
3672
* remap_io_sg - remap an IO mapping to userspace
3773
* @vma: user vma to map to
@@ -46,7 +82,12 @@ int remap_io_sg(struct vm_area_struct *vma,
4682
unsigned long addr, unsigned long size,
4783
struct scatterlist *sgl, resource_size_t iobase)
4884
{
49-
unsigned long pfn, len, remapped = 0;
85+
struct remap_pfn r = {
86+
.mm = vma->vm_mm,
87+
.prot = vma->vm_page_prot,
88+
.sgt = __sgt_iter(sgl, use_dma(iobase)),
89+
.iobase = iobase,
90+
};
5091
int err;
5192

5293
/* We rely on prevalidation of the io-mapping to skip track_pfn(). */
@@ -55,25 +96,11 @@ int remap_io_sg(struct vm_area_struct *vma,
5596
if (!use_dma(iobase))
5697
flush_cache_range(vma, addr, size);
5798

58-
do {
59-
if (use_dma(iobase)) {
60-
if (!sg_dma_len(sgl))
61-
break;
62-
pfn = (sg_dma_address(sgl) + iobase) >> PAGE_SHIFT;
63-
len = sg_dma_len(sgl);
64-
} else {
65-
pfn = page_to_pfn(sg_page(sgl));
66-
len = sgl->length;
67-
}
68-
69-
err = remap_pfn_range(vma, addr + remapped, pfn, len,
70-
vma->vm_page_prot);
71-
if (err)
72-
break;
73-
remapped += len;
74-
} while ((sgl = __sg_next(sgl)));
75-
76-
if (err)
77-
zap_vma_ptes(vma, addr, remapped);
78-
return err;
99+
err = apply_to_page_range(r.mm, addr, size, remap_sg, &r);
100+
if (unlikely(err)) {
101+
zap_vma_ptes(vma, addr, r.pfn << PAGE_SHIFT);
102+
return err;
103+
}
104+
105+
return 0;
79106
}

0 commit comments

Comments
 (0)