Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: 8840/1: use a raw_spinlock_t in unwind

Mostly unwind is done with irqs enabled however SLUB may call it with
irqs disabled while creating a new SLUB cache.

I had system freeze while loading a module which called
kmem_cache_create() on init. That means SLUB's __slab_alloc() disabled
interrupts and then

->new_slab_objects()
->new_slab()
->setup_object()
->setup_object_debug()
->init_tracking()
->set_track()
->save_stack_trace()
->save_stack_trace_tsk()
->walk_stackframe()
->unwind_frame()
->unwind_find_idx()
=>spin_lock_irqsave(&unwind_lock);

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

authored by

Sebastian Andrzej Siewior and committed by
Russell King
74ffe79a 143c2a89

+7 -7
+7 -7
arch/arm/kernel/unwind.c
··· 93 93 static const struct unwind_idx *__origin_unwind_idx; 94 94 extern const struct unwind_idx __stop_unwind_idx[]; 95 95 96 - static DEFINE_SPINLOCK(unwind_lock); 96 + static DEFINE_RAW_SPINLOCK(unwind_lock); 97 97 static LIST_HEAD(unwind_tables); 98 98 99 99 /* Convert a prel31 symbol to an absolute address */ ··· 201 201 /* module unwind tables */ 202 202 struct unwind_table *table; 203 203 204 - spin_lock_irqsave(&unwind_lock, flags); 204 + raw_spin_lock_irqsave(&unwind_lock, flags); 205 205 list_for_each_entry(table, &unwind_tables, list) { 206 206 if (addr >= table->begin_addr && 207 207 addr < table->end_addr) { ··· 213 213 break; 214 214 } 215 215 } 216 - spin_unlock_irqrestore(&unwind_lock, flags); 216 + raw_spin_unlock_irqrestore(&unwind_lock, flags); 217 217 } 218 218 219 219 pr_debug("%s: idx = %p\n", __func__, idx); ··· 529 529 tab->begin_addr = text_addr; 530 530 tab->end_addr = text_addr + text_size; 531 531 532 - spin_lock_irqsave(&unwind_lock, flags); 532 + raw_spin_lock_irqsave(&unwind_lock, flags); 533 533 list_add_tail(&tab->list, &unwind_tables); 534 - spin_unlock_irqrestore(&unwind_lock, flags); 534 + raw_spin_unlock_irqrestore(&unwind_lock, flags); 535 535 536 536 return tab; 537 537 } ··· 543 543 if (!tab) 544 544 return; 545 545 546 - spin_lock_irqsave(&unwind_lock, flags); 546 + raw_spin_lock_irqsave(&unwind_lock, flags); 547 547 list_del(&tab->list); 548 - spin_unlock_irqrestore(&unwind_lock, flags); 548 + raw_spin_unlock_irqrestore(&unwind_lock, flags); 549 549 550 550 kfree(tab); 551 551 }