aboutsummaryrefslogtreecommitdiffstats
path: root/linux-2.6-xen-sparse/arch/x86_64/kernel/traps-xen.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-2.6-xen-sparse/arch/x86_64/kernel/traps-xen.c')
-rw-r--r--linux-2.6-xen-sparse/arch/x86_64/kernel/traps-xen.c98
1 files changed, 55 insertions, 43 deletions
diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/traps-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/traps-xen.c
index 6229915b11..f99eb0e2b9 100644
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/traps-xen.c
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/traps-xen.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/nmi.h>
+#include <linux/kprobes.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -46,9 +47,6 @@
#include <asm/proto.h>
#include <asm/nmi.h>
-#include <linux/irq.h>
-
-
extern struct gate_struct idt_table[256];
asmlinkage void divide_error(void);
@@ -274,7 +272,7 @@ EXPORT_SYMBOL(dump_stack);
void show_registers(struct pt_regs *regs)
{
int i;
- int in_kernel = (regs->cs & 3) == 0;
+ int in_kernel = !user_mode(regs);
unsigned long rsp;
const int cpu = safe_smp_processor_id();
struct task_struct *cur = cpu_pda[cpu].pcurrent;
@@ -318,18 +316,18 @@ void handle_BUG(struct pt_regs *regs)
struct bug_frame f;
char tmp;
- if (regs->cs & 3)
+ if (user_mode(regs))
return;
if (__copy_from_user(&f, (struct bug_frame *) regs->rip,
sizeof(struct bug_frame)))
return;
- if ((unsigned long)f.filename < __PAGE_OFFSET ||
+ if (f.filename >= 0 ||
f.ud2[0] != 0x0f || f.ud2[1] != 0x0b)
return;
- if (__get_user(tmp, f.filename))
- f.filename = "unmapped filename";
+ if (__get_user(tmp, (char *)(long)f.filename))
+ f.filename = (int)(long)"unmapped filename";
printk("----------- [cut here ] --------- [please bite here ] ---------\n");
- printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line);
+ printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", (char *)(long)f.filename, f.line);
}
#ifdef CONFIG_BUG
@@ -342,30 +340,33 @@ void out_of_line_bug(void)
static DEFINE_SPINLOCK(die_lock);
static int die_owner = -1;
-void oops_begin(void)
+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
- spin_lock(&die_lock);
+ spin_lock(&die_lock);
}
- die_owner = cpu;
+ die_owner = cpu;
console_verbose();
- bust_spinlocks(1);
+ bust_spinlocks(1);
+ return flags;
}
-void oops_end(void)
+void oops_end(unsigned long flags)
{
die_owner = -1;
- bust_spinlocks(0);
- spin_unlock(&die_lock);
+ bust_spinlocks(0);
+ spin_unlock_irqrestore(&die_lock, flags);
if (panic_on_oops)
- panic("Oops");
-}
+ panic("Oops");
+}
void __die(const char * str, struct pt_regs * regs, long err)
{
@@ -391,10 +392,11 @@ void __die(const char * str, struct pt_regs * regs, long err)
void die(const char * str, struct pt_regs * regs, long err)
{
- oops_begin();
+ unsigned long flags = oops_begin();
+
handle_BUG(regs);
__die(str, regs, err);
- oops_end();
+ oops_end(flags);
do_exit(SIGSEGV);
}
static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
@@ -406,7 +408,8 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e
#ifdef CONFIG_X86_LOCAL_APIC
void die_nmi(char *str, struct pt_regs *regs)
{
- oops_begin();
+ unsigned long flags = oops_begin();
+
/*
* We are in trouble anyway, lets at least try
* to get a message out.
@@ -416,13 +419,14 @@ void die_nmi(char *str, struct pt_regs *regs)
if (panic_on_timeout || panic_on_oops)
panic("nmi watchdog");
printk("console shuts up ...\n");
- oops_end();
+ oops_end(flags);
do_exit(SIGSEGV);
}
#endif
-static void do_trap(int trapnr, int signr, char *str,
- struct pt_regs * regs, long error_code, siginfo_t *info)
+static void __kprobes do_trap(int trapnr, int signr, char *str,
+ struct pt_regs * regs, long error_code,
+ siginfo_t *info)
{
conditional_sti(regs);
@@ -439,7 +443,7 @@ static void do_trap(int trapnr, int signr, char *str,
}
#endif
- if ((regs->cs & 3) != 0) {
+ if (user_mode(regs)) {
struct task_struct *tsk = current;
if (exception_trace && unhandled_signal(tsk, signr))
@@ -506,7 +510,8 @@ DO_ERROR(18, SIGSEGV, "reserved", reserved)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
-asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
+asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
+ long error_code)
{
conditional_sti(regs);
@@ -524,7 +529,7 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
}
#endif
- if ((regs->cs & 3)!=0) {
+ if (user_mode(regs)) {
struct task_struct *tsk = current;
if (exception_trace && unhandled_signal(tsk, SIGSEGV))
@@ -592,9 +597,12 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
asmlinkage void default_do_nmi(struct pt_regs *regs)
{
unsigned char reason = 0;
+ int cpu;
+
+ cpu = smp_processor_id();
/* Only the BSP gets external NMIs from the system. */
- if (!smp_processor_id())
+ if (!cpu)
reason = get_nmi_reason();
if (!(reason & 0xc0)) {
@@ -625,7 +633,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs)
io_check_error(reason, regs);
}
-asmlinkage void do_int3(struct pt_regs * regs, long error_code)
+asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
{
if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
return;
@@ -644,7 +652,7 @@ asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs)
if (eregs == (struct pt_regs *)eregs->rsp)
;
/* Exception from user space */
- else if (eregs->cs & 3)
+ else if (user_mode(eregs))
regs = ((struct pt_regs *)current->thread.rsp0) - 1;
/* Exception from kernel and interrupts are enabled. Move to
kernel process stack. */
@@ -656,7 +664,8 @@ asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs)
}
/* runs on IST stack. */
-asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code)
+asmlinkage void __kprobes do_debug(struct pt_regs * regs,
+ unsigned long error_code)
{
unsigned long condition;
struct task_struct *tsk = current;
@@ -675,7 +684,7 @@ asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code)
}
#endif
- asm("movq %%db6,%0" : "=r" (condition));
+ get_debugreg(condition, 6);
if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
SIGTRAP) == NOTIFY_STOP)
@@ -703,7 +712,7 @@ asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code)
* allowing programs to debug themselves without the ptrace()
* interface.
*/
- if ((regs->cs & 3) == 0)
+ if (!user_mode(regs))
goto clear_TF_reenable;
/*
* Was the TF flag set by a debugger? If so, clear it now,
@@ -721,13 +730,13 @@ asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code)
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_BRKPT;
- if ((regs->cs & 3) == 0)
+ if (!user_mode(regs))
goto clear_dr7;
info.si_addr = (void __user *)regs->rip;
force_sig_info(SIGTRAP, &info, tsk);
clear_dr7:
- asm volatile("movq %0,%%db7"::"r"(0UL));
+ set_debugreg(0UL, 7);
return;
clear_TF_reenable:
@@ -762,7 +771,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs)
unsigned short cwd, swd;
conditional_sti(regs);
- if ((regs->cs & 3) == 0 &&
+ if (!user_mode(regs) &&
kernel_math_error(regs, "kernel x87 math error"))
return;
@@ -789,13 +798,16 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs)
*/
cwd = get_fpu_cwd(task);
swd = get_fpu_swd(task);
- switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
+ switch (swd & ~cwd & 0x3f) {
case 0x000:
default:
break;
case 0x001: /* Invalid Op */
- case 0x041: /* Stack Fault */
- case 0x241: /* Stack Fault | Direction */
+ /*
+ * swd & 0x240 == 0x040: Stack Underflow
+ * swd & 0x240 == 0x240: Stack Overflow
+ * User must clear the SF bit (0x40) if set
+ */
info.si_code = FPE_FLTINV;
break;
case 0x002: /* Denormalize */
@@ -828,7 +840,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
unsigned short mxcsr;
conditional_sti(regs);
- if ((regs->cs & 3) == 0 &&
+ if (!user_mode(regs) &&
kernel_math_error(regs, "kernel simd math error"))
return;