mirror of
https://github.com/LineageOS/android_kernel_samsung_msm8226.git
synced 2026-09-28 00:00:22 +02:00
mm: make is_vmalloc_addr lockless
is_vmalloc_addr currently takes the vmap_area_lock and walks the list of vmalloc areas to determine if an address is actually a vmalloc address. Unfortunately, the current locking structure with vmap_area_lock does not disable irqs which means that it may be possible to recusively take the vmap_area_lock if an irq occurs while walking the tree list. Considering the list of possible vmalloc vs. not vmalloc ranges is not going to change after bootup, skip the tree walking and just keep a bitmap of which virtual addresses are set aside for vmalloc and which are not. Change-Id: I0c159e09dc17b5c6641d08dcf630e6116b991cd5 CRs-Fixed: 591797 Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
This commit is contained in:
committed by
Olav Haugan
parent
2101ee7dfa
commit
f2da5eb8e5
+3
-1
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+41
-30
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user