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

📄 xmon.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Routines providing a simple monitor for use on the PowerMac. * * Copyright (C) 1996 Paul Mackerras. * *      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 of the License, or (at your option) any later version. */#include <linux/config.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/smp.h>#include <linux/mm.h>#include <linux/reboot.h>#include <asm/ptrace.h>#include <asm/string.h>#include <asm/prom.h>#include <asm/machdep.h>#include <asm/processor.h>#include <asm/pgtable.h>#include <asm/mmu.h>#include <asm/mmu_context.h>#include <asm/naca.h>#include <asm/paca.h>#include <asm/ppcdebug.h>#include "nonstdio.h"#include "privinst.h"#define scanhex	xmon_scanhex#define skipbl	xmon_skipbl#ifdef CONFIG_SMPstatic unsigned long cpus_in_xmon = 0;static unsigned long got_xmon = 0;static volatile int take_xmon = -1;#endif /* CONFIG_SMP */static unsigned long adrs;static int size = 1;static unsigned long ndump = 64;static unsigned long nidump = 16;static unsigned long ncsum = 4096;static int termch;static u_int bus_error_jmp[100];#define setjmp xmon_setjmp#define longjmp xmon_longjmp#define memlist_entry list_entry#define memlist_next(x) ((x)->next)#define memlist_prev(x) ((x)->prev)/* Max number of stack frames we are willing to produce on a backtrace. */#define MAXFRAMECOUNT 50/* Breakpoint stuff */struct bpt {	unsigned long address;	unsigned instr;	unsigned long count;	unsigned char enabled;	char funcname[64];	/* function name for humans */};#define NBPTS	16static struct bpt bpts[NBPTS];static struct bpt dabr;static struct bpt iabr;static unsigned bpinstr = 0x7fe00008;	/* trap *//* Prototypes */extern void (*debugger_fault_handler)(struct pt_regs *);static int cmds(struct pt_regs *);static int mread(unsigned long, void *, int);static int mwrite(unsigned long, void *, int);static void handle_fault(struct pt_regs *);static void byterev(unsigned char *, int);static void memex(void);static int bsesc(void);static void dump(void);static void prdump(unsigned long, long);#ifdef __MWERKS__static void prndump(unsigned, int);static int nvreadb(unsigned);#endifstatic int ppc_inst_dump(unsigned long, long);void print_address(unsigned long);static int getsp(void);static void dump_hash_table(void);static void backtrace(struct pt_regs *);static void excprint(struct pt_regs *);static void prregs(struct pt_regs *);static void memops(int);static void memlocate(void);static void memzcan(void);static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);int skipbl(void);int scanhex(unsigned long *valp);static void scannl(void);static int hexdigit(int);void getstring(char *, int);static void flush_input(void);static int inchar(void);static void take_input(char *);/* static void openforth(void); */static unsigned long read_spr(int);static void write_spr(int, unsigned long);static void super_regs(void);static void print_sysmap(void);static void remove_bpts(void);static void insert_bpts(void);static struct bpt *at_breakpoint(unsigned long pc);static void bpt_cmds(void);static void cacheflush(void);#ifdef CONFIG_SMPstatic void cpu_cmd(void);#endif /* CONFIG_SMP */static void csum(void);static void mem_translate(void);static void mem_check(void);static void mem_find_real(void);static void mem_find_vsid(void);static void mem_check_full_group(void);static void mem_check_pagetable_vsids (void);static void mem_map_check_slab(void);static void mem_map_lock_pages(void);static void mem_map_check_hash(void);static void mem_check_dup_rpn (void);static void debug_trace(void);extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned long);extern void printf(const char *fmt, ...);extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);extern int xmon_putc(int c, void *f);extern int putchar(int ch);extern int xmon_read_poll(void);extern int setjmp(u_int *);extern void longjmp(u_int *, int);extern unsigned long _ASR;pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va);	/* from htab.c */#define GETWORD(v)	(((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])static char *help_string = "\Commands:\n\  b	show breakpoints\n\  bd	set data breakpoint\n\  bi	set instruction breakpoint\n\  bc	clear breakpoint\n\  d	dump bytes\n\  di	dump instructions\n\  df	dump float values\n\  dd	dump double values\n\  e	print exception information\n\  f	flush cache\n\  h	dump hash table\n\  m	examine/change memory\n\  mm	move a block of memory\n\  ms	set a block of memory\n\  md	compare two blocks of memory\n\  ml	locate a block of memory\n\  mz	zero a block of memory\n\  mx	translation information for an effective address\n\  mi	show information about memory allocation\n\  M	print System.map\n\  p 	show the task list\n\  r	print registers\n\  s	single step\n\  S	print special registers\n\  t	print backtrace\n\  T	Enable/Disable PPCDBG flags\n\  x	exit monitor\n\  z	reboot\n\  Z	halt\n\";static int xmon_trace[NR_CPUS];#define SSTEP	1		/* stepping because of 's' command */#define BRSTEP	2		/* stepping over breakpoint *//* * Stuff for reading and writing memory safely */extern inline void sync(void){	asm volatile("sync; isync");}extern inline void __delay(unsigned int loops){	if (loops != 0)		__asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :				     "r" (loops) : "ctr");}/* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs). A PPC stack frame looks like this: High Address    Back Chain    FP reg save area    GP reg save area    Local var space    Parameter save area		(SP+48)    TOC save area		(SP+40)    link editor doubleword	(SP+32)    compiler doubleword		(SP+24)    LR save			(SP+16)    CR save			(SP+8)    Back Chain			(SP+0) Note that the LR (ret addr) may not be saved in the current frame if no functions have been called from the current function. *//* A traceback table typically follows each function. The find_tb_table() func will fill in this struct.  Note that the struct is not an exact match with the encoded table defined by the ABI.  It is defined here more for programming convenience. */struct tbtable {	unsigned long	flags;		/* flags: */#define TBTAB_FLAGSGLOBALLINK	(1L<<47)#define TBTAB_FLAGSISEPROL	(1L<<46)#define TBTAB_FLAGSHASTBOFF	(1L<<45)#define TBTAB_FLAGSINTPROC	(1L<<44)#define TBTAB_FLAGSHASCTL	(1L<<43)#define TBTAB_FLAGSTOCLESS	(1L<<42)#define TBTAB_FLAGSFPPRESENT	(1L<<41)#define TBTAB_FLAGSNAMEPRESENT	(1L<<38)#define TBTAB_FLAGSUSESALLOCA	(1L<<37)#define TBTAB_FLAGSSAVESCR	(1L<<33)#define TBTAB_FLAGSSAVESLR	(1L<<32)#define TBTAB_FLAGSSTORESBC	(1L<<31)#define TBTAB_FLAGSFIXUP	(1L<<30)#define TBTAB_FLAGSPARMSONSTK	(1L<<0)	unsigned char	fp_saved;	/* num fp regs saved f(32-n)..f31 */	unsigned char	gpr_saved;	/* num gpr's saved */	unsigned char	fixedparms;	/* num fixed point parms */	unsigned char	floatparms;	/* num float parms */	unsigned char	parminfo[32];	/* types of args.  null terminated */#define TBTAB_PARMFIXED 1#define TBTAB_PARMSFLOAT 2#define TBTAB_PARMDFLOAT 3	unsigned int	tb_offset;	/* offset from start of func */	unsigned long	funcstart;	/* addr of start of function */	char		name[64];	/* name of function (null terminated)*/};static int find_tb_table(unsigned long codeaddr, struct tbtable *tab);voidxmon(struct pt_regs *excp){	struct pt_regs regs;	int cmd;	unsigned long msr;	if (excp == NULL) {		/* Ok, grab regs as they are now.		 This won't do a particularily good job because the		 prologue has already been executed.		 ToDo: We could reach back into the callers save		 area to do a better job of representing the		 caller's state.		 */		asm volatile ("std	0,0(%0)\n\			std	1,8(%0)\n\			std	2,16(%0)\n\			std	3,24(%0)\n\			std	4,32(%0)\n\			std	5,40(%0)\n\			std	6,48(%0)\n\			std	7,56(%0)\n\			std	8,64(%0)\n\			std	9,72(%0)\n\			std	10,80(%0)\n\			std	11,88(%0)\n\			std	12,96(%0)\n\			std	13,104(%0)\n\			std	14,112(%0)\n\			std	15,120(%0)\n\			std	16,128(%0)\n\			std	17,136(%0)\n\			std	18,144(%0)\n\			std	19,152(%0)\n\			std	20,160(%0)\n\			std	21,168(%0)\n\			std	22,176(%0)\n\			std	23,184(%0)\n\			std	24,192(%0)\n\			std	25,200(%0)\n\			std	26,208(%0)\n\			std	27,216(%0)\n\			std	28,224(%0)\n\			std	29,232(%0)\n\			std	30,240(%0)\n\			std	31,248(%0)" : : "b" (&regs));		printf("xmon called\n");		/* Fetch the link reg for this stack frame.		 NOTE: the prev printf fills in the lr. */		regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];		regs.msr = get_msr();		regs.ctr = get_ctr();		regs.xer = get_xer();		regs.ccr = get_cr();		regs.trap = 0;		excp = &regs;	}	msr = get_msr();	set_msrd(msr & ~MSR_EE);	/* disable interrupts */	excprint(excp);#ifdef CONFIG_SMP	if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))		for (;;)			;	while (test_and_set_bit(0, &got_xmon)) {		if (take_xmon == smp_processor_id()) {			take_xmon = -1;			break;		}	}	/*	 * XXX: breakpoints are removed while any cpu is in xmon	 */#endif /* CONFIG_SMP */	remove_bpts();	cmd = cmds(excp);	if (cmd == 's') {		xmon_trace[smp_processor_id()] = SSTEP;		excp->msr |= 0x400;	} else if (at_breakpoint(excp->nip)) {		xmon_trace[smp_processor_id()] = BRSTEP;		excp->msr |= 0x400;	} else {		xmon_trace[smp_processor_id()] = 0;		insert_bpts();	}#ifdef CONFIG_SMP	clear_bit(0, &got_xmon);	clear_bit(smp_processor_id(), &cpus_in_xmon);#endif /* CONFIG_SMP */	set_msrd(msr);		/* restore interrupt enable */}/* Code can call this to get a backtrace and continue. */voidxmon_backtrace(const char *fmt, ...){	va_list ap;	struct pt_regs regs;	/* Ok, grab regs as they are now.	 This won't do a particularily good job because the	 prologue has already been executed.	 ToDo: We could reach back into the callers save	 area to do a better job of representing the	 caller's state.	 */	asm volatile ("std	0,0(%0)\n\	    std	1,8(%0)\n\	    std	2,16(%0)\n\	    std	3,24(%0)\n\	    std	4,32(%0)\n\	    std	5,40(%0)\n\	    std	6,48(%0)\n\	    std	7,56(%0)\n\	    std	8,64(%0)\n\	    std	9,72(%0)\n\	    std	10,80(%0)\n\	    std	11,88(%0)\n\	    std	12,96(%0)\n\	    std	13,104(%0)\n\	    std	14,112(%0)\n\	    std	15,120(%0)\n\	    std	16,128(%0)\n\	    std	17,136(%0)\n\	    std	18,144(%0)\n\	    std	19,152(%0)\n\	    std	20,160(%0)\n\	    std	21,168(%0)\n\	    std	22,176(%0)\n\	    std	23,184(%0)\n\	    std	24,192(%0)\n\	    std	25,200(%0)\n\	    std	26,208(%0)\n\	    std	27,216(%0)\n\	    std	28,224(%0)\n\	    std	29,232(%0)\n\	    std	30,240(%0)\n\	    std	31,248(%0)" : : "b" (&regs));	/* Fetch the link reg for this stack frame.	 NOTE: the prev printf fills in the lr. */	regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];	regs.msr = get_msr();	regs.ctr = get_ctr();	regs.xer = get_xer();	regs.ccr = get_cr();	regs.trap = 0;	va_start(ap, fmt);	xmon_vfprintf(stdout, fmt, ap);	xmon_putc('\n', stdout);	va_end(ap);	take_input("\n");	backtrace(&regs);}/* Call this to poll for ^C during busy operations. * Returns true if the user has hit ^C. */intxmon_interrupted(void){	int ret = xmon_read_poll();	if (ret == 3) {		printf("\n^C interrupted.\n");		return 1;	}	return 0;}voidxmon_irq(int irq, void *d, struct pt_regs *regs){	unsigned long flags;	__save_flags(flags);	__cli();	printf("Keyboard interrupt\n");	xmon(regs);	__restore_flags(flags);}intxmon_bpt(struct pt_regs *regs){	struct bpt *bp;	bp = at_breakpoint(regs->nip);	if (!bp)		return 0;	if (bp->count) {		--bp->count;		remove_bpts();		excprint(regs);		xmon_trace[smp_processor_id()] = BRSTEP;		regs->msr |= 0x400;	} else {		printf("Stopped at breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname);		xmon(regs);	}	return 1;}intxmon_sstep(struct pt_regs *regs){	if (!xmon_trace[smp_processor_id()])		return 0;	if (xmon_trace[smp_processor_id()] == BRSTEP) {		xmon_trace[smp_processor_id()] = 0;		insert_bpts();	} else {		xmon(regs);	}	return 1;}intxmon_dabr_match(struct pt_regs *regs){	if (dabr.enabled && dabr.count) {		--dabr.count;		remove_bpts();		excprint(regs);		xmon_trace[smp_processor_id()] = BRSTEP;		regs->msr |= 0x400;	} else {		dabr.instr = regs->nip;		xmon(regs);	}	return 1;}intxmon_iabr_match(struct pt_regs *regs){	if (iabr.enabled && iabr.count) {		--iabr.count;		remove_bpts();		excprint(regs);		xmon_trace[smp_processor_id()] = BRSTEP;		regs->msr |= 0x400;	} else {		xmon(regs);	}	return 1;}static struct bpt *at_breakpoint(unsigned long pc){	int i;	struct bpt *bp;	if (dabr.enabled && pc == dabr.instr)		return &dabr;	if (iabr.enabled && pc == iabr.address)		return &iabr;	bp = bpts;	for (i = 0; i < NBPTS; ++i, ++bp)		if (bp->enabled && pc == bp->address)			return bp;	return 0;}static voidinsert_bpts(){	int i;	struct bpt *bp;	if (naca->platform != PLATFORM_PSERIES)		return;	bp = bpts;	for (i = 0; i < NBPTS; ++i, ++bp) {		if (!bp->enabled)			continue;		if (mread(bp->address, &bp->instr, 4) != 4		    || mwrite(bp->address, &bpinstr, 4) != 4) {

⌨️ 快捷键说明

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