aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-02-20 02:29:08 -0500
committerTejun Heo <tj@kernel.org>2009-02-20 02:29:08 -0500
commitf0aa6617903648077dffe5cfcf7c4458f4610fa7 (patch)
treec97ab20b953bfea8a6516d741585ea088a8bf7ef
parentf2a8205c4ef1af917d175c36a4097ae5587791c8 (diff)
vmalloc: implement vm_area_register_early()
Impact: allow multiple early vm areas There are places where kernel VM area needs to be allocated before vmalloc is initialized. This is done by allocating static vm_struct, initializing several fields and linking it to vmlist and later vmalloc initialization picking up these from vmlist. This is currently done manually and if there's more than one such areas, there's no defined way to arbitrate who gets which address. This patch implements vm_area_register_early(), which takes vm_area struct with flags and size initialized, assigns address to it and puts it on the vmlist. This way, multiple early vm areas can determine which addresses they should use. The only current user - alpha mm init - is converted to use it. Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--arch/alpha/mm/init.c20
-rw-r--r--include/linux/vmalloc.h1
-rw-r--r--mm/vmalloc.c24
3 files changed, 38 insertions, 7 deletions
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 5d7a16eab312..df6df025ded4 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -189,9 +189,21 @@ callback_init(void * kernel_end)
189 189
190 if (alpha_using_srm) { 190 if (alpha_using_srm) {
191 static struct vm_struct console_remap_vm; 191 static struct vm_struct console_remap_vm;
192 unsigned long vaddr = VMALLOC_START; 192 unsigned long nr_pages = 0;
193 unsigned long vaddr;
193 unsigned long i, j; 194 unsigned long i, j;
194 195
196 /* calculate needed size */
197 for (i = 0; i < crb->map_entries; ++i)
198 nr_pages += crb->map[i].count;
199
200 /* register the vm area */
201 console_remap_vm.flags = VM_ALLOC;
202 console_remap_vm.size = nr_pages << PAGE_SHIFT;
203 vm_area_register_early(&console_remap_vm);
204
205 vaddr = (unsigned long)consle_remap_vm.addr;
206
195 /* Set up the third level PTEs and update the virtual 207 /* Set up the third level PTEs and update the virtual
196 addresses of the CRB entries. */ 208 addresses of the CRB entries. */
197 for (i = 0; i < crb->map_entries; ++i) { 209 for (i = 0; i < crb->map_entries; ++i) {
@@ -213,12 +225,6 @@ callback_init(void * kernel_end)
213 vaddr += PAGE_SIZE; 225 vaddr += PAGE_SIZE;
214 } 226 }
215 } 227 }
216
217 /* Let vmalloc know that we've allocated some space. */
218 console_remap_vm.flags = VM_ALLOC;
219 console_remap_vm.addr = (void *) VMALLOC_START;
220 console_remap_vm.size = vaddr - VMALLOC_START;
221 vmlist = &console_remap_vm;
222 } 228 }
223 229
224 callback_init_done = 1; 230 callback_init_done = 1;
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 506e7620a986..bbc051392298 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -106,5 +106,6 @@ extern long vwrite(char *buf, char *addr, unsigned long count);
106 */ 106 */
107extern rwlock_t vmlist_lock; 107extern rwlock_t vmlist_lock;
108extern struct vm_struct *vmlist; 108extern struct vm_struct *vmlist;
109extern __init void vm_area_register_early(struct vm_struct *vm);
109 110
110#endif /* _LINUX_VMALLOC_H */ 111#endif /* _LINUX_VMALLOC_H */
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index c37924a2ee36..d206261ad9ef 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -24,6 +24,7 @@
24#include <linux/radix-tree.h> 24#include <linux/radix-tree.h>
25#include <linux/rcupdate.h> 25#include <linux/rcupdate.h>
26#include <linux/bootmem.h> 26#include <linux/bootmem.h>
27#include <linux/pfn.h>
27 28
28#include <asm/atomic.h> 29#include <asm/atomic.h>
29#include <asm/uaccess.h> 30#include <asm/uaccess.h>
@@ -982,6 +983,29 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro
982} 983}
983EXPORT_SYMBOL(vm_map_ram); 984EXPORT_SYMBOL(vm_map_ram);
984 985
986/**
987 * vm_area_register_early - register vmap area early during boot
988 * @vm: vm_struct to register
989 * @size: size of area to register
990 *
991 * This function is used to register kernel vm area before
992 * vmalloc_init() is called. @vm->size and @vm->flags should contain
993 * proper values on entry and other fields should be zero. On return,
994 * vm->addr contains the allocated address.
995 *
996 * DO NOT USE THIS FUNCTION UNLESS YOU KNOW WHAT YOU'RE DOING.
997 */
998void __init vm_area_register_early(struct vm_struct *vm)
999{
1000 static size_t vm_init_off __initdata;
1001
1002 vm->addr = (void *)VMALLOC_START + vm_init_off;
1003 vm_init_off = PFN_ALIGN(vm_init_off + vm->size);
1004
1005 vm->next = vmlist;
1006 vmlist = vm;
1007}
1008
985void __init vmalloc_init(void) 1009void __init vmalloc_init(void)
986{ 1010{
987 struct vmap_area *va; 1011 struct vmap_area *va;