All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@siemens.com>
To: Jason Wessel <jason.wessel@windriver.com>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH] kgdb:unify x86-kgdb
Date: Thu, 17 Jan 2008 15:32:22 +0100	[thread overview]
Message-ID: <478F66F6.40107@siemens.com> (raw)

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 <jan.kiszka@siemens.com>

---
 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 <amitkale@linsyssoft.com>
+ * 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 <trini@kernel.crashing.org>
+ *  Jim Kingdon, Cygnus Support.
+ *  David Grothe <dave@gcom.com>
+ *  Tigran Aivazian <tigran@sco.com>
+ *  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<akale@veritas.com>
- *  Updated by:	     Tom Rini <trini@kernel.crashing.org>
- *  Updated by:	     Jason Wessel <jason.wessel@windriver.com>
- *  Modified for 386 by Jim Kingdon, Cygnus Support.
- *  Origianl kgdb, compatibility with 2.1.xx kernel by
- *  David Grothe <dave@gcom.com>
- *  Additional support from Tigran Aivazian <tigran@sco.com>
- */
-
-#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 <amitkale@linsyssoft.com>
- * 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<akale@veritas.com>
- *  Modified for 386 by Jim Kingdon, Cygnus Support.
- *  Origianl kgdb, compatibility with 2.1.xx kernel by
- *  David Grothe <dave@gcom.com>
- *  Integrated into 2.2.5 kernel by Tigran Aivazian <tigran@sco.com>
- *  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,
-};

             reply	other threads:[~2008-01-17 14:32 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-17 14:32 Jan Kiszka [this message]
2008-01-17 14:35 ` [PATCH] kgdb:unify x86-kgdb Jason Wessel
2008-01-17 14:43   ` Jan Kiszka
2008-01-17 23:27     ` Jason Wessel
2008-01-18  9:10       ` Jan Kiszka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=478F66F6.40107@siemens.com \
    --to=jan.kiszka@siemens.com \
    --cc=jason.wessel@windriver.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.