[PATCH] boot-time ioremap alternative

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



(Note: Patch also attached because the inline version is certain to get
line wrapped.)

An alternative to (on i386) boot-time ioremap approaches, which is
more
architecture independent (though arch dependent code needs adjustments
if this is to be made use of, which with this patch only happens for
i386 and x86_64) and doesn't require alternative boot-time interfaces.

Signed-off-by: Jan Beulich <[email protected]>

diff -Npru 2.6.13/arch/i386/kernel/setup.c
2.6.13-early-ioremap/arch/i386/kernel/setup.c
--- 2.6.13/arch/i386/kernel/setup.c	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-early-ioremap/arch/i386/kernel/setup.c	2005-09-01
13:58:18.000000000 +0200
@@ -1119,6 +1119,9 @@ static unsigned long __init setup_memory
 	}
 	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
 		pages_to_mb(highend_pfn - highstart_pfn));
+	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+#else
+	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
 #endif
 	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
 			pages_to_mb(max_low_pfn));
diff -Npru 2.6.13/arch/i386/mm/init.c
2.6.13-early-ioremap/arch/i386/mm/init.c
--- 2.6.13/arch/i386/mm/init.c	2005-08-29 01:41:01.000000000 +0200
+++ 2.6.13-early-ioremap/arch/i386/mm/init.c	2005-09-01
13:58:34.000000000 +0200
@@ -559,12 +559,6 @@ void __init mem_init(void)
  
 	set_max_mapnr_init();
 
-#ifdef CONFIG_HIGHMEM
-	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
-#else
-	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
-#endif
-
 	/* this will put all low memory onto the freelists */
 	totalram_pages += free_all_bootmem();
 
diff -Npru 2.6.13/arch/i386/mm/ioremap.c
2.6.13-early-ioremap/arch/i386/mm/ioremap.c
--- 2.6.13/arch/i386/mm/ioremap.c	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-early-ioremap/arch/i386/mm/ioremap.c	2005-09-01
14:00:53.000000000 +0200
@@ -257,7 +257,8 @@ void iounmap(volatile void __iomem *addr
 	} 
 out_unlock:
 	write_unlock(&vmlist_lock);
-	kfree(p); 
+	if (p)
+		free_vm_area(p);
 }
 EXPORT_SYMBOL(iounmap);
 
diff -Npru 2.6.13/arch/i386/mm/pgtable.c
2.6.13-early-ioremap/arch/i386/mm/pgtable.c
--- 2.6.13/arch/i386/mm/pgtable.c	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-early-ioremap/arch/i386/mm/pgtable.c	2005-09-01
11:32:11.000000000 +0200
@@ -11,6 +11,7 @@
 #include <linux/smp.h>
 #include <linux/highmem.h>
 #include <linux/slab.h>
+#include <linux/bootmem.h>
 #include <linux/pagemap.h>
 #include <linux/spinlock.h>
 
@@ -148,7 +149,9 @@ void __set_fixmap (enum fixed_addresses 
 
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long
address)
 {
-	return (pte_t
*)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	if (likely(totalram_pages))
+		return (pte_t
*)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	return alloc_bootmem_pages(PAGE_SIZE);
 }
 
 struct page *pte_alloc_one(struct mm_struct *mm, unsigned long
address)
diff -Npru 2.6.13/arch/x86_64/kernel/setup.c
2.6.13-early-ioremap/arch/x86_64/kernel/setup.c
--- 2.6.13/arch/x86_64/kernel/setup.c	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-early-ioremap/arch/x86_64/kernel/setup.c	2005-09-01
15:34:02.000000000 +0200
@@ -561,6 +561,7 @@ void __init setup_arch(char **cmdline_p)
 	 * we are rounding upwards:
 	 */
 	end_pfn = e820_end_of_ram();
+	high_memory = (void *)__va(end_pfn * PAGE_SIZE - 1) + 1;
 
 	check_efer();
 
diff -Npru 2.6.13/arch/x86_64/mm/init.c
2.6.13-early-ioremap/arch/x86_64/mm/init.c
--- 2.6.13/arch/x86_64/mm/init.c	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-early-ioremap/arch/x86_64/mm/init.c	2005-09-01
11:32:11.000000000 +0200
@@ -427,7 +427,6 @@ void __init mem_init(void)
 	max_low_pfn = end_pfn;
 	max_pfn = end_pfn;
 	num_physpages = end_pfn;
-	high_memory = (void *) __va(end_pfn * PAGE_SIZE);
 
 	/* clear the zero-page */
 	memset(empty_zero_page, 0, PAGE_SIZE);
diff -Npru 2.6.13/arch/x86_64/mm/ioremap.c
2.6.13-early-ioremap/arch/x86_64/mm/ioremap.c
--- 2.6.13/arch/x86_64/mm/ioremap.c	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-early-ioremap/arch/x86_64/mm/ioremap.c	2005-09-01
16:47:08.000000000 +0200
@@ -266,5 +266,6 @@ void iounmap(volatile void __iomem *addr
 	else if (p->flags >> 20)
 		ioremap_change_attr(p->phys_addr, p->size, 0);
 	write_unlock(&vmlist_lock);
-	kfree(p); 
+	if(p)
+		free_vm_area(p);
 }
diff -Npru 2.6.13/include/linux/vmalloc.h
2.6.13-early-ioremap/include/linux/vmalloc.h
--- 2.6.13/include/linux/vmalloc.h	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-early-ioremap/include/linux/vmalloc.h	2005-09-01
17:47:16.000000000 +0200
@@ -8,6 +8,7 @@
 #define VM_IOREMAP	0x00000001	/* ioremap() and friends */
 #define VM_ALLOC	0x00000002	/* vmalloc() */
 #define VM_MAP		0x00000004	/* vmap()ed pages */
+#define VM_BOOTMEM	0x00000008	/* allocated from bootmem */
 /* bits [20..32] reserved for arch specific ioremap internals */
 
 struct vm_struct {
@@ -42,6 +43,7 @@ extern struct vm_struct *__get_vm_area(u
 					unsigned long start, unsigned
long end);
 extern struct vm_struct *remove_vm_area(void *addr);
 extern struct vm_struct *__remove_vm_area(void *addr);
+extern void free_vm_area(struct vm_struct *area);
 extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
 			struct page ***pages);
 extern void unmap_vm_area(struct vm_struct *area);
diff -Npru 2.6.13/mm/page_alloc.c 2.6.13-early-ioremap/mm/page_alloc.c
--- 2.6.13/mm/page_alloc.c	2005-08-29 01:41:01.000000000 +0200
+++ 2.6.13-early-ioremap/mm/page_alloc.c	2005-09-02
10:02:41.000000000 +0200
@@ -987,6 +987,15 @@ fastcall unsigned long get_zeroed_page(u
 {
 	struct page * page;
 
+	if (unlikely(!totalram_pages)) {
+		/* This exists solely for page table allocation; pages
+		   allocated this way must never be freed! */
+		void *address = alloc_bootmem_pages(PAGE_SIZE);
+
+		clear_page(address);
+		return (unsigned long) address;
+	}
+
 	/*
 	 * get_zeroed_page() returns a 32-bit address, which cannot
represent
 	 * a highmem page
diff -Npru 2.6.13/mm/vmalloc.c 2.6.13-early-ioremap/mm/vmalloc.c
--- 2.6.13/mm/vmalloc.c	2005-08-29 01:41:01.000000000 +0200
+++ 2.6.13-early-ioremap/mm/vmalloc.c	2005-09-02 10:09:12.000000000
+0200
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/highmem.h>
 #include <linux/slab.h>
+#include <linux/bootmem.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 
@@ -179,20 +180,24 @@ struct vm_struct *__get_vm_area(unsigned
 	}
 	addr = ALIGN(start, align);
 	size = PAGE_ALIGN(size);
-
-	area = kmalloc(sizeof(*area), GFP_KERNEL);
-	if (unlikely(!area))
-		return NULL;
-
-	if (unlikely(!size)) {
-		kfree (area);
+	if (unlikely(!size))
 		return NULL;
-	}
-
 	/*
 	 * We always allocate a guard page.
 	 */
 	size += PAGE_SIZE;
+	if (unlikely(!size))
+		return NULL;
+
+	BUG_ON(flags & VM_BOOTMEM);
+	if (likely(malloc_sizes->cs_cachep))
+		area = kmalloc(sizeof(*area), GFP_KERNEL);
+	else {
+		area = alloc_bootmem(sizeof(*area));
+		flags |= VM_BOOTMEM;
+	}
+	if (unlikely(!area))
+		return NULL;
 
 	write_lock(&vmlist_lock);
 	for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
@@ -227,7 +232,7 @@ found:
 
 out:
 	write_unlock(&vmlist_lock);
-	kfree(area);
+	free_vm_area(area);
 	if (printk_ratelimit())
 		printk(KERN_WARNING "allocation failed: out of vmalloc
space - use vmalloc=<size> to increase size.\n");
 	return NULL;
@@ -288,6 +293,14 @@ struct vm_struct *remove_vm_area(void *a
 	return v;
 }
 
+void free_vm_area(struct vm_struct *area)
+{
+	if (likely(!(area->flags & VM_BOOTMEM)))
+		kfree(area);
+	else if (!malloc_sizes->cs_cachep)
+		free_bootmem(virt_to_phys(area), sizeof(*area));
+}
+
 void __vunmap(void *addr, int deallocate_pages)
 {
 	struct vm_struct *area;
@@ -324,7 +337,7 @@ void __vunmap(void *addr, int deallocate
 			kfree(area->pages);
 	}
 
-	kfree(area);
+	free_vm_area(area);
 	return;
 }
 
@@ -413,7 +426,7 @@ void *__vmalloc_area(struct vm_struct *a
 	area->pages = pages;
 	if (!area->pages) {
 		remove_vm_area(area->addr);
-		kfree(area);
+		free_vm_area(area);
 		return NULL;
 	}
 	memset(area->pages, 0, array_size);

Attachment: linux-2.6.13-early-ioremap.patch
Description: Binary data


[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux