git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
vserver 1.9.5.x5
[linux-2.6.git]
/
arch
/
x86_64
/
kernel
/
traps.c
diff --git
a/arch/x86_64/kernel/traps.c
b/arch/x86_64/kernel/traps.c
index
c0a31a4
..
72e672e
100644
(file)
--- a/
arch/x86_64/kernel/traps.c
+++ b/
arch/x86_64/kernel/traps.c
@@
-43,9
+43,11
@@
#include <asm/pgalloc.h>
#include <asm/pda.h>
#include <asm/proto.h>
#include <asm/pgalloc.h>
#include <asm/pda.h>
#include <asm/proto.h>
+#include <asm/nmi.h>
#include <linux/irq.h>
#include <linux/irq.h>
+
extern struct gate_struct idt_table[256];
asmlinkage void divide_error(void);
extern struct gate_struct idt_table[256];
asmlinkage void divide_error(void);
@@
-72,6
+74,17
@@
asmlinkage void spurious_interrupt_bug(void);
asmlinkage void call_debug(void);
struct notifier_block *die_chain;
asmlinkage void call_debug(void);
struct notifier_block *die_chain;
+static DEFINE_SPINLOCK(die_notifier_lock);
+
+int register_die_notifier(struct notifier_block *nb)
+{
+ int err = 0;
+ unsigned long flags;
+ spin_lock_irqsave(&die_notifier_lock, flags);
+ err = notifier_chain_register(&die_chain, nb);
+ spin_unlock_irqrestore(&die_notifier_lock, flags);
+ return err;
+}
static inline void conditional_sti(struct pt_regs *regs)
{
static inline void conditional_sti(struct pt_regs *regs)
{
@@
-311,7
+324,7
@@
void out_of_line_bug(void)
BUG();
}
BUG();
}
-static
spinlock_t die_lock = SPIN_LOCK_UNLOCKED
;
+static
DEFINE_SPINLOCK(die_lock)
;
static int die_owner = -1;
void oops_begin(void)
static int die_owner = -1;
void oops_begin(void)
@@
-376,13
+389,20
@@
static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e
die(str, regs, err);
}
die(str, regs, err);
}
-
static inline unsigned long get_cr2(void
)
+
void die_nmi(char *str, struct pt_regs *regs
)
{
{
- unsigned long address;
-
- /* get the address */
- __asm__("movq %%cr2,%0":"=r" (address));
- return address;
+ oops_begin();
+ /*
+ * We are in trouble anyway, lets at least try
+ * to get a message out.
+ */
+ printk(str, safe_smp_processor_id());
+ show_registers(regs);
+ if (panic_on_timeout || panic_on_oops)
+ panic("nmi watchdog");
+ printk("console shuts up ...\n");
+ oops_end();
+ do_exit(SIGSEGV);
}
static void do_trap(int trapnr, int signr, char *str,
}
static void do_trap(int trapnr, int signr, char *str,
@@
-458,7
+478,6
@@
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
}
DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->rip)
}
DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->rip)
-DO_ERROR( 3, SIGTRAP, "int3", int3);
DO_ERROR( 4, SIGSEGV, "overflow", overflow)
DO_ERROR( 5, SIGSEGV, "bounds", bounds)
DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->rip)
DO_ERROR( 4, SIGSEGV, "overflow", overflow)
DO_ERROR( 5, SIGSEGV, "bounds", bounds)
DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->rip)
@@
-528,8
+547,9
@@
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
regs->rip = fixup->fixup;
return;
}
regs->rip = fixup->fixup;
return;
}
- notify_die(DIE_GPF, "general protection fault", regs, error_code,
- 13, SIGSEGV);
+ if (notify_die(DIE_GPF, "general protection fault", regs,
+ error_code, 13, SIGSEGV) == NOTIFY_STOP)
+ return;
die("general protection fault", regs, error_code);
}
}
die("general protection fault", regs, error_code);
}
}
@@
-563,9
+583,13
@@
static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
printk("Do you have a strange power saving mode enabled?\n");
}
printk("Do you have a strange power saving mode enabled?\n");
}
-asmlinkage void default_do_nmi(struct pt_regs *
regs)
+asmlinkage void default_do_nmi(struct pt_regs *regs)
{
{
- unsigned char reason = inb(0x61);
+ unsigned char reason = 0;
+
+ /* Only the BSP gets external NMIs from the system. */
+ if (!smp_processor_id())
+ reason = get_nmi_reason();
if (!(reason & 0xc0)) {
if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
if (!(reason & 0xc0)) {
if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
@@
-586,6
+610,9
@@
asmlinkage void default_do_nmi(struct pt_regs * regs)
}
if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
return;
}
if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
return;
+
+ /* AK: following checks seem to be broken on modern chipsets. FIXME */
+
if (reason & 0x80)
mem_parity_error(reason, regs);
if (reason & 0x40)
if (reason & 0x80)
mem_parity_error(reason, regs);
if (reason & 0x40)
@@
-601,6
+628,15
@@
asmlinkage void default_do_nmi(struct pt_regs * regs)
inb(0x71); /* dummy */
}
inb(0x71); /* dummy */
}
+asmlinkage void do_int3(struct pt_regs * regs, long error_code)
+{
+ if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
+ return;
+ }
+ do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
+ return;
+}
+
/* runs on IST stack. */
asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code)
{
/* runs on IST stack. */
asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code)
{
@@
-630,6
+666,10
@@
asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code)
asm("movq %%db6,%0" : "=r" (condition));
asm("movq %%db6,%0" : "=r" (condition));
+ if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+ SIGTRAP) == NOTIFY_STOP) {
+ return regs;
+ }
conditional_sti(regs);
/* Mask out spurious debug traps due to lazy DR7 setting */
conditional_sti(regs);
/* Mask out spurious debug traps due to lazy DR7 setting */
@@
-642,7
+682,9
@@
asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code)
tsk->thread.debugreg6 = condition;
/* Mask out spurious TF errors due to lazy TF clearing */
tsk->thread.debugreg6 = condition;
/* Mask out spurious TF errors due to lazy TF clearing */
- if (condition & DR_STEP) {
+ if ((condition & DR_STEP) &&
+ (notify_die(DIE_DEBUGSTEP, "debugstep", regs, condition,
+ 1, SIGTRAP) != NOTIFY_STOP)) {
/*
* The TF error should be masked out only if the current
* process is not traced and if the TRAP flag has been set
/*
* The TF error should be masked out only if the current
* process is not traced and if the TRAP flag has been set
@@
-834,6
+876,10
@@
asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs)
{
}
{
}
+asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
+{
+}
+
/*
* 'math_state_restore()' saves the current math information in the
* old math state array, and gets the new ones from the current task
/*
* 'math_state_restore()' saves the current math information in the
* old math state array, and gets the new ones from the current task
@@
-846,7
+892,7
@@
asmlinkage void math_state_restore(void)
struct task_struct *me = current;
clts(); /* Allow maths ops (or we recurse) */
struct task_struct *me = current;
clts(); /* Allow maths ops (or we recurse) */
- if (!
me->used_math
)
+ if (!
used_math()
)
init_fpu(me);
restore_fpu_checking(&me->thread.i387.fxsave);
me->thread_info->status |= TS_USEDFPU;
init_fpu(me);
restore_fpu_checking(&me->thread.i387.fxsave);
me->thread_info->status |= TS_USEDFPU;
@@
-862,8
+908,8
@@
void __init trap_init(void)
set_intr_gate(0,÷_error);
set_intr_gate_ist(1,&debug,DEBUG_STACK);
set_intr_gate_ist(2,&nmi,NMI_STACK);
set_intr_gate(0,÷_error);
set_intr_gate_ist(1,&debug,DEBUG_STACK);
set_intr_gate_ist(2,&nmi,NMI_STACK);
- set_system_gate(3,&int3);
/* int3-5 can be called from all */
- set_system_gate(4,&overflow);
+ set_system_gate(3,&int3);
+ set_system_gate(4,&overflow);
/* int4-5 can be called from all */
set_system_gate(5,&bounds);
set_intr_gate(6,&invalid_op);
set_intr_gate(7,&device_not_available);
set_system_gate(5,&bounds);
set_intr_gate(6,&invalid_op);
set_intr_gate(7,&device_not_available);
@@
-877,7
+923,9
@@
void __init trap_init(void)
set_intr_gate(15,&spurious_interrupt_bug);
set_intr_gate(16,&coprocessor_error);
set_intr_gate(17,&alignment_check);
set_intr_gate(15,&spurious_interrupt_bug);
set_intr_gate(16,&coprocessor_error);
set_intr_gate(17,&alignment_check);
+#ifdef CONFIG_X86_MCE
set_intr_gate_ist(18,&machine_check, MCE_STACK);
set_intr_gate_ist(18,&machine_check, MCE_STACK);
+#endif
set_intr_gate(19,&simd_coprocessor_error);
#ifdef CONFIG_IA32_EMULATION
set_intr_gate(19,&simd_coprocessor_error);
#ifdef CONFIG_IA32_EMULATION
@@
-900,3
+948,11
@@
static int __init oops_dummy(char *s)
return -1;
}
__setup("oops=", oops_dummy);
return -1;
}
__setup("oops=", oops_dummy);
+
+static int __init kstack_setup(char *s)
+{
+ kstack_depth_to_print = simple_strtoul(s,NULL,0);
+ return 0;
+}
+__setup("kstack=", kstack_setup);
+