⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppc-stub.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* In case GDB is started before us, ack any packets (presumably	 * "$?#xx") sitting there.	 *	 * I've found this code causes more problems than it solves,	 * so that's why it's commented out.  GDB seems to work fine	 * now starting either before or after the kernel   -bwb	 */	while((c = getDebugChar()) != '$');	while((c = getDebugChar()) != '#');	c = getDebugChar(); /* eat first csum byte */	c = getDebugChar(); /* eat second csum byte */	putDebugChar('+'); /* ack it */#endif	debugger = kgdb;	debugger_bpt = kgdb_bpt;	debugger_sstep = kgdb_sstep;	debugger_iabr_match = kgdb_iabr_match;	debugger_dabr_match = kgdb_dabr_match;	initialized = 1;}static void kgdb_fault_handler(struct pt_regs *regs){	kgdb_longjmp((long*)fault_jmp_buf, 1);}int kgdb_bpt(struct pt_regs *regs){	return handle_exception(regs);}int kgdb_sstep(struct pt_regs *regs){	return handle_exception(regs);}void kgdb(struct pt_regs *regs){	handle_exception(regs);}int kgdb_iabr_match(struct pt_regs *regs){	printk(KERN_ERR "kgdb doesn't support iabr, what?!?\n");	return handle_exception(regs);}int kgdb_dabr_match(struct pt_regs *regs){	printk(KERN_ERR "kgdb doesn't support dabr, what?!?\n");	return handle_exception(regs);}/* Convert the hardware trap type code to a unix signal number. *//* * This table contains the mapping between PowerPC hardware trap types, and * signals, which are primarily what GDB understands. */static struct hard_trap_info{	unsigned int tt;		/* Trap type code for powerpc */	unsigned char signo;		/* Signal that we map this trap into */} hard_trap_info[] = {#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)	{ 0x100, SIGINT  },		/* critical input interrupt */	{ 0x200, SIGSEGV },		/* machine check */	{ 0x300, SIGSEGV },		/* data storage */	{ 0x400, SIGBUS  },		/* instruction storage */	{ 0x500, SIGINT  },		/* interrupt */	{ 0x600, SIGBUS  },		/* alignment */	{ 0x700, SIGILL  },		/* program */	{ 0x800, SIGILL  },		/* reserved */	{ 0x900, SIGILL  },		/* reserved */	{ 0xa00, SIGILL  },		/* reserved */	{ 0xb00, SIGILL  },		/* reserved */	{ 0xc00, SIGCHLD },		/* syscall */	{ 0xd00, SIGILL  },		/* reserved */	{ 0xe00, SIGILL  },		/* reserved */	{ 0xf00, SIGILL  },		/* reserved */	/*	** 0x1000  PIT	** 0x1010  FIT	** 0x1020  watchdog	** 0x1100  data TLB miss	** 0x1200  instruction TLB miss	*/	{ 0x2002, SIGTRAP},		/* debug */#else	{ 0x200, SIGSEGV },		/* machine check */	{ 0x300, SIGSEGV },		/* address error (store) */	{ 0x400, SIGBUS },		/* instruction bus error */	{ 0x500, SIGINT },		/* interrupt */	{ 0x600, SIGBUS },		/* alingment */	{ 0x700, SIGTRAP },		/* breakpoint trap */	{ 0x800, SIGFPE },		/* fpu unavail */	{ 0x900, SIGALRM },		/* decrementer */	{ 0xa00, SIGILL },		/* reserved */	{ 0xb00, SIGILL },		/* reserved */	{ 0xc00, SIGCHLD },		/* syscall */	{ 0xd00, SIGTRAP },		/* single-step/watch */	{ 0xe00, SIGFPE },		/* fp assist */#endif	{ 0, 0}				/* Must be last */};static int computeSignal(unsigned int tt){	struct hard_trap_info *ht;	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)		if (ht->tt == tt)			return ht->signo;	return SIGHUP; /* default for things we don't know about */}#define PC_REGNUM 64#define SP_REGNUM 1/* * This function does all command processing for interfacing to gdb. */static inthandle_exception (struct pt_regs *regs){	int sigval;	int addr;	int length;	char *ptr;	unsigned int msr;	/* We don't handle user-mode breakpoints. */	if (user_mode(regs))		return 0;	if (debugger_fault_handler) {		debugger_fault_handler(regs);		panic("kgdb longjump failed!\n");	}	if (kgdb_active) {		printk(KERN_ERR "interrupt while in kgdb, returning\n");		return 0;	}	kgdb_active = 1;	kgdb_started = 1;#ifdef KGDB_DEBUG	printk("kgdb: entering handle_exception; trap [0x%x]\n",			(unsigned int)regs->trap);#endif	kgdb_interruptible(0);	lock_kernel();	msr = mfmsr();	mtmsr(msr & ~MSR_EE);	/* disable interrupts */	if (regs->nip == (unsigned long)breakinst) {		/* Skip over breakpoint trap insn */		regs->nip += 4;	}	/* reply to host that an exception has occurred */	sigval = computeSignal(regs->trap);	ptr = remcomOutBuffer;	*ptr++ = 'T';	*ptr++ = hexchars[sigval >> 4];	*ptr++ = hexchars[sigval & 0xf];	*ptr++ = hexchars[PC_REGNUM >> 4];	*ptr++ = hexchars[PC_REGNUM & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *)&regs->nip, ptr, 4);	*ptr++ = ';';	*ptr++ = hexchars[SP_REGNUM >> 4];	*ptr++ = hexchars[SP_REGNUM & 0xf];	*ptr++ = ':';	ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4);	*ptr++ = ';';	*ptr++ = 0;	putpacket(remcomOutBuffer);	if (kdebug)		printk("remcomOutBuffer: %s\n", remcomOutBuffer);	/* XXX We may want to add some features dealing with poking the	 * XXX page tables, ... (look at sparc-stub.c for more info)	 * XXX also required hacking to the gdb sources directly...	 */	while (1) {		remcomOutBuffer[0] = 0;		getpacket(remcomInBuffer);		switch (remcomInBuffer[0]) {		case '?': /* report most recent signal */			remcomOutBuffer[0] = 'S';			remcomOutBuffer[1] = hexchars[sigval >> 4];			remcomOutBuffer[2] = hexchars[sigval & 0xf];			remcomOutBuffer[3] = 0;			break;#if 0		case 'q': /* this screws up gdb for some reason...*/		{			extern long _start, sdata, __bss_start;			ptr = &remcomInBuffer[1];			if (strncmp(ptr, "Offsets", 7) != 0)				break;			ptr = remcomOutBuffer;			sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x",				&_start, &sdata, &__bss_start);			break;		}#endif		case 'd':			/* toggle debug flag */			kdebug ^= 1;			break;		case 'g':	/* return the value of the CPU registers.				 * some of them are non-PowerPC names :(				 * they are stored in gdb like:				 * struct {				 *     u32 gpr[32];				 *     f64 fpr[32];				 *     u32 pc, ps, cnd, lr; (ps=msr)				 *     u32 cnt, xer, mq;				 * }				 */		{			int i;			ptr = remcomOutBuffer;			/* General Purpose Regs */			ptr = mem2hex((char *)regs, ptr, 32 * 4);			/* Floating Point Regs - FIXME */			/*ptr = mem2hex((char *), ptr, 32 * 8);*/			for(i=0; i<(32*8*2); i++) { /* 2chars/byte */				ptr[i] = '0';			}			ptr += 32*8*2;			/* pc, msr, cr, lr, ctr, xer, (mq is unused) */			ptr = mem2hex((char *)&regs->nip, ptr, 4);			ptr = mem2hex((char *)&regs->msr, ptr, 4);			ptr = mem2hex((char *)&regs->ccr, ptr, 4);			ptr = mem2hex((char *)&regs->link, ptr, 4);			ptr = mem2hex((char *)&regs->ctr, ptr, 4);			ptr = mem2hex((char *)&regs->xer, ptr, 4);		}			break;		case 'G': /* set the value of the CPU registers */		{			ptr = &remcomInBuffer[1];			/*			 * If the stack pointer has moved, you should pray.			 * (cause only god can help you).			 */			/* General Purpose Regs */			hex2mem(ptr, (char *)regs, 32 * 4);			/* Floating Point Regs - FIXME?? */			/*ptr = hex2mem(ptr, ??, 32 * 8);*/			ptr += 32*8*2;			/* pc, msr, cr, lr, ctr, xer, (mq is unused) */			ptr = hex2mem(ptr, (char *)&regs->nip, 4);			ptr = hex2mem(ptr, (char *)&regs->msr, 4);			ptr = hex2mem(ptr, (char *)&regs->ccr, 4);			ptr = hex2mem(ptr, (char *)&regs->link, 4);			ptr = hex2mem(ptr, (char *)&regs->ctr, 4);			ptr = hex2mem(ptr, (char *)&regs->xer, 4);			strcpy(remcomOutBuffer,"OK");		}			break;		case 'H':			/* don't do anything, yet, just acknowledge */			hexToInt(&ptr, &addr);			strcpy(remcomOutBuffer,"OK");			break;		case 'm':	/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */				/* Try to read %x,%x.  */			ptr = &remcomInBuffer[1];			if (hexToInt(&ptr, &addr) && *ptr++ == ','					&& hexToInt(&ptr, &length)) {				if (mem2hex((char *)addr, remcomOutBuffer,							length))					break;				strcpy(remcomOutBuffer, "E03");			} else				strcpy(remcomOutBuffer, "E01");			break;		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */			/* Try to read '%x,%x:'.  */			ptr = &remcomInBuffer[1];			if (hexToInt(&ptr, &addr) && *ptr++ == ','					&& hexToInt(&ptr, &length)					&& *ptr++ == ':') {				if (hex2mem(ptr, (char *)addr, length))					strcpy(remcomOutBuffer, "OK");				else					strcpy(remcomOutBuffer, "E03");				flush_icache_range(addr, addr+length);			} else				strcpy(remcomOutBuffer, "E02");			break;		case 'k': /* kill the program, actually just continue */		case 'c': /* cAA..AA  Continue; address AA..AA optional */			/* try to read optional parameter, pc unchanged if no parm */			ptr = &remcomInBuffer[1];			if (hexToInt(&ptr, &addr))				regs->nip = addr;/* Need to flush the instruction cache here, as we may have deposited a * breakpoint, and the icache probably has no way of knowing that a data ref to * some location may have changed something that is in the instruction cache. */			kgdb_flush_cache_all();			mtmsr(msr);			kgdb_interruptible(1);			unlock_kernel();			kgdb_active = 0;			if (kdebug) {				printk("remcomInBuffer: %s\n", remcomInBuffer);				printk("remcomOutBuffer: %s\n", remcomOutBuffer);			}			return 1;		case 's':			kgdb_flush_cache_all();#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)			mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC);			regs->msr |= MSR_DE;#else			regs->msr |= MSR_SE;#endif			unlock_kernel();			kgdb_active = 0;			if (kdebug) {				printk("remcomInBuffer: %s\n", remcomInBuffer);				printk("remcomOutBuffer: %s\n", remcomOutBuffer);			}			return 1;		case 'r':		/* Reset (if user process..exit ???)*/			panic("kgdb reset.");			break;		}			/* switch */		if (remcomOutBuffer[0] && kdebug) {			printk("remcomInBuffer: %s\n", remcomInBuffer);			printk("remcomOutBuffer: %s\n", remcomOutBuffer);		}		/* reply to the request */		putpacket(remcomOutBuffer);	} /* while(1) */}/* This function will generate a breakpoint exception.  It is used at the   beginning of a program to sync up with a debugger and can be used   otherwise as a quick means to stop program execution and "break" into   the debugger. */voidbreakpoint(void){	if (!initialized) {		printk("breakpoint() called b4 kgdb init\n");		return;	}	asm("	.globl breakinst	\n\	     breakinst: .long 0x7d821008");}#ifdef CONFIG_KGDB_CONSOLE/* Output string in GDB O-packet format if GDB has connected. If nothing   output, returns 0 (caller must then handle output). */intkgdb_output_string (const char* s, unsigned int count){	char buffer[512];	if (!kgdb_started)		return 0;	count = (count <= (sizeof(buffer) / 2 - 2))		? count : (sizeof(buffer) / 2 - 2);	buffer[0] = 'O';	mem2hex (s, &buffer[1], count);	putpacket(buffer);	return 1;}#endifstatic void sysrq_handle_gdb(int key, struct pt_regs *pt_regs,			     struct tty_struct *tty){	printk("Entering GDB stub\n");	breakpoint();}static struct sysrq_key_op sysrq_gdb_op = {        .handler        = sysrq_handle_gdb,        .help_msg       = "Gdb",        .action_msg     = "GDB",};static int gdb_register_sysrq(void){	printk("Registering GDB sysrq handler\n");	register_sysrq_key('g', &sysrq_gdb_op);	return 0;}module_init(gdb_register_sysrq);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -