📄 i386-lite.patch
字号:
This adds the basic support for i386. The only real changes outside of newKGDB files and Makefile/related is that for support early on we must set sometraps sooner rather than later, but it is safe to always do this. Also, tobreak in as early as possible, i386 now calls parse_early_param() toexplicitly look at anything marked early_param(). We also add a few morenotify_die() calls in areas where KGDB needs to take a peek sometimes.Finally, we add some labels to switch_to macros so that when backtracing wecan see where we really are.Signed-off-by: Milind Dumbare <milind@linsyssoft.com> arch/i386/kernel/Makefile | 1 arch/i386/kernel/kgdb-jmp.S | 74 ++++++++++ arch/i386/kernel/kgdb.c | 314 ++++++++++++++++++++++++++++++++++++++++++++ arch/i386/kernel/setup.c | 3 arch/i386/kernel/traps.c | 14 + arch/i386/mm/fault.c | 4 include/asm-i386/kdebug.h | 1 include/asm-i386/kgdb.h | 49 ++++++ lib/Kconfig.debug | 2 9 files changed, 456 insertions(+), 6 deletions(-)Index: linux-2.6.16/arch/i386/mm/fault.c===================================================================--- linux-2.6.16.orig/arch/i386/mm/fault.c 2006-03-20 11:23:29.000000000 +0530+++ linux-2.6.16/arch/i386/mm/fault.c 2006-04-25 11:28:55.000000000 +0530@@ -433,6 +433,10 @@ if (is_prefetch(regs, address, error_code)) return; + if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs,+ error_code, 14, SIGSEGV) == NOTIFY_STOP)+ return;+ /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice.Index: linux-2.6.16/arch/i386/kernel/kgdb-jmp.S===================================================================--- linux-2.6.16.orig/arch/i386/kernel/kgdb-jmp.S 2006-04-25 10:59:23.506518750 +0530+++ linux-2.6.16/arch/i386/kernel/kgdb-jmp.S 2006-04-25 11:28:55.000000000 +0530@@ -0,0 +1,74 @@+/*+ * arch/i386/kernel/kgdb-jmp.S+ *+ * Save and restore system registers so that within a limited frame we+ * may have a fault and "jump back" to a known safe location.+ *+ * Author: George Anzinger <george@mvista.com>+ *+ * Cribbed from glibc, which carries the following:+ * Copyright (C) 1996, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.+ * Copyright (C) 2005 by MontaVista Software.+ *+ * This file is licensed under the terms of the GNU General Public License+ * version 2. This program as licensed "as is" without any warranty of+ * any kind, whether express or implied.+ */++#include <linux/linkage.h>++#define PCOFF 0+#define LINKAGE 4 /* just the return address */+#define PTR_SIZE 4+#define PARMS LINKAGE /* no space for saved regs */+#define JMPBUF PARMS+#define VAL JMPBUF+PTR_SIZE++#define JB_BX 0+#define JB_SI 1+#define JB_DI 2+#define JB_BP 3+#define JB_SP 4+#define JB_PC 5++/* This must be called prior to kgdb_fault_longjmp and+ * kgdb_fault_longjmp must not be called outside of the context of the+ * last call to kgdb_fault_setjmp.+ * kgdb_fault_setjmp(int *jmp_buf[6])+ */+ENTRY(kgdb_fault_setjmp)+ movl JMPBUF(%esp), %eax++ /* Save registers. */+ movl %ebx, (JB_BX*4)(%eax)+ movl %esi, (JB_SI*4)(%eax)+ movl %edi, (JB_DI*4)(%eax)+ /* Save SP as it will be after we return. */+ leal JMPBUF(%esp), %ecx+ movl %ecx, (JB_SP*4)(%eax)+ movl PCOFF(%esp), %ecx /* Save PC we are returning to now. */+ movl %ecx, (JB_PC*4)(%eax)+ movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer. */++ /* Restore state so we can now try the access. */+ movl JMPBUF(%esp), %ecx /* User's jmp_buf in %ecx. */+ /* Save the return address now. */+ movl (JB_PC*4)(%ecx), %edx+ /* Restore registers. */+ movl $0, %eax+ movl (JB_SP*4)(%ecx), %esp+ jmp *%edx /* Jump to saved PC. */++/* kgdb_fault_longjmp(int *jmp_buf[6]) */+ENTRY(kgdb_fault_longjmp)+ movl JMPBUF(%esp), %ecx /* User's jmp_buf in %ecx. */+ /* Save the return address now. */+ movl (JB_PC*4)(%ecx), %edx+ /* Restore registers. */+ movl (JB_BX*4)(%ecx), %ebx+ movl (JB_SI*4)(%ecx), %esi+ movl (JB_DI*4)(%ecx), %edi+ movl (JB_BP*4)(%ecx), %ebp+ movl $1, %eax+ movl (JB_SP*4)(%ecx), %esp+ jmp *%edx /* Jump to saved PC. */Index: linux-2.6.16/arch/i386/kernel/kgdb.c===================================================================--- linux-2.6.16.orig/arch/i386/kernel/kgdb.c 2006-04-25 10:59:23.506518750 +0530+++ linux-2.6.16/arch/i386/kernel/kgdb.c 2006-04-25 11:28:55.000000000 +0530@@ -0,0 +1,314 @@+/*+ *+ * 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.+ */+/*+ * Contributor: Lake Stevens Instrument Division$+ * Written by: Glenn Engel $+ * Updated by: Amit Kale<akale@veritas.com>+ * Updated by: Tom Rini <trini@kernel.crashing.org>+ * 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 <asm/ptrace.h> /* for linux pt_regs struct */+#include <linux/kgdb.h>+#include <linux/init.h>+#include <asm/apicdef.h>+#include <asm/desc.h>+#include <asm/kdebug.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;++extern atomic_t cpu_doing_single_step;++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)(®s->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 },+};++void kgdb_correct_hw_break(void)+{+ int breakno;+ int correctit;+ int breakbit;+ unsigned dr7;++ asm volatile ("movl %%db7, %0\n":"=r" (dr7)+ :);+ do {+ unsigned addr0, addr1, addr2, addr3;+ asm volatile ("movl %%db0, %0\n"+ "movl %%db1, %1\n"+ "movl %%db2, %2\n"+ "movl %%db3, %3\n":"=r" (addr0), "=r"(addr1),+ "=r"(addr2), "=r"(addr3):);+ } while (0);+ correctit = 0;+ for (breakno = 0; breakno < 3; 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) << 16) <<+ (breakno << 2);+ switch (breakno) {+ case 0:+ asm volatile ("movl %0, %%dr0\n"::"r"+ (breakinfo[breakno].addr));+ break;++ case 1:+ asm volatile ("movl %0, %%dr1\n"::"r"+ (breakinfo[breakno].addr));+ break;++ case 2:+ asm volatile ("movl %0, %%dr2\n"::"r"+ (breakinfo[breakno].addr));+ break;++ case 3:+ asm volatile ("movl %0, %%dr3\n"::"r"+ (breakinfo[breakno].addr));+ break;+ }+ } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {+ correctit = 1;+ dr7 &= ~breakbit;+ dr7 &= ~(0xf0000 << (breakno << 2));+ }+ }+ if (correctit)+ asm volatile ("movl %0, %%db7\n"::"r" (dr7));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -