Skip to content

Commit

Permalink
vmalloc: implement vm_area_register_early()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tejun Heo committed Feb 20, 2009
1 parent f2a8205 commit f0aa661
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 7 deletions.
20 changes: 13 additions & 7 deletions arch/alpha/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,21 @@ callback_init(void * kernel_end)

if (alpha_using_srm) {
static struct vm_struct console_remap_vm;
unsigned long vaddr = VMALLOC_START;
unsigned long nr_pages = 0;
unsigned long vaddr;
unsigned long i, j;

/* calculate needed size */
for (i = 0; i < crb->map_entries; ++i)
nr_pages += crb->map[i].count;

/* register the vm area */
console_remap_vm.flags = VM_ALLOC;
console_remap_vm.size = nr_pages << PAGE_SHIFT;
vm_area_register_early(&console_remap_vm);

vaddr = (unsigned long)consle_remap_vm.addr;

/* Set up the third level PTEs and update the virtual
addresses of the CRB entries. */
for (i = 0; i < crb->map_entries; ++i) {
Expand All @@ -213,12 +225,6 @@ callback_init(void * kernel_end)
vaddr += PAGE_SIZE;
}
}

/* Let vmalloc know that we've allocated some space. */
console_remap_vm.flags = VM_ALLOC;
console_remap_vm.addr = (void *) VMALLOC_START;
console_remap_vm.size = vaddr - VMALLOC_START;
vmlist = &console_remap_vm;
}

callback_init_done = 1;
Expand Down
1 change: 1 addition & 0 deletions include/linux/vmalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,6 @@ extern long vwrite(char *buf, char *addr, unsigned long count);
*/
extern rwlock_t vmlist_lock;
extern struct vm_struct *vmlist;
extern __init void vm_area_register_early(struct vm_struct *vm);

#endif /* _LINUX_VMALLOC_H */
24 changes: 24 additions & 0 deletions mm/vmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/radix-tree.h>
#include <linux/rcupdate.h>
#include <linux/bootmem.h>
#include <linux/pfn.h>

#include <asm/atomic.h>
#include <asm/uaccess.h>
Expand Down Expand Up @@ -982,6 +983,29 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro
}
EXPORT_SYMBOL(vm_map_ram);

/**
* vm_area_register_early - register vmap area early during boot
* @vm: vm_struct to register
* @size: size of area to register
*
* This function is used to register kernel vm area before
* vmalloc_init() is called. @vm->size and @vm->flags should contain
* proper values on entry and other fields should be zero. On return,
* vm->addr contains the allocated address.
*
* DO NOT USE THIS FUNCTION UNLESS YOU KNOW WHAT YOU'RE DOING.
*/
void __init vm_area_register_early(struct vm_struct *vm)
{
static size_t vm_init_off __initdata;

vm->addr = (void *)VMALLOC_START + vm_init_off;
vm_init_off = PFN_ALIGN(vm_init_off + vm->size);

vm->next = vmlist;
vmlist = vm;
}

void __init vmalloc_init(void)
{
struct vmap_area *va;
Expand Down

0 comments on commit f0aa661

Please sign in to comment.