Messages in this thread Patch in this message | | | Date | Sun, 9 Jan 2005 08:56:11 -0700 (MST) | From | Zwane Mwaikambo <> | Subject | [PATCH] Fixes for prep_zero_page |
| |
On Sun, 9 Jan 2005, Andrew Morton wrote:
> Well it's doing clear_highpage() before __alloc_pages() has called > kernel_map_pages(), so CONFIG_DEBUG_PAGEALLOC is quite kaput. > > So the current __GFP_ZERO buglist is: > > 1: Breaks CONFIG_DEBUG_PAGEALLOC > > 2: Breaks the cache aliasing protection for anonymous pages > > 3: prep_zero_page() uses KM_USER0 so __GFP_ZERO from IRQ context will > cause rare memory corruption.
The following should take care of 1 and 3. I opted to unmap the pages again after the clear page so that it remains isolated and we don't have to make additional checks to see if we should unmap the pages.
Signed-off-by: Zwane Mwaikambo <zwane@arm.linux.org.uk>
Index: linux-2.6.10-mm2/include/linux/highmem.h =================================================================== RCS file: /home/cvsroot/linux-2.6.10-mm2/include/linux/highmem.h,v retrieving revision 1.1.1.1 diff -u -p -B -r1.1.1.1 highmem.h --- linux-2.6.10-mm2/include/linux/highmem.h 9 Jan 2005 04:51:52 -0000 1.1.1.1 +++ linux-2.6.10-mm2/include/linux/highmem.h 9 Jan 2005 15:32:17 -0000 @@ -50,6 +50,18 @@ static inline void clear_highpage(struct kunmap_atomic(kaddr, KM_USER0); } +static inline void clear_irq_highpage(struct page *page) +{ + char *kaddr; + unsigned long flags; + + local_irq_save(flags); + kaddr = kmap_atomic(page, KM_IRQ0); + clear_page(kaddr); + kunmap_atomic(kaddr, KM_IRQ0); + local_irq_restore(flags); +} + /* * Same but also flushes aliased cache contents to RAM. */ Index: linux-2.6.10-mm2/mm/page_alloc.c =================================================================== RCS file: /home/cvsroot/linux-2.6.10-mm2/mm/page_alloc.c,v retrieving revision 1.1.1.1 diff -u -p -B -r1.1.1.1 page_alloc.c --- linux-2.6.10-mm2/mm/page_alloc.c 9 Jan 2005 04:52:40 -0000 1.1.1.1 +++ linux-2.6.10-mm2/mm/page_alloc.c 9 Jan 2005 15:46:00 -0000 @@ -691,10 +691,17 @@ perthread_pages_alloc(void) */ static inline void prep_zero_page(struct page *page, int order) { - int i; + int i, nr_pages = (1 << order); + int context = in_interrupt(); - for(i = 0; i < (1 << order); i++) - clear_highpage(page + i); + kernel_map_pages(page, nr_pages, 1); + for(i = 0; i < nr_pages; i++) { + if (likely(!context)) + clear_highpage(page + i); + else + clear_irq_highpage(page + i); + } + kernel_map_pages(page, nr_pages, 0); } static struct page * - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |