Rather than blindly re-enabling interrupts in oops_end(), save their state
in oope_begin() and then restore that state.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
static DEFINE_SPINLOCK(die_lock);
static int die_owner = -1;
static DEFINE_SPINLOCK(die_lock);
static int die_owner = -1;
+unsigned long oops_begin(void)
- int cpu = safe_smp_processor_id();
- /* racy, but better than risking deadlock. */
- local_irq_disable();
+ int cpu = safe_smp_processor_id();
+ unsigned long flags;
+
+ /* racy, but better than risking deadlock. */
+ local_irq_save(flags);
if (!spin_trylock(&die_lock)) {
if (cpu == die_owner)
/* nested oops. should stop eventually */;
else
if (!spin_trylock(&die_lock)) {
if (cpu == die_owner)
/* nested oops. should stop eventually */;
else
+ bust_spinlocks(1);
+ return flags;
+void oops_end(unsigned long flags)
- bust_spinlocks(0);
- spin_unlock(&die_lock);
+ bust_spinlocks(0);
+ spin_unlock_irqrestore(&die_lock, flags);
void __die(const char * str, struct pt_regs * regs, long err)
{
void __die(const char * str, struct pt_regs * regs, long err)
{
void die(const char * str, struct pt_regs * regs, long err)
{
void die(const char * str, struct pt_regs * regs, long err)
{
+ unsigned long flags = oops_begin();
+
handle_BUG(regs);
__die(str, regs, err);
handle_BUG(regs);
__die(str, regs, err);
do_exit(SIGSEGV);
}
static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
do_exit(SIGSEGV);
}
static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
void die_nmi(char *str, struct pt_regs *regs)
{
void die_nmi(char *str, struct pt_regs *regs)
{
+ unsigned long flags = oops_begin();
+
/*
* We are in trouble anyway, lets at least try
* to get a message out.
/*
* We are in trouble anyway, lets at least try
* to get a message out.
if (panic_on_timeout || panic_on_oops)
panic("nmi watchdog");
printk("console shuts up ...\n");
if (panic_on_timeout || panic_on_oops)
panic("nmi watchdog");
printk("console shuts up ...\n");
static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
unsigned long error_code)
{
static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
unsigned long error_code)
{
+ unsigned long flags = oops_begin();
+
printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
current->comm, address);
dump_pagetable(address);
__die("Bad pagetable", regs, error_code);
printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
current->comm, address);
dump_pagetable(address);
__die("Bad pagetable", regs, error_code);
unsigned long address;
const struct exception_table_entry *fixup;
int write;
unsigned long address;
const struct exception_table_entry *fixup;
int write;
siginfo_t info;
#ifdef CONFIG_CHECKING
siginfo_t info;
#ifdef CONFIG_CHECKING
* terminate things with extreme prejudice.
*/
* terminate things with extreme prejudice.
*/
if (address < PAGE_SIZE)
printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
if (address < PAGE_SIZE)
printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
__die("Oops", regs, error_code);
/* Executive summary in case the body of the oops scrolled away */
printk(KERN_EMERG "CR2: %016lx\n", address);
__die("Oops", regs, error_code);
/* Executive summary in case the body of the oops scrolled away */
printk(KERN_EMERG "CR2: %016lx\n", address);
extern void __die(const char *,struct pt_regs *,long);
extern void show_registers(struct pt_regs *regs);
extern void dump_pagetable(unsigned long);
extern void __die(const char *,struct pt_regs *,long);
extern void show_registers(struct pt_regs *regs);
extern void dump_pagetable(unsigned long);
-extern void oops_begin(void);
-extern void oops_end(void);
+extern unsigned long oops_begin(void);
+extern void oops_end(unsigned long);
extern void swap_low_mappings(void);
extern void swap_low_mappings(void);
-extern void oops_begin(void);
-extern void die(const char *,struct pt_regs *,long);
-extern void __die(const char * str, struct pt_regs * regs, long err);
extern void __show_regs(struct pt_regs * regs);
extern void show_regs(struct pt_regs * regs);
extern void __show_regs(struct pt_regs * regs);
extern void show_regs(struct pt_regs * regs);