linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@digeo.com>
To: Christoph Hellwig <hch@infradead.org>
Cc: davidm@hpl.hp.com, michel@daenzer.net, davej@codemonkey.org.uk,
	linux-kernel@vger.kernel.org, dri-devel@lists.sourceforge.net
Subject: Re: Improved DRM support for cant_use_aperture platforms
Date: Mon, 12 May 2003 15:08:31 -0700	[thread overview]
Message-ID: <20030512150831.5bf2e14c.akpm@digeo.com> (raw)
In-Reply-To: <20030512225728.A17182@infradead.org>

Christoph Hellwig <hch@infradead.org> wrote:
>
> On Mon, May 12, 2003 at 02:51:08PM -0700, David Mosberger wrote:
> > Is there someone else on this list who would be able to look into
> > backporting vmap()/vunmap() to 2.4?  I don't use 2.4 with any
> > regularity anymore, but I suppose if nobody else is interested, I
> > could look into it.
> 
> I did that for the XFS tree ages ago, it's also in the -ac and -aa (the latter
> still has the old three-arg version) now. I will submit it to Marcelo as soon
> as 2.4.21 is out (so with the current 2.4 merge rate it'll be in in about 6 month..)
> 

That 2.5 vmap rework introduced a subtle race-bug-goes-oops in
vmalloc()/vfree().  The below patch from Bill fixes it up.




From: William Lee Irwin III <wli@holomorphy.com>

The new vmalloc() semantics from 2.5.32 had a race window.  As things stand,
the presence of a vm_area in the vmlist protects from allocators other than
the owner examining the ptes in that area.  This puts an ordering constraint
on unmapping, so that allocators are required to unmap areas before removing
them from the list or otherwise dropping the lock.

Currently, unmap_vm_area() is done outside the lock and after the area is
removed, which as we've seen from Felix von Leitner's test is oopsable.

The following patch folds calls to unmap_vm_area() into remove_vm_area() to
reinstate what are essentially the 2.4.x semantics of vfree().  This renders
a number of unmap_vm_area() calls unnecessary (and in fact oopsable since
they wipe ptes from later allocations).  It's an open question as to whether
this is sufficiently performant, but it is the minimally invasive approach. 
The more performant alternative is to provide the right API hooks to wipe the
vmalloc() area clean before removing them from the list, using the ownership
of the area to eliminate holding the vmlist_lock for the duration of the
unmapping.  If it proves to be necessary wli is on standby to implement it.


 25-akpm/arch/i386/mm/ioremap.c       |    1 -
 25-akpm/arch/sparc64/kernel/module.c |    2 ++
 25-akpm/arch/x86_64/kernel/module.c  |    2 +-
 25-akpm/arch/x86_64/mm/ioremap.c     |    1 -
 25-akpm/mm/vmalloc.c                 |    3 +--
 5 files changed, 4 insertions(+), 5 deletions(-)

diff -puN arch/i386/mm/ioremap.c~vmalloc-race-fix arch/i386/mm/ioremap.c
--- 25/arch/i386/mm/ioremap.c~vmalloc-race-fix	Mon May 12 14:17:19 2003
+++ 25-akpm/arch/i386/mm/ioremap.c	Mon May 12 14:17:19 2003
@@ -222,7 +222,6 @@ void iounmap(void *addr)
 		return;
 	} 
 
-	unmap_vm_area(p);
 	if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { 
 		change_page_attr(virt_to_page(__va(p->phys_addr)),
 				 p->size >> PAGE_SHIFT,
diff -puN arch/sparc64/kernel/module.c~vmalloc-race-fix arch/sparc64/kernel/module.c
--- 25/arch/sparc64/kernel/module.c~vmalloc-race-fix	Mon May 12 14:17:19 2003
+++ 25-akpm/arch/sparc64/kernel/module.c	Mon May 12 14:17:19 2003
@@ -138,7 +138,9 @@ void *module_alloc(unsigned long size)
 /* Free memory returned from module_core_alloc/module_init_alloc */
 void module_free(struct module *mod, void *module_region)
 {
+	write_lock(&vmlist_lock);
 	module_unmap(module_region);
+	write_unlock(&vmlist_lock);
 	/* FIXME: If module_region == mod->init_region, trim exception
            table entries. */
 }
diff -puN arch/x86_64/kernel/module.c~vmalloc-race-fix arch/x86_64/kernel/module.c
--- 25/arch/x86_64/kernel/module.c~vmalloc-race-fix	Mon May 12 14:17:19 2003
+++ 25-akpm/arch/x86_64/kernel/module.c	Mon May 12 14:17:19 2003
@@ -48,7 +48,6 @@ void module_free(struct module *mod, voi
 	for (prevp = &mod_vmlist ; (map = *prevp) ; prevp = &map->next) {
 		if ((unsigned long)map->addr == addr) {
 			*prevp = map->next;
-			write_unlock(&vmlist_lock); 
 			goto found;
 		}
 	}
@@ -57,6 +56,7 @@ void module_free(struct module *mod, voi
 	return;
  found:
 	unmap_vm_area(map);
+	write_unlock(&vmlist_lock); 
 	if (map->pages) {
 		for (i = 0; i < map->nr_pages; i++)
 			if (map->pages[i])
diff -puN arch/x86_64/mm/ioremap.c~vmalloc-race-fix arch/x86_64/mm/ioremap.c
--- 25/arch/x86_64/mm/ioremap.c~vmalloc-race-fix	Mon May 12 14:17:19 2003
+++ 25-akpm/arch/x86_64/mm/ioremap.c	Mon May 12 14:17:19 2003
@@ -222,7 +222,6 @@ void iounmap(void *addr)
 		return;
 	} 
 
-	unmap_vm_area(p);
 	if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { 
 		change_page_attr(virt_to_page(__va(p->phys_addr)),
 				 p->size >> PAGE_SHIFT,
diff -puN mm/vmalloc.c~vmalloc-race-fix mm/vmalloc.c
--- 25/mm/vmalloc.c~vmalloc-race-fix	Mon May 12 14:17:19 2003
+++ 25-akpm/mm/vmalloc.c	Mon May 12 14:17:19 2003
@@ -260,6 +260,7 @@ struct vm_struct *remove_vm_area(void *a
 	return NULL;
 
 found:
+	unmap_vm_area(tmp);
 	*p = tmp->next;
 	write_unlock(&vmlist_lock);
 	return tmp;
@@ -283,8 +284,6 @@ void __vunmap(void *addr, int deallocate
 				addr);
 		return;
 	}
-
-	unmap_vm_area(area);
 	
 	if (deallocate_pages) {
 		int i;

_


  reply	other threads:[~2003-05-12 22:00 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-05-10 10:09 Improved DRM support for cant_use_aperture platforms David Mosberger
2003-05-10 13:12 ` Dave Jones
2003-05-11 11:43 ` Michel Dänzer
2003-05-11 18:09   ` David Mosberger
2003-05-11 19:55     ` Dave Jones
2003-05-11 21:55       ` Michel Dänzer
2003-05-12 18:53         ` David Mosberger
2003-05-12 19:48           ` [Dri-devel] " Michel Dänzer
2003-05-12 20:19             ` David Mosberger
2003-05-12 21:21               ` Michel Dänzer
2003-05-12 21:51                 ` David Mosberger
2003-05-12 21:57                   ` Christoph Hellwig
2003-05-12 22:08                     ` Andrew Morton [this message]
2003-05-12 22:20                       ` Christoph Hellwig
2003-05-13  0:34                   ` Michel Dänzer
2003-05-13  1:09                     ` David Mosberger
2003-05-13 13:33                       ` Ivan Kokshaysky
2003-05-13 16:20                         ` David Mosberger
2003-05-14  9:41                           ` Ivan Kokshaysky
2003-05-14 10:27                             ` Michel Dänzer
2003-05-14 17:09                             ` David Mosberger
2003-05-13  7:43                     ` David Mosberger
2003-05-14 14:08                       ` Michel Dänzer
2003-05-15 15:59                         ` David Mosberger
2003-05-15 22:37                           ` Michel Dänzer
2003-05-16 23:50                             ` [Dri-devel] " Michel Dänzer
2003-05-12 20:40             ` David Mosberger

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=20030512150831.5bf2e14c.akpm@digeo.com \
    --to=akpm@digeo.com \
    --cc=davej@codemonkey.org.uk \
    --cc=davidm@hpl.hp.com \
    --cc=dri-devel@lists.sourceforge.net \
    --cc=hch@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michel@daenzer.net \
    /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).