diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index a1a2e51e69f..669b10e16f7 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1500,7 +1500,9 @@ static void __init map_lowmem(void) vm->flags = VM_LOWMEM | VM_ARM_STATIC_MAPPING; vm->flags |= VM_ARM_MTYPE(type); vm->caller = map_lowmem; - vm_area_add_early(vm++); + vm_area_add_early(vm); + mark_vmalloc_reserved_area(vm->addr, vm->size); + vm++; } } diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 7675a5c84f3..500421f6f0f 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -136,6 +136,12 @@ extern struct vm_struct *vmlist; extern __init void vm_area_add_early(struct vm_struct *vm); extern __init void vm_area_register_early(struct vm_struct *vm, size_t align); extern __init int vm_area_check_early(struct vm_struct *vm); +#ifdef CONFIG_ENABLE_VMALLOC_SAVING +extern void mark_vmalloc_reserved_area(void *addr, unsigned long size); +#else +static inline void mark_vmalloc_reserved_area(void *addr, unsigned long size) +{ }; +#endif #ifdef CONFIG_SMP # ifdef CONFIG_MMU diff --git a/mm/vmalloc.c b/mm/vmalloc.c index e17469362b0..2e074aa3fb6 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -184,36 +184,6 @@ static int vmap_page_range(unsigned long start, unsigned long end, return ret; } -#ifdef ENABLE_VMALLOC_SAVING -int is_vmalloc_addr(const void *x) -{ - struct rb_node *n; - struct vmap_area *va; - int ret = 0; - - spin_lock(&vmap_area_lock); - - for (n = rb_first(vmap_area_root); n; rb_next(n)) { - va = rb_entry(n, struct vmap_area, rb_node); - if (x >= va->va_start && x < va->va_end) { - ret = 1; - break; - } - } - - spin_unlock(&vmap_area_lock); - return ret; -} -#else -int is_vmalloc_addr(const void *x) -{ - unsigned long addr = (unsigned long)x; - - return addr >= VMALLOC_START && addr < VMALLOC_END; -} -#endif -EXPORT_SYMBOL(is_vmalloc_addr); - int is_vmalloc_or_module_addr(const void *x) { /* @@ -302,6 +272,47 @@ static unsigned long cached_align; static unsigned long vmap_area_pcpu_hole; +#ifdef CONFIG_ENABLE_VMALLOC_SAVING +#define POSSIBLE_VMALLOC_START PAGE_OFFSET + +#define VMALLOC_BITMAP_SIZE ((VMALLOC_END - PAGE_OFFSET) >> \ + PAGE_SHIFT) +#define VMALLOC_TO_BIT(addr) ((addr - PAGE_OFFSET) >> PAGE_SHIFT) +#define BIT_TO_VMALLOC(i) (PAGE_OFFSET + i * PAGE_SIZE) + +DECLARE_BITMAP(possible_areas, VMALLOC_BITMAP_SIZE); + +void mark_vmalloc_reserved_area(void *x, unsigned long size) +{ + unsigned long addr = (unsigned long)x; + + bitmap_set(possible_areas, VMALLOC_TO_BIT(addr), size >> PAGE_SHIFT); +} + +int is_vmalloc_addr(const void *x) +{ + unsigned long addr = (unsigned long)x; + + if (addr < POSSIBLE_VMALLOC_START || addr >= VMALLOC_END) + return 0; + + if (test_bit(VMALLOC_TO_BIT(addr), possible_areas)) + return 0; + + return 1; +} +#else +int is_vmalloc_addr(const void *x) +{ + unsigned long addr = (unsigned long)x; + + return addr >= VMALLOC_START && addr < VMALLOC_END; +} +#endif +EXPORT_SYMBOL(is_vmalloc_addr); + + + static struct vmap_area *__find_vmap_area(unsigned long addr) { struct rb_node *n = vmap_area_root.rb_node;