diff -up arch/x86/kernel/kgdb_32.c arch/x86/kernel/kgdb_64.c

screamed for unification. Here it is.

Signed-off-by: Jan Kiszka <[EMAIL PROTECTED]>

---
 arch/x86/kernel/Makefile_32 |    2 
 arch/x86/kernel/Makefile_64 |    2 
 arch/x86/kernel/kgdb.c      |  561 ++++++++++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/kgdb_32.c   |  414 --------------------------------
 arch/x86/kernel/kgdb_64.c   |  495 --------------------------------------
 5 files changed, 563 insertions(+), 911 deletions(-)

Index: b/arch/x86/kernel/Makefile_32
===================================================================
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -37,7 +37,7 @@ obj-y                         += sysenter_32.o vsyscall_32.o
 obj-$(CONFIG_ACPI_SRAT)        += srat_32.o
 obj-$(CONFIG_EFI)              += efi_32.o efi_stub_32.o
 obj-$(CONFIG_DOUBLEFAULT)      += doublefault_32.o
-obj-$(CONFIG_KGDB)             += kgdb_32.o kgdb-jmp_32.o
+obj-$(CONFIG_KGDB)             += kgdb.o kgdb-jmp_32.o
 obj-$(CONFIG_VM86)             += vm86_32.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_HPET_TIMER)       += hpet.o
Index: b/arch/x86/kernel/Makefile_64
===================================================================
--- a/arch/x86/kernel/Makefile_64
+++ b/arch/x86/kernel/Makefile_64
@@ -31,7 +31,7 @@ obj-$(CONFIG_GART_IOMMU)      += pci-gart_64.
 obj-$(CONFIG_CALGARY_IOMMU)    += pci-calgary_64.o tce_64.o
 obj-$(CONFIG_SWIOTLB)          += pci-swiotlb_64.o
 obj-$(CONFIG_KPROBES)          += kprobes_64.o
-obj-$(CONFIG_KGDB)             += kgdb_64.o kgdb-jmp_64.o
+obj-$(CONFIG_KGDB)             += kgdb.o kgdb-jmp_64.o
 obj-$(CONFIG_X86_PM_TIMER)     += pmtimer_64.o
 obj-$(CONFIG_X86_VSMP)         += vsmp_64.o
 obj-$(CONFIG_K8_NB)            += k8.o
Index: b/arch/x86/kernel/kgdb.c
===================================================================
--- /dev/null
+++ b/arch/x86/kernel/kgdb.c
@@ -0,0 +1,561 @@
+/*
+ * arch/x86/kernel/kgdb.c
+ *
+ * Copyright (C) 2000-2001 VERITAS Software Corporation.
+ * Copyright (C) 2002 Andi Kleen, SuSE Labs
+ * Copyright (C) 2004 Amit S. Kale <[EMAIL PROTECTED]>
+ * Copyright (C) 2004 LinSysSoft Technologies Pvt. Ltd.
+ * Copyright (C) 2007 Jason Wessel, Wind River Systems, Inc.
+ * Copyright (C) 2007 MontaVista Software, Inc.
+ *
+ *
+ * Contributors at various stages not listed above:
+ *  Lake Stevens Instrument Division (Glenn Engel)
+ *  Tom Rini <[EMAIL PROTECTED]>
+ *  Jim Kingdon, Cygnus Support.
+ *  David Grothe <[EMAIL PROTECTED]>
+ *  Tigran Aivazian <[EMAIL PROTECTED]>
+ *  Jim Houston
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <asm/system.h>
+#include <linux/ptrace.h>              /* for linux pt_regs struct */
+#include <linux/kgdb.h>
+#include <linux/init.h>
+#include <linux/kdebug.h>
+#ifdef CONFIG_X86_32
+#include <mach_ipi.h>
+#else /* !CONFIG_X86_32 */
+#include <asm/mach_apic.h>
+#endif /* !CONFIG_X86_32 */
+
+/* Put the error code here just in case the user cares.  */
+int gdb_x86_errcode;
+/* Likewise, the vector number here (since GDB only gets the signal
+   number through the usual means, and that's not very specific).  */
+int gdb_x86_vector = -1;
+
+#ifdef CONFIG_X86_32
+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+       gdb_regs[_EAX] = regs->eax;
+       gdb_regs[_EBX] = regs->ebx;
+       gdb_regs[_ECX] = regs->ecx;
+       gdb_regs[_EDX] = regs->edx;
+       gdb_regs[_ESI] = regs->esi;
+       gdb_regs[_EDI] = regs->edi;
+       gdb_regs[_EBP] = regs->ebp;
+       gdb_regs[_DS] = regs->xds;
+       gdb_regs[_ES] = regs->xes;
+       gdb_regs[_PS] = regs->eflags;
+       gdb_regs[_CS] = regs->xcs;
+       gdb_regs[_PC] = regs->eip;
+       gdb_regs[_ESP] = (int)(&regs->esp);
+       gdb_regs[_SS] = __KERNEL_DS;
+       gdb_regs[_FS] = 0xFFFF;
+       gdb_regs[_GS] = 0xFFFF;
+}
+
+/*
+ * Extracts ebp, esp and eip values understandable by gdb from the values
+ * saved by switch_to.
+ * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
+ * prior to entering switch_to is 8 greater then the value that is saved.
+ * If switch_to changes, change following code appropriately.
+ */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct 
*p)
+{
+       gdb_regs[_EAX] = 0;
+       gdb_regs[_EBX] = 0;
+       gdb_regs[_ECX] = 0;
+       gdb_regs[_EDX] = 0;
+       gdb_regs[_ESI] = 0;
+       gdb_regs[_EDI] = 0;
+       gdb_regs[_EBP] = *(unsigned long *)p->thread.esp;
+       gdb_regs[_DS] = __KERNEL_DS;
+       gdb_regs[_ES] = __KERNEL_DS;
+       gdb_regs[_PS] = 0;
+       gdb_regs[_CS] = __KERNEL_CS;
+       gdb_regs[_PC] = p->thread.eip;
+       gdb_regs[_ESP] = p->thread.esp;
+       gdb_regs[_SS] = __KERNEL_DS;
+       gdb_regs[_FS] = 0xFFFF;
+       gdb_regs[_GS] = 0xFFFF;
+}
+
+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+       regs->eax = gdb_regs[_EAX];
+       regs->ebx = gdb_regs[_EBX];
+       regs->ecx = gdb_regs[_ECX];
+       regs->edx = gdb_regs[_EDX];
+       regs->esi = gdb_regs[_ESI];
+       regs->edi = gdb_regs[_EDI];
+       regs->ebp = gdb_regs[_EBP];
+       regs->xds = gdb_regs[_DS];
+       regs->xes = gdb_regs[_ES];
+       regs->eflags = gdb_regs[_PS];
+       regs->xcs = gdb_regs[_CS];
+       regs->eip = gdb_regs[_PC];
+}
+
+#else /* CONFIG_X86_64 */
+
+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+       gdb_regs[_RAX] = regs->rax;
+       gdb_regs[_RBX] = regs->rbx;
+       gdb_regs[_RCX] = regs->rcx;
+       gdb_regs[_RDX] = regs->rdx;
+       gdb_regs[_RSI] = regs->rsi;
+       gdb_regs[_RDI] = regs->rdi;
+       gdb_regs[_RBP] = regs->rbp;
+       gdb_regs[_PS] = regs->eflags;
+       gdb_regs[_PC] = regs->rip;
+       gdb_regs[_R8] = regs->r8;
+       gdb_regs[_R9] = regs->r9;
+       gdb_regs[_R10] = regs->r10;
+       gdb_regs[_R11] = regs->r11;
+       gdb_regs[_R12] = regs->r12;
+       gdb_regs[_R13] = regs->r13;
+       gdb_regs[_R14] = regs->r14;
+       gdb_regs[_R15] = regs->r15;
+       gdb_regs[_RSP] = regs->rsp;
+}
+
+extern void thread_return(void);
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct 
*p)
+{
+       gdb_regs[_RAX] = 0;
+       gdb_regs[_RBX] = 0;
+       gdb_regs[_RCX] = 0;
+       gdb_regs[_RDX] = 0;
+       gdb_regs[_RSI] = 0;
+       gdb_regs[_RDI] = 0;
+       gdb_regs[_RBP] = *(unsigned long *)p->thread.rsp;
+       gdb_regs[_PS] = *(unsigned long *)(p->thread.rsp + 8);
+       gdb_regs[_PC] = (unsigned long)&thread_return;
+       gdb_regs[_R8] = 0;
+       gdb_regs[_R9] = 0;
+       gdb_regs[_R10] = 0;
+       gdb_regs[_R11] = 0;
+       gdb_regs[_R12] = 0;
+       gdb_regs[_R13] = 0;
+       gdb_regs[_R14] = 0;
+       gdb_regs[_R15] = 0;
+       gdb_regs[_RSP] = p->thread.rsp;
+}
+
+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+       regs->rax = gdb_regs[_RAX];
+       regs->rbx = gdb_regs[_RBX];
+       regs->rcx = gdb_regs[_RCX];
+       regs->rdx = gdb_regs[_RDX];
+       regs->rsi = gdb_regs[_RSI];
+       regs->rdi = gdb_regs[_RDI];
+       regs->rbp = gdb_regs[_RBP];
+       regs->eflags = gdb_regs[_PS];
+       regs->rip = gdb_regs[_PC];
+       regs->r8 = gdb_regs[_R8];
+       regs->r9 = gdb_regs[_R9];
+       regs->r10 = gdb_regs[_R10];
+       regs->r11 = gdb_regs[_R11];
+       regs->r12 = gdb_regs[_R12];
+       regs->r13 = gdb_regs[_R13];
+       regs->r14 = gdb_regs[_R14];
+       regs->r15 = gdb_regs[_R15];
+}
+#endif /* CONFIG_X86_64 */
+
+static struct hw_breakpoint {
+       unsigned enabled;
+       unsigned type;
+       unsigned len;
+       unsigned long addr;
+} breakinfo[4] = {
+       { .enabled = 0 },
+       { .enabled = 0 },
+       { .enabled = 0 },
+       { .enabled = 0 },
+};
+
+static void kgdb_correct_hw_break(void)
+{
+       int breakno;
+       int breakbit;
+       int correctit = 0;
+       unsigned long dr7;
+
+       get_debugreg(dr7, 7);
+       for (breakno = 0; breakno < 4; breakno++) {
+               breakbit = 2 << (breakno << 1);
+               if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
+                       correctit = 1;
+                       dr7 |= breakbit;
+                       dr7 &= ~(0xf0000 << (breakno << 2));
+                       dr7 |= ((breakinfo[breakno].len << 2) |
+                                breakinfo[breakno].type) <<
+                              ((breakno << 2) + 16);
+                       switch (breakno) {
+                       case 0:
+                               set_debugreg(breakinfo[0].addr, 0);
+                               break;
+
+                       case 1:
+                               set_debugreg(breakinfo[1].addr, 1);
+                               break;
+
+                       case 2:
+                               set_debugreg(breakinfo[2].addr, 2);
+                               break;
+
+                       case 3:
+                               set_debugreg(breakinfo[3].addr, 3);
+                               break;
+                       }
+               } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
+                       correctit = 1;
+                       dr7 &= ~breakbit;
+                       dr7 &= ~(0xf0000 << (breakno << 2));
+               }
+       }
+       if (correctit)
+               set_debugreg(dr7, 7);
+}
+
+static int kgdb_remove_hw_break(unsigned long addr, int len,
+                               enum kgdb_bptype bptype)
+{
+       int i;
+
+       for (i = 0; i < 4; i++)
+               if (breakinfo[i].addr == addr && breakinfo[i].enabled)
+                       break;
+       if (i == 4)
+               return -1;
+
+       breakinfo[i].enabled = 0;
+       return 0;
+}
+
+static void kgdb_remove_all_hw_break(void)
+{
+       int i;
+
+       for (i = 0; i < 4; i++)
+               memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
+}
+
+static int kgdb_set_hw_break(unsigned long addr, int len,
+                            enum kgdb_bptype bptype)
+{
+       int i;
+       unsigned type;
+
+       for (i = 0; i < 4; i++)
+               if (!breakinfo[i].enabled)
+                       break;
+       if (i == 4)
+               return -1;
+
+       switch (bptype) {
+       case bp_hardware_breakpoint:
+               type = 0;
+               len  = 1;
+               break;
+       case bp_write_watchpoint:
+               type = 1;
+               break;
+       case bp_access_watchpoint:
+               type = 3;
+               break;
+       default:
+               return -1;
+       }
+
+       if (len == 1 || len == 2 || len == 4)
+               breakinfo[i].len  = len - 1;
+       else
+               return -1;
+
+       breakinfo[i].enabled = 1;
+       breakinfo[i].addr = addr;
+       breakinfo[i].type = type;
+       return 0;
+}
+
+void kgdb_disable_hw_debug(struct pt_regs *regs)
+{
+       /* Disable hardware debugging while we are in kgdb */
+       set_debugreg(0UL, 7);
+}
+
+void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code)
+{
+       /* Master processor is completely in the debugger */
+       gdb_x86_vector = e_vector;
+       gdb_x86_errcode = err_code;
+}
+
+#ifdef CONFIG_SMP
+void kgdb_roundup_cpus(unsigned long flags)
+{
+       send_IPI_allbutself(APIC_DM_NMI);
+}
+#endif
+
+int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
+                              char *remcom_in_buffer, char *remcom_out_buffer,
+                              struct pt_regs *linux_regs)
+{
+       unsigned long addr;
+       char *ptr;
+       int newPC;
+       unsigned long dr6;
+
+       switch (remcom_in_buffer[0]) {
+       case 'c':
+       case 's':
+               /* try to read optional parameter, pc unchanged if no parm */
+               ptr = &remcom_in_buffer[1];
+               if (kgdb_hex2long(&ptr, &addr))
+                       instruction_pointer(linux_regs) = addr;
+               newPC = instruction_pointer(linux_regs);
+
+               /* clear the trace bit */
+               linux_regs->eflags &= ~TF_MASK;
+               atomic_set(&cpu_doing_single_step, -1);
+
+               /* set the trace bit if we're stepping */
+               if (remcom_in_buffer[0] == 's') {
+                       linux_regs->eflags |= TF_MASK;
+                       debugger_step = 1;
+                       if (kgdb_contthread)
+                               atomic_set(&cpu_doing_single_step,
+                                          raw_smp_processor_id());
+
+               }
+
+               get_debugreg(dr6, 6);
+               if (!(dr6 & 0x4000)) {
+                       int breakno;
+
+                       for (breakno = 0; breakno < 4; ++breakno) {
+                               if (dr6 & (1 << breakno) &&
+                                   breakinfo[breakno].type == 0) {
+                                       /* Set restore flag */
+                                       linux_regs->eflags |= X86_EFLAGS_RF;
+                                       break;
+                               }
+                       }
+               }
+               set_debugreg(0UL, 6);
+               kgdb_correct_hw_break();
+
+               return 0;
+       }
+       /* this means that we do not want to exit from the handler */
+       return -1;
+}
+
+#ifdef CONFIG_X86_64
+static struct pt_regs *in_interrupt_stack(unsigned long rsp, int cpu)
+{
+       struct pt_regs *regs = NULL;
+       unsigned long end = (unsigned long)cpu_pda(cpu)->irqstackptr;
+
+       if (rsp <= end && rsp >= end - IRQSTACKSIZE + 8)
+               regs = *(((struct pt_regs **)end) - 1);
+
+       return regs;
+}
+
+static struct pt_regs *in_exception_stack(unsigned long rsp, int cpu)
+{
+       struct tss_struct *init_tss = &__get_cpu_var(init_tss);
+       struct pt_regs *regs;
+       int i;
+
+       for (i = 0; i < N_EXCEPTION_STACKS; i++)
+               if (rsp >= init_tss[cpu].ist[i] &&
+                   rsp <= init_tss[cpu].ist[i] + EXCEPTION_STKSZ) {
+                       regs = (void *) init_tss[cpu].ist[i] + EXCEPTION_STKSZ;
+                       return regs - 1;
+               }
+
+       return NULL;
+}
+
+void kgdb_shadowinfo(struct pt_regs *regs, char *buffer, unsigned threadid)
+{
+       static char intr_desc[] = "Stack at interrupt entrypoint";
+       static char exc_desc[] = "Stack at exception entrypoint";
+       struct pt_regs *stregs;
+       int cpu = raw_smp_processor_id();
+       stregs = in_interrupt_stack(regs->rsp, cpu);
+       if (stregs)
+               kgdb_mem2hex(intr_desc, buffer, strlen(intr_desc));
+       else {
+               stregs = in_exception_stack(regs->rsp, cpu);
+               if (stregs)
+                       kgdb_mem2hex(exc_desc, buffer, strlen(exc_desc));
+       }
+}
+
+struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs, int threadid)
+{
+       struct pt_regs *stregs;
+       int cpu = raw_smp_processor_id();
+
+       stregs = in_interrupt_stack(regs->rsp, cpu);
+       if (stregs)
+               return current;
+       else {
+               stregs = in_exception_stack(regs->rsp, cpu);
+               if (stregs)
+                       return current;
+       }
+
+       return NULL;
+}
+
+struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid)
+{
+       struct pt_regs *stregs;
+       int cpu = raw_smp_processor_id();
+
+       stregs = in_interrupt_stack(regs->rsp, cpu);
+       if (stregs)
+               return stregs;
+       else {
+               stregs = in_exception_stack(regs->rsp, cpu);
+               if (stregs)
+                       return stregs;
+       }
+
+       return NULL;
+}
+#endif /* CONFIG_X86_64 */
+
+static inline int single_step_cont(struct pt_regs *regs,
+                       struct die_args *args)
+{
+       /* single step exception from kernel space to user space so
+        * eat the exception and continue the process
+        */
+       printk(KERN_ERR "KGDB: trap/step from kernel to user space,"
+                       " resuming...\n");
+       kgdb_arch_handle_exception(args->trapnr, args->signr,
+                                  args->err, "c", "", regs);
+
+       return NOTIFY_STOP;
+}
+
+static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
+                      void *ptr)
+{
+       struct die_args *args = ptr;
+       struct pt_regs *regs = args->regs;
+
+       switch (cmd) {
+       case DIE_NMI:
+               if (atomic_read(&debugger_active)) {
+                       /* KGDB CPU roundup */
+                       kgdb_nmihook(raw_smp_processor_id(), regs);
+                       return NOTIFY_STOP;
+               }
+               return NOTIFY_DONE;
+       case DIE_NMI_IPI:
+               if (atomic_read(&debugger_active)) {
+                       /* KGDB CPU roundup */
+                       if (kgdb_nmihook(raw_smp_processor_id(), regs))
+                               return NOTIFY_DONE;
+                       return NOTIFY_STOP;
+               }
+               return NOTIFY_DONE;
+       case DIE_NMIWATCHDOG:
+               if (atomic_read(&debugger_active)) {
+                       /* KGDB CPU roundup */
+                       kgdb_nmihook(raw_smp_processor_id(), regs);
+                       return NOTIFY_STOP;
+               }
+               /* Enter debugger */
+               break;
+       case DIE_DEBUG:
+               if (atomic_read(&cpu_doing_single_step) ==
+                       raw_smp_processor_id() && user_mode(regs))
+                       return single_step_cont(regs, args);
+               /* fall through */
+       default:
+               if (user_mode(regs))
+                       return NOTIFY_DONE;
+       }
+
+       if (kgdb_may_fault) {
+               kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+               return NOTIFY_STOP;
+       }
+
+       if (kgdb_handle_exception(args->trapnr, args->signr,
+                                 args->err, regs))
+               return NOTIFY_DONE;
+
+       return NOTIFY_STOP;
+}
+
+static struct notifier_block kgdb_notifier = {
+       .notifier_call = kgdb_notify,
+       .priority = 0x7fffffff, /* we need to be notified first */
+};
+
+int kgdb_arch_init(void)
+{
+       register_die_notifier(&kgdb_notifier);
+       return 0;
+}
+
+/*
+ * Skip an int3 exception when it occurs after a breakpoint has been
+ * removed. Backtrack eip by 1 since the int3 would have caused it to
+ * increment by 1.
+ */
+
+int kgdb_skipexception(int exception, struct pt_regs *regs)
+{
+       if (exception == 3 &&
+           kgdb_isremovedbreak(instruction_pointer(regs) - 1)) {
+               instruction_pointer(regs) -= 1;
+               return 1;
+       }
+       return 0;
+}
+
+unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
+{
+       if (exception == 3)
+               return instruction_pointer(regs) - 1;
+       return instruction_pointer(regs);
+}
+
+struct kgdb_arch arch_kgdb_ops = {
+       .gdb_bpt_instr = {0xcc},
+       .flags = KGDB_HW_BREAKPOINT,
+#ifdef CONFIG_X86_64
+       .shadowth = 1,
+#endif
+       .set_hw_breakpoint = kgdb_set_hw_break,
+       .remove_hw_breakpoint = kgdb_remove_hw_break,
+       .remove_all_hw_break = kgdb_remove_all_hw_break,
+       .correct_hw_break = kgdb_correct_hw_break,
+};
Index: b/arch/x86/kernel/kgdb_32.c
===================================================================
--- a/arch/x86/kernel/kgdb_32.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- */
-
-/*
- * Copyright (C) 2000-2001 VERITAS Software Corporation.
- * Copyright (C) 2007 Wind River Systems, Inc.
- * Copyright (C) 2007 MontaVista Software, Inc.
- */
-/*
- *  Contributor:     Lake Stevens Instrument Division$
- *  Written by:      Glenn Engel $
- *  Updated by:             Amit Kale<[EMAIL PROTECTED]>
- *  Updated by:             Tom Rini <[EMAIL PROTECTED]>
- *  Updated by:             Jason Wessel <[EMAIL PROTECTED]>
- *  Modified for 386 by Jim Kingdon, Cygnus Support.
- *  Origianl kgdb, compatibility with 2.1.xx kernel by
- *  David Grothe <[EMAIL PROTECTED]>
- *  Additional support from Tigran Aivazian <[EMAIL PROTECTED]>
- */
-
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <asm/vm86.h>
-#include <asm/system.h>
-#include <linux/ptrace.h>              /* for linux pt_regs struct */
-#include <linux/kgdb.h>
-#include <linux/init.h>
-#include <linux/kdebug.h>
-#include <asm/apicdef.h>
-#include <asm/desc.h>
-
-#include "mach_ipi.h"
-
-/* Put the error code here just in case the user cares.  */
-int gdb_i386errcode;
-/* Likewise, the vector number here (since GDB only gets the signal
-   number through the usual means, and that's not very specific).  */
-int gdb_i386vector = -1;
-
-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-{
-       gdb_regs[_EAX] = regs->eax;
-       gdb_regs[_EBX] = regs->ebx;
-       gdb_regs[_ECX] = regs->ecx;
-       gdb_regs[_EDX] = regs->edx;
-       gdb_regs[_ESI] = regs->esi;
-       gdb_regs[_EDI] = regs->edi;
-       gdb_regs[_EBP] = regs->ebp;
-       gdb_regs[_DS] = regs->xds;
-       gdb_regs[_ES] = regs->xes;
-       gdb_regs[_PS] = regs->eflags;
-       gdb_regs[_CS] = regs->xcs;
-       gdb_regs[_PC] = regs->eip;
-       gdb_regs[_ESP] = (int)(&regs->esp);
-       gdb_regs[_SS] = __KERNEL_DS;
-       gdb_regs[_FS] = 0xFFFF;
-       gdb_regs[_GS] = 0xFFFF;
-}
-
-/*
- * Extracts ebp, esp and eip values understandable by gdb from the values
- * saved by switch_to.
- * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
- * prior to entering switch_to is 8 greater then the value that is saved.
- * If switch_to changes, change following code appropriately.
- */
-void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct 
*p)
-{
-       gdb_regs[_EAX] = 0;
-       gdb_regs[_EBX] = 0;
-       gdb_regs[_ECX] = 0;
-       gdb_regs[_EDX] = 0;
-       gdb_regs[_ESI] = 0;
-       gdb_regs[_EDI] = 0;
-       gdb_regs[_EBP] = *(unsigned long *)p->thread.esp;
-       gdb_regs[_DS] = __KERNEL_DS;
-       gdb_regs[_ES] = __KERNEL_DS;
-       gdb_regs[_PS] = 0;
-       gdb_regs[_CS] = __KERNEL_CS;
-       gdb_regs[_PC] = p->thread.eip;
-       gdb_regs[_ESP] = p->thread.esp;
-       gdb_regs[_SS] = __KERNEL_DS;
-       gdb_regs[_FS] = 0xFFFF;
-       gdb_regs[_GS] = 0xFFFF;
-}
-
-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-{
-       regs->eax = gdb_regs[_EAX];
-       regs->ebx = gdb_regs[_EBX];
-       regs->ecx = gdb_regs[_ECX];
-       regs->edx = gdb_regs[_EDX];
-       regs->esi = gdb_regs[_ESI];
-       regs->edi = gdb_regs[_EDI];
-       regs->ebp = gdb_regs[_EBP];
-       regs->xds = gdb_regs[_DS];
-       regs->xes = gdb_regs[_ES];
-       regs->eflags = gdb_regs[_PS];
-       regs->xcs = gdb_regs[_CS];
-       regs->eip = gdb_regs[_PC];
-}
-
-static struct hw_breakpoint {
-       unsigned enabled;
-       unsigned type;
-       unsigned len;
-       unsigned addr;
-} breakinfo[4] = {
-       { .enabled = 0 },
-       { .enabled = 0 },
-       { .enabled = 0 },
-       { .enabled = 0 },
-};
-
-static void kgdb_correct_hw_break(void)
-{
-       int breakno;
-       int breakbit;
-       int correctit = 0;
-       unsigned long dr7;
-
-       get_debugreg(dr7, 7);
-       for (breakno = 0; breakno < 4; breakno++) {
-               breakbit = 2 << (breakno << 1);
-               if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
-                       correctit = 1;
-                       dr7 |= breakbit;
-                       dr7 &= ~(0xf0000 << (breakno << 2));
-                       dr7 |= ((breakinfo[breakno].len << 2) |
-                                breakinfo[breakno].type) <<
-                              ((breakno << 2) + 16);
-                       switch (breakno) {
-                       case 0:
-                               set_debugreg(breakinfo[0].addr, 0);
-                               break;
-
-                       case 1:
-                               set_debugreg(breakinfo[1].addr, 1);
-                               break;
-
-                       case 2:
-                               set_debugreg(breakinfo[2].addr, 2);
-                               break;
-
-                       case 3:
-                               set_debugreg(breakinfo[3].addr, 3);
-                               break;
-                       }
-               } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
-                       correctit = 1;
-                       dr7 &= ~breakbit;
-                       dr7 &= ~(0xf0000 << (breakno << 2));
-               }
-       }
-       if (correctit)
-               set_debugreg(dr7, 7);
-}
-
-static int kgdb_remove_hw_break(unsigned long addr, int len,
-                               enum kgdb_bptype bptype)
-{
-       int i;
-
-       for (i = 0; i < 4; i++)
-               if (breakinfo[i].addr == addr && breakinfo[i].enabled)
-                       break;
-       if (i == 4)
-               return -1;
-
-       breakinfo[i].enabled = 0;
-       return 0;
-}
-
-static void kgdb_remove_all_hw_break(void)
-{
-       int i;
-
-       for (i = 0; i < 4; i++)
-               memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
-}
-
-static int kgdb_set_hw_break(unsigned long addr, int len,
-                            enum kgdb_bptype bptype)
-{
-       int i;
-       unsigned type;
-
-       for (i = 0; i < 4; i++)
-               if (!breakinfo[i].enabled)
-                       break;
-       if (i == 4)
-               return -1;
-
-       switch (bptype) {
-       case bp_hardware_breakpoint:
-               type = 0;
-               len  = 1;
-               break;
-       case bp_write_watchpoint:
-               type = 1;
-               break;
-       case bp_access_watchpoint:
-               type = 3;
-               break;
-       default:
-               return -1;
-       }
-
-       if (len == 1 || len == 2 || len == 4)
-               breakinfo[i].len  = len - 1;
-       else
-               return -1;
-
-       breakinfo[i].enabled = 1;
-       breakinfo[i].addr = addr;
-       breakinfo[i].type = type;
-       return 0;
-}
-
-void kgdb_disable_hw_debug(struct pt_regs *regs)
-{
-       /* Disable hardware debugging while we are in kgdb */
-       set_debugreg(0, 7);
-}
-
-void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code)
-{
-       /* Master processor is completely in the debugger */
-       gdb_i386vector = e_vector;
-       gdb_i386errcode = err_code;
-}
-
-#ifdef CONFIG_SMP
-void kgdb_roundup_cpus(unsigned long flags)
-{
-       send_IPI_allbutself(APIC_DM_NMI);
-}
-#endif
-
-int kgdb_arch_handle_exception(int e_vector, int signo,
-                              int err_code, char *remcom_in_buffer,
-                              char *remcom_out_buffer,
-                              struct pt_regs *linux_regs)
-{
-       long addr;
-       char *ptr;
-       int newPC;
-       int dr6;
-
-       switch (remcom_in_buffer[0]) {
-       case 'c':
-       case 's':
-               /* try to read optional parameter, pc unchanged if no parm */
-               ptr = &remcom_in_buffer[1];
-               if (kgdb_hex2long(&ptr, &addr))
-                       linux_regs->eip = addr;
-               newPC = linux_regs->eip;
-
-               /* clear the trace bit */
-               linux_regs->eflags &= ~TF_MASK;
-               atomic_set(&cpu_doing_single_step, -1);
-
-               /* set the trace bit if we're stepping */
-               if (remcom_in_buffer[0] == 's') {
-                       linux_regs->eflags |= TF_MASK;
-                       debugger_step = 1;
-                       atomic_set(&cpu_doing_single_step,
-                                  raw_smp_processor_id());
-               }
-
-               get_debugreg(dr6, 6);
-               if (!(dr6 & 0x4000)) {
-                       int breakno;
-                       for (breakno = 0; breakno < 4; ++breakno) {
-                               if (dr6 & (1 << breakno) &&
-                                   breakinfo[breakno].type == 0) {
-                                       /* Set restore flag */
-                                       linux_regs->eflags |= X86_EFLAGS_RF;
-                                       break;
-                               }
-                       }
-               }
-               set_debugreg(0, 6);
-               kgdb_correct_hw_break();
-
-               return 0;
-       }
-       /* this means that we do not want to exit from the handler */
-       return -1;
-}
-
-static inline int single_step_cont(struct pt_regs *regs,
-                       struct die_args *args)
-{
-       /* single step exception from kernel space to user space so
-        * eat the exception and continue the process
-        */
-       printk(KERN_ERR "KGDB: trap/step from kernel to user space,"
-                       " resuming...\n");
-       kgdb_arch_handle_exception(args->trapnr, args->signr,
-                       args->err, "c", "", regs);
-
-       return NOTIFY_STOP;
-}
-
-static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
-                      void *ptr)
-{
-       struct die_args *args = ptr;
-       struct pt_regs *regs = args->regs;
-
-       switch (cmd) {
-       case DIE_NMI:
-               if (atomic_read(&debugger_active)) {
-                       /* KGDB CPU roundup */
-                       kgdb_nmihook(raw_smp_processor_id(), regs);
-                       return NOTIFY_STOP;
-               }
-               return NOTIFY_DONE;
-       case DIE_NMI_IPI:
-               if (atomic_read(&debugger_active)) {
-                       /* KGDB CPU roundup */
-                       if (kgdb_nmihook(raw_smp_processor_id(), regs))
-                               return NOTIFY_DONE;
-                       return NOTIFY_STOP;
-               }
-               return NOTIFY_DONE;
-       case DIE_NMIWATCHDOG:
-               if (atomic_read(&debugger_active)) {
-                       /* KGDB CPU roundup */
-                       kgdb_nmihook(raw_smp_processor_id(), regs);
-                       return NOTIFY_STOP;
-               }
-               /* Enter debugger */
-               break;
-       case DIE_DEBUG:
-               if (atomic_read(&cpu_doing_single_step) ==
-                       raw_smp_processor_id() &&
-                       user_mode(regs))
-                       return single_step_cont(regs, args);
-               /* fall through */
-       default:
-               if (user_mode(regs))
-                       return NOTIFY_DONE;
-       }
-
-       if (kgdb_may_fault) {
-               kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-               return NOTIFY_STOP;
-       }
-
-       if (kgdb_handle_exception(args->trapnr, args->signr,
-          args->err, regs))
-               return NOTIFY_DONE;
-
-       return NOTIFY_STOP;
-}
-
-static struct notifier_block kgdb_notifier = {
-       .notifier_call = kgdb_notify,
-};
-
-int kgdb_arch_init(void)
-{
-       register_die_notifier(&kgdb_notifier);
-       return 0;
-}
-
-/*
- * Skip an int3 exception when it occurs after a breakpoint has been
- * removed. Backtrack eip by 1 since the int3 would have caused it to
- * increment by 1.
- */
-
-int kgdb_skipexception(int exception, struct pt_regs *regs)
-{
-       if (exception == 3 && kgdb_isremovedbreak(regs->eip - 1)) {
-               regs->eip -= 1;
-               return 1;
-       }
-       return 0;
-}
-
-unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
-{
-       if (exception == 3)
-               return instruction_pointer(regs) - 1;
-
-       return instruction_pointer(regs);
-}
-
-struct kgdb_arch arch_kgdb_ops = {
-       .gdb_bpt_instr = {0xcc},
-       .flags = KGDB_HW_BREAKPOINT,
-       .set_hw_breakpoint = kgdb_set_hw_break,
-       .remove_hw_breakpoint = kgdb_remove_hw_break,
-       .remove_all_hw_break = kgdb_remove_all_hw_break,
-       .correct_hw_break = kgdb_correct_hw_break,
-};
Index: b/arch/x86/kernel/kgdb_64.c
===================================================================
--- a/arch/x86/kernel/kgdb_64.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- */
-
-/*
- * Copyright (C) 2004 Amit S. Kale <[EMAIL PROTECTED]>
- * Copyright (C) 2000-2001 VERITAS Software Corporation.
- * Copyright (C) 2002 Andi Kleen, SuSE Labs
- * Copyright (C) 2004 LinSysSoft Technologies Pvt. Ltd.
- * Copyright (C) 2007 Jason Wessel, Wind River Systems, Inc.
- * Copyright (C) 2007 MontaVista Software, Inc.
- */
-/****************************************************************************
- *  Contributor:     Lake Stevens Instrument Division$
- *  Written by:      Glenn Engel $
- *  Updated by:             Amit Kale<[EMAIL PROTECTED]>
- *  Modified for 386 by Jim Kingdon, Cygnus Support.
- *  Origianl kgdb, compatibility with 2.1.xx kernel by
- *  David Grothe <[EMAIL PROTECTED]>
- *  Integrated into 2.2.5 kernel by Tigran Aivazian <[EMAIL PROTECTED]>
- *  X86_64 changes from Andi Kleen's patch merged by Jim Houston
- */
-
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <asm/system.h>
-#include <linux/ptrace.h>              /* for linux pt_regs struct */
-#include <linux/kgdb.h>
-#include <linux/init.h>
-#include <linux/kdebug.h>
-#include <asm/apicdef.h>
-#include <asm/mach_apic.h>
-#include <asm/debugreg.h>
-
-/* Put the error code here just in case the user cares.  */
-int gdb_x86_64errcode;
-/* Likewise, the vector number here (since GDB only gets the signal
-   number through the usual means, and that's not very specific).  */
-int gdb_x86_64vector = -1;
-
-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-{
-       gdb_regs[_RAX] = regs->rax;
-       gdb_regs[_RBX] = regs->rbx;
-       gdb_regs[_RCX] = regs->rcx;
-       gdb_regs[_RDX] = regs->rdx;
-       gdb_regs[_RSI] = regs->rsi;
-       gdb_regs[_RDI] = regs->rdi;
-       gdb_regs[_RBP] = regs->rbp;
-       gdb_regs[_PS] = regs->eflags;
-       gdb_regs[_PC] = regs->rip;
-       gdb_regs[_R8] = regs->r8;
-       gdb_regs[_R9] = regs->r9;
-       gdb_regs[_R10] = regs->r10;
-       gdb_regs[_R11] = regs->r11;
-       gdb_regs[_R12] = regs->r12;
-       gdb_regs[_R13] = regs->r13;
-       gdb_regs[_R14] = regs->r14;
-       gdb_regs[_R15] = regs->r15;
-       gdb_regs[_RSP] = regs->rsp;
-}
-
-extern void thread_return(void);
-void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct 
*p)
-{
-       gdb_regs[_RAX] = 0;
-       gdb_regs[_RBX] = 0;
-       gdb_regs[_RCX] = 0;
-       gdb_regs[_RDX] = 0;
-       gdb_regs[_RSI] = 0;
-       gdb_regs[_RDI] = 0;
-       gdb_regs[_RBP] = *(unsigned long *)p->thread.rsp;
-       gdb_regs[_PS] = *(unsigned long *)(p->thread.rsp + 8);
-       gdb_regs[_PC] = (unsigned long)&thread_return;
-       gdb_regs[_R8] = 0;
-       gdb_regs[_R9] = 0;
-       gdb_regs[_R10] = 0;
-       gdb_regs[_R11] = 0;
-       gdb_regs[_R12] = 0;
-       gdb_regs[_R13] = 0;
-       gdb_regs[_R14] = 0;
-       gdb_regs[_R15] = 0;
-       gdb_regs[_RSP] = p->thread.rsp;
-}
-
-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-{
-       regs->rax = gdb_regs[_RAX];
-       regs->rbx = gdb_regs[_RBX];
-       regs->rcx = gdb_regs[_RCX];
-       regs->rdx = gdb_regs[_RDX];
-       regs->rsi = gdb_regs[_RSI];
-       regs->rdi = gdb_regs[_RDI];
-       regs->rbp = gdb_regs[_RBP];
-       regs->eflags = gdb_regs[_PS];
-       regs->rip = gdb_regs[_PC];
-       regs->r8 = gdb_regs[_R8];
-       regs->r9 = gdb_regs[_R9];
-       regs->r10 = gdb_regs[_R10];
-       regs->r11 = gdb_regs[_R11];
-       regs->r12 = gdb_regs[_R12];
-       regs->r13 = gdb_regs[_R13];
-       regs->r14 = gdb_regs[_R14];
-       regs->r15 = gdb_regs[_R15];
-}                              /* gdb_regs_to_regs */
-
-static struct hw_breakpoint {
-       unsigned enabled;
-       unsigned type;
-       unsigned len;
-       unsigned long addr;
-} breakinfo[4] = {
-       { .enabled = 0 },
-       { .enabled = 0 },
-       { .enabled = 0 },
-       { .enabled = 0 },
-};
-
-static void kgdb_correct_hw_break(void)
-{
-       int breakno;
-       int breakbit;
-       int correctit = 0;
-       unsigned long dr7;
-
-       get_debugreg(dr7, 7);
-       for (breakno = 0; breakno < 4; breakno++) {
-               breakbit = 2 << (breakno << 1);
-               if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
-                       correctit = 1;
-                       dr7 |= breakbit;
-                       dr7 &= ~(0xf0000 << (breakno << 2));
-                       dr7 |= ((breakinfo[breakno].len << 2) |
-                                breakinfo[breakno].type) <<
-                              ((breakno << 2) + 16);
-                       switch (breakno) {
-                       case 0:
-                               set_debugreg(breakinfo[0].addr, 0);
-                               break;
-
-                       case 1:
-                               set_debugreg(breakinfo[1].addr, 1);
-                               break;
-
-                       case 2:
-                               set_debugreg(breakinfo[2].addr, 2);
-                               break;
-
-                       case 3:
-                               set_debugreg(breakinfo[3].addr, 3);
-                               break;
-                       }
-               } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
-                       correctit = 1;
-                       dr7 &= ~breakbit;
-                       dr7 &= ~(0xf0000 << (breakno << 2));
-               }
-       }
-       if (correctit)
-               set_debugreg(dr7, 7);
-}
-
-static int kgdb_remove_hw_break(unsigned long addr, int len,
-                               enum kgdb_bptype bptype)
-{
-       int i;
-
-       for (i = 0; i < 4; i++)
-               if (breakinfo[i].addr == addr && breakinfo[i].enabled)
-                       break;
-       if (i == 4)
-               return -1;
-
-       breakinfo[i].enabled = 0;
-       return 0;
-}
-
-static void kgdb_remove_all_hw_break(void)
-{
-       int i;
-
-       for (i = 0; i < 4; i++)
-               memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
-}
-
-static int kgdb_set_hw_break(unsigned long addr, int len,
-                            enum kgdb_bptype bptype)
-{
-       int i;
-       unsigned type;
-
-       for (i = 0; i < 4; i++)
-               if (!breakinfo[i].enabled)
-                       break;
-       if (i == 4)
-               return -1;
-
-       switch (bptype) {
-       case bp_hardware_breakpoint:
-               type = 0;
-               len  = 1;
-               break;
-       case bp_write_watchpoint:
-               type = 1;
-               break;
-       case bp_access_watchpoint:
-               type = 3;
-               break;
-       default:
-               return -1;
-       }
-
-       if (len == 1 || len == 2 || len == 4)
-               breakinfo[i].len  = len - 1;
-       else
-               return -1;
-
-       breakinfo[i].enabled = 1;
-       breakinfo[i].addr = addr;
-       breakinfo[i].type = type;
-       return 0;
-}
-
-void kgdb_disable_hw_debug(struct pt_regs *regs)
-{
-       /* Disable hardware debugging while we are in kgdb */
-       set_debugreg(0UL, 7);
-}
-
-void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code)
-{
-       /* Master processor is completely in the debugger */
-       gdb_x86_64vector = e_vector;
-       gdb_x86_64errcode = err_code;
-}
-
-void kgdb_roundup_cpus(unsigned long flags)
-{
-       send_IPI_allbutself(APIC_DM_NMI);
-}
-
-int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
-                              char *remcomInBuffer, char *remcomOutBuffer,
-                              struct pt_regs *linux_regs)
-{
-       unsigned long addr;
-       char *ptr;
-       int newPC;
-       unsigned long dr6;
-
-       switch (remcomInBuffer[0]) {
-       case 'c':
-       case 's':
-               /* try to read optional parameter, pc unchanged if no parm */
-               ptr = &remcomInBuffer[1];
-               if (kgdb_hex2long(&ptr, &addr))
-                       linux_regs->rip = addr;
-               newPC = linux_regs->rip;
-
-               /* clear the trace bit */
-               linux_regs->eflags &= ~TF_MASK;
-               atomic_set(&cpu_doing_single_step, -1);
-
-               /* set the trace bit if we're stepping */
-               if (remcomInBuffer[0] == 's') {
-                       linux_regs->eflags |= TF_MASK;
-                       debugger_step = 1;
-                       if (kgdb_contthread)
-                               atomic_set(&cpu_doing_single_step,
-                                          raw_smp_processor_id());
-
-               }
-
-               get_debugreg(dr6, 6);
-               if (!(dr6 & 0x4000)) {
-                       int breakno;
-
-                       for (breakno = 0; breakno < 4; ++breakno) {
-                               if (dr6 & (1 << breakno) &&
-                                   breakinfo[breakno].type == 0) {
-                                       /* Set restore flag */
-                                       linux_regs->eflags |= X86_EFLAGS_RF;
-                                       break;
-                               }
-                       }
-               }
-               set_debugreg(0UL, 6);
-               kgdb_correct_hw_break();
-
-               return 0;
-       }
-       /* this means that we do not want to exit from the handler */
-       return -1;
-}
-
-static struct pt_regs *in_interrupt_stack(unsigned long rsp, int cpu)
-{
-       struct pt_regs *regs = NULL;
-       unsigned long end = (unsigned long)cpu_pda(cpu)->irqstackptr;
-
-       if (rsp <= end && rsp >= end - IRQSTACKSIZE + 8)
-               regs = *(((struct pt_regs **)end) - 1);
-
-       return regs;
-}
-
-static struct pt_regs *in_exception_stack(unsigned long rsp, int cpu)
-{
-       struct tss_struct *init_tss = &__get_cpu_var(init_tss);
-       struct pt_regs *regs;
-       int i;
-
-       for (i = 0; i < N_EXCEPTION_STACKS; i++)
-               if (rsp >= init_tss[cpu].ist[i] &&
-                   rsp <= init_tss[cpu].ist[i] + EXCEPTION_STKSZ) {
-                       regs = (void *) init_tss[cpu].ist[i] + EXCEPTION_STKSZ;
-                       return regs - 1;
-               }
-
-       return NULL;
-}
-
-void kgdb_shadowinfo(struct pt_regs *regs, char *buffer, unsigned threadid)
-{
-       static char intr_desc[] = "Stack at interrupt entrypoint";
-       static char exc_desc[] = "Stack at exception entrypoint";
-       struct pt_regs *stregs;
-       int cpu = raw_smp_processor_id();
-       stregs = in_interrupt_stack(regs->rsp, cpu);
-       if (stregs)
-               kgdb_mem2hex(intr_desc, buffer, strlen(intr_desc));
-       else {
-               stregs = in_exception_stack(regs->rsp, cpu);
-               if (stregs)
-                       kgdb_mem2hex(exc_desc, buffer, strlen(exc_desc));
-       }
-}
-
-struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs, int threadid)
-{
-       struct pt_regs *stregs;
-       int cpu = raw_smp_processor_id();
-
-       stregs = in_interrupt_stack(regs->rsp, cpu);
-       if (stregs)
-               return current;
-       else {
-               stregs = in_exception_stack(regs->rsp, cpu);
-               if (stregs)
-                       return current;
-       }
-
-       return NULL;
-}
-
-struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid)
-{
-       struct pt_regs *stregs;
-       int cpu = raw_smp_processor_id();
-
-       stregs = in_interrupt_stack(regs->rsp, cpu);
-       if (stregs)
-               return stregs;
-       else {
-               stregs = in_exception_stack(regs->rsp, cpu);
-               if (stregs)
-                       return stregs;
-       }
-
-       return NULL;
-}
-
-static inline int single_step_cont(struct pt_regs *regs,
-                       struct die_args *args)
-{
-       /* single step exception from kernel space to user space so
-        * eat the exception and continue the process
-        */
-       printk(KERN_ERR "KGDB: trap/step from kernel to user space,"
-                       " resuming...\n");
-       kgdb_arch_handle_exception(args->trapnr, args->signr,
-                       args->err, "c", "", regs);
-
-       return NOTIFY_STOP;
-}
-
-static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
-                      void *ptr)
-{
-       struct die_args *args = ptr;
-       struct pt_regs *regs = args->regs;
-
-       switch (cmd) {
-       case DIE_NMI:
-               if (atomic_read(&debugger_active)) {
-                       /* KGDB CPU roundup */
-                       kgdb_nmihook(raw_smp_processor_id(), regs);
-                       return NOTIFY_STOP;
-               }
-               return NOTIFY_DONE;
-       case DIE_NMI_IPI:
-               if (atomic_read(&debugger_active)) {
-                       /* KGDB CPU roundup */
-                       if (kgdb_nmihook(raw_smp_processor_id(), regs))
-                               return NOTIFY_DONE;
-                       return NOTIFY_STOP;
-               }
-               return NOTIFY_DONE;
-       case DIE_NMIWATCHDOG:
-               if (atomic_read(&debugger_active)) {
-                       /* KGDB CPU roundup */
-                       kgdb_nmihook(raw_smp_processor_id(), regs);
-                       return NOTIFY_STOP;
-               }
-               /* Enter debugger */
-               break;
-       case DIE_DEBUG:
-               if (atomic_read(&cpu_doing_single_step) ==
-                       raw_smp_processor_id() &&
-                       user_mode(regs))
-                       return single_step_cont(regs, args);
-               /* fall through */
-       default:
-               if (user_mode(regs))
-                       return NOTIFY_DONE;
-       }
-
-       if (kgdb_may_fault) {
-               kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-               return NOTIFY_STOP;
-       }
-
-       if (kgdb_handle_exception(args->trapnr, args->signr,
-               args->err, regs))
-               return NOTIFY_DONE;
-
-       return NOTIFY_STOP;
-}
-
-static struct notifier_block kgdb_notifier = {
-       .notifier_call = kgdb_notify,
-       .priority = 0x7fffffff, /* we need to be notified first */
-};
-
-int kgdb_arch_init(void)
-{
-       register_die_notifier(&kgdb_notifier);
-       return 0;
-}
-
-/*
- * Skip an int3 exception when it occurs after a breakpoint has been
- * removed. Backtrack eip by 1 since the int3 would have caused it to
- * increment by 1.
- */
-
-int kgdb_skipexception(int exception, struct pt_regs *regs)
-{
-       if (exception == 3 && kgdb_isremovedbreak(regs->rip - 1)) {
-               regs->rip -= 1;
-               return 1;
-       }
-       return 0;
-}
-
-unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
-{
-       if (exception == 3)
-               return instruction_pointer(regs) - 1;
-       return instruction_pointer(regs);
-}
-
-struct kgdb_arch arch_kgdb_ops = {
-       .gdb_bpt_instr = {0xcc},
-       .flags = KGDB_HW_BREAKPOINT,
-       .shadowth = 1,
-       .set_hw_breakpoint = kgdb_set_hw_break,
-       .remove_hw_breakpoint = kgdb_remove_hw_break,
-       .remove_all_hw_break = kgdb_remove_all_hw_break,
-       .correct_hw_break = kgdb_correct_hw_break,
-};
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to