dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: Lepton Wu <ytht.net@gmail.com>
To: dri-devel@lists.freedesktop.org
Cc: christian.koenig@amd.com, Lepton Wu <ytht.net@gmail.com>
Subject: [RFC] drm/vgem: Don't use get_page in fault handler.
Date: Mon,  6 Jul 2020 21:21:00 -0700	[thread overview]
Message-ID: <20200707042100.2550260-1-ytht.net@gmail.com> (raw)

For pages which are allocated in ttm with transparent huge pages,
tail pages have zero as reference count. The current vgem code use
get_page on them and it will trigger BUG when release_pages get called
on those pages later.

Here I attach the minimal code to trigger this bug on a qemu VM which
enables virtio gpu (card1) and vgem (card0). BTW, since the upstream
virtio gpu has changed to use drm gem and moved away from ttm. So we
have to use an old kernel like 5.4 to reproduce it. But I guess
same thing could happen for a real GPU if the real GPU use similar code
path to allocate pages from ttm. I am not sure about two things: first, do we
need to fix this? will a real GPU hit this code path? Second, suppose this
need to be fixed, should this be fixed in ttm side or vgem side?  If we remove
"huge_flags &= ~__GFP_COMP" from ttm_get_pages, then get_page in vgem works
fine. But it's there for fix another bug:
https://bugs.freedesktop.org/show_bug.cgi?id=103138
It could also be "fixed" with this patch. But I am really not sure if this is
the way to go.

Here is the code to reproduce this bug:

unsigned int WIDTH = 1024;
unsigned int HEIGHT = 513;
unsigned int size = WIDTH * HEIGHT * 4;

int work(int vfd, int dfd, int handle) {
	int ret;
	struct drm_prime_handle hf = {.handle =  handle };
	ret = ioctl(dfd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &hf);
	fprintf(stderr, "fd is %d\n", hf.fd);
	hf.flags = DRM_CLOEXEC | DRM_RDWR;
	ret = ioctl(vfd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &hf);
	fprintf(stderr, "new handle is %d\n", hf.handle);
	struct drm_mode_map_dumb map = {.handle = hf.handle };
	ret = ioctl(vfd, DRM_IOCTL_MODE_MAP_DUMB, &map);
	fprintf(stderr, "need map at offset %lld\n", map.offset);
	unsigned char * ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, vfd,
			  map.offset);
	memset(ptr, 2, size);
	munmap(ptr, size);
}

int main()
{
	int vfd = open("/dev/dri/card0", O_RDWR); // vgem
	int dfd = open("/dev/dri/card1", O_RDWR); // virtio gpu

	int ret;
        struct drm_mode_create_dumb ct = {};

	ct.height = HEIGHT;
	ct.width = WIDTH;
	ct.bpp = 32;
	ret = ioctl(dfd, DRM_IOCTL_MODE_CREATE_DUMB, &ct);
	work(vfd, dfd, ct.handle);
	fprintf(stderr, "done\n");
}

Signed-off-by: Lepton Wu <ytht.net@gmail.com>
---
 drivers/gpu/drm/vgem/vgem_drv.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c
index ec1a8ebb6f1b..be3d97e29804 100644
--- a/drivers/gpu/drm/vgem/vgem_drv.c
+++ b/drivers/gpu/drm/vgem/vgem_drv.c
@@ -87,9 +87,8 @@ static vm_fault_t vgem_gem_fault(struct vm_fault *vmf)
 
 	mutex_lock(&obj->pages_lock);
 	if (obj->pages) {
-		get_page(obj->pages[page_offset]);
-		vmf->page = obj->pages[page_offset];
-		ret = 0;
+		ret = vmf_insert_pfn(vmf->vma, vmf->address,
+				     page_to_pfn(obj->pages[page_offset]));
 	}
 	mutex_unlock(&obj->pages_lock);
 	if (ret) {
@@ -263,7 +262,6 @@ static struct drm_ioctl_desc vgem_ioctls[] = {
 
 static int vgem_mmap(struct file *filp, struct vm_area_struct *vma)
 {
-	unsigned long flags = vma->vm_flags;
 	int ret;
 
 	ret = drm_gem_mmap(filp, vma);
@@ -273,7 +271,6 @@ static int vgem_mmap(struct file *filp, struct vm_area_struct *vma)
 	/* Keep the WC mmaping set by drm_gem_mmap() but our pages
 	 * are ordinary and not special.
 	 */
-	vma->vm_flags = flags | VM_DONTEXPAND | VM_DONTDUMP;
 	return 0;
 }
 
-- 
2.27.0.212.ge8ba1cc988-goog

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

             reply	other threads:[~2020-07-07  7:27 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-07  4:21 Lepton Wu [this message]
2020-07-07  8:22 ` [RFC] drm/vgem: Don't use get_page in fault handler Chris Wilson
2020-07-07  8:59 ` Daniel Vetter
2020-07-07 10:58   ` Christian König
2020-07-07 11:07     ` Chris Wilson
2020-07-07 12:05       ` Thomas Hellström (Intel)
2020-07-07 12:15         ` Chris Wilson
2020-07-07 13:55         ` Christian König

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200707042100.2550260-1-ytht.net@gmail.com \
    --to=ytht.net@gmail.com \
    --cc=christian.koenig@amd.com \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).