Re: 2.6.15-rc1-mm2 0x414 Bad page states

From: Hugh Dickins
Date: Wed Nov 23 2005 - 15:33:16 EST


On Wed, 23 Nov 2005, Dave Airlie wrote:
> On 11/23/05, Michael Frank <mhf@xxxxxxxxxx> wrote:
> >
> > Your patch fixed the DRM issue.

Thanks a lot for the testing and feedback, Michael.

> I'm at a bit of a loss how this can fix the i810 driver, but maybe I'm
> missing something,

I presume it's going the drm_do_vm_dma_nopage route, and the pages
in the pagelist (though each PAGE_SIZEd itself) have been allocated
from >0-order pages.

> I'm having a look at the drm_pci_alloc code that
> calls pci_alloc_consistent, it may have an issue also (Hugh??)

Just when I thought I could get away from DRM! I've spent a while
groping around there again, and I believe you're right that there
is an issue with drm_pci_alloc too, but that it's not a new issue.

Not a new issue because we've only been changing the behaviour of
PageReserved, and there was no PageReservation around drm_pci_alloc.

But an issue, yes, because pci_alloc_consistent is likely to supply
a >0-order page, with latter constituent 0-order pages having count 0.

Hmm, could this have caused some of my mm/rmap.c BUG_ONs in the past?
Not very likely, I think; but it's not immediately obvious quite how
it would have behaved; certainly "Bad page states" a possibility
(even before the recent changes).

Below is a cowardly patch which I believe will correct this: since
nopage will be a problem here, just go the remap_pfn_range way instead.

I'm not proud of coming up with different adhoc solutions to different
manifestations of the same underlying problem, but pci_alloc_consistent
depends on the architecture, I don't want to go there. Uncompiled,
untested, see what you think.

Though two worries noticed on the way. One, there's drm_addbufs_pci:
that's a bit confusingly named, isn't it, since it's working on the
DMA pagelist, and unrelated to drm_pci_alloc? Two, is it right that
only _DRM_SHM and _DRM_CONSISTENT end up using drm_vm_shm_close,
which does cleanup which the others miss by using drm_vm_close?
No need to explain why I'm wrong! just mentioned in case it's wrong.

> I've queued up the patch for Linus, along with a couple of other bugfixes...

Thanks for looking after that, Dave. Please take care of this one too,
if you agree it's the right thing to do...

_DRM_CONSISTENT memory is allocated in one range by pci_alloc_consistent,
and is therefore likely to be a >0-order page, whose constituent 0-order
pages should not be exposed to nopage and freeing: use remap_pfn_range.

Signed-off-by: Hugh Dickins <hugh@xxxxxxxxxxx>

--- 2.6.15-rc2-git3/drivers/char/drm/drm_vm.c 2005-11-20 19:43:39.000000000 +0000
+++ linux/drivers/char/drm/drm_vm.c 2005-11-23 19:15:58.000000000 +0000
@@ -154,8 +154,7 @@ static __inline__ struct page *drm_do_vm

offset = address - vma->vm_start;
i = (unsigned long)map->handle + offset;
- page = (map->type == _DRM_CONSISTENT) ?
- virt_to_page((void *)i) : vmalloc_to_page((void *)i);
+ page = vmalloc_to_page((void *)i);
if (!page)
return NOPAGE_OOM;
get_page(page);
@@ -636,10 +635,16 @@ int drm_mmap(struct file *filp, struct v
vma->vm_start, vma->vm_end, map->offset + offset);
vma->vm_ops = &drm_vm_ops;
break;
- case _DRM_SHM:
case _DRM_CONSISTENT:
- /* Consistent memory is really like shared memory. It's only
- * allocate in a different way */
+ /* Consistent memory is really like shared memory. But
+ * it's allocated in a different way, so avoid nopage */
+ if (remap_pfn_range(vma, vma->vm_start,
+ page_to_pfn(virt_to_page(map->handle)),
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+ /* fall through to _DRM_SHM... */
+ case _DRM_SHM:
vma->vm_ops = &drm_vm_shm_ops;
vma->vm_private_data = (void *)map;
/* Don't let this area swap. Change when
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/