diff options
Diffstat (limited to 'arch/powerpc/xmon/xmon.c')
| -rw-r--r-- | arch/powerpc/xmon/xmon.c | 411 | 
1 files changed, 244 insertions, 167 deletions
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index d17d04cfb2c..d199bfa2f1f 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -17,8 +17,9 @@  #include <linux/reboot.h>  #include <linux/delay.h>  #include <linux/kallsyms.h> +#include <linux/kmsg_dump.h>  #include <linux/cpumask.h> -#include <linux/module.h> +#include <linux/export.h>  #include <linux/sysrq.h>  #include <linux/interrupt.h>  #include <linux/irq.h> @@ -39,9 +40,10 @@  #include <asm/irq_regs.h>  #include <asm/spu.h>  #include <asm/spu_priv1.h> -#include <asm/firmware.h>  #include <asm/setjmp.h>  #include <asm/reg.h> +#include <asm/debug.h> +#include <asm/hw_breakpoint.h>  #ifdef CONFIG_PPC64  #include <asm/hvcall.h> @@ -51,14 +53,13 @@  #include "nonstdio.h"  #include "dis-asm.h" -#define scanhex	xmon_scanhex -#define skipbl	xmon_skipbl -  #ifdef CONFIG_SMP  static cpumask_t cpus_in_xmon = CPU_MASK_NONE;  static unsigned long xmon_taken = 1;  static int xmon_owner;  static int xmon_gate; +#else +#define xmon_owner 0  #endif /* CONFIG_SMP */  static unsigned long in_xmon __read_mostly = 0; @@ -166,15 +167,15 @@ extern void xmon_leave(void);  #ifdef CONFIG_PPC64  #define REG		"%.16lx" -#define REGS_PER_LINE	4 -#define LAST_VOLATILE	13  #else  #define REG		"%.8lx" -#define REGS_PER_LINE	8 -#define LAST_VOLATILE	12  #endif +#ifdef __LITTLE_ENDIAN__ +#define GETWORD(v)	(((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0]) +#else  #define GETWORD(v)	(((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3]) +#endif  #define isxdigit(c)	(('0' <= (c) && (c) <= '9') \  			 || ('a' <= (c) && (c) <= 'f') \ @@ -201,7 +202,13 @@ Commands:\n\    di	dump instructions\n\    df	dump float values\n\    dd	dump double values\n\ -  dl    dump the kernel log buffer\n\ +  dl    dump the kernel log buffer\n" +#ifdef CONFIG_PPC64 +  "\ +  dp[#]	dump paca for current cpu, or cpu #\n\ +  dpa	dump paca for all possible cpus\n" +#endif +  "\    dr	dump stream of raw bytes\n\    e	print exception information\n\    f	flush cache\n\ @@ -228,13 +235,11 @@ Commands:\n\    t	print backtrace\n\    x	exit monitor and recover\n\    X	exit monitor and dont recover\n" -#ifdef CONFIG_PPC64 +#if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)  "  u	dump segment table or SLB\n" -#endif -#ifdef CONFIG_PPC_STD_MMU_32 +#elif defined(CONFIG_PPC_STD_MMU_32)  "  u	dump segment registers\n" -#endif -#ifdef CONFIG_44x +#elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)  "  u	dump TLB\n"  #endif  "  ?	help\n" @@ -308,16 +313,23 @@ static void get_output_lock(void)  	if (xmon_speaker == me)  		return; +  	for (;;) { -		if (xmon_speaker == 0) { -			last_speaker = cmpxchg(&xmon_speaker, 0, me); -			if (last_speaker == 0) -				return; -		} -		timeout = 10000000; +		last_speaker = cmpxchg(&xmon_speaker, 0, me); +		if (last_speaker == 0) +			return; + +		/* +		 * Wait a full second for the lock, we might be on a slow +		 * console, but check every 100us. +		 */ +		timeout = 10000;  		while (xmon_speaker == last_speaker) { -			if (--timeout > 0) +			if (--timeout > 0) { +				udelay(100);  				continue; +			} +  			/* hostile takeover */  			prev = cmpxchg(&xmon_speaker, last_speaker, me);  			if (prev == last_speaker) @@ -334,14 +346,14 @@ static void release_output_lock(void)  int cpus_are_in_xmon(void)  { -	return !cpus_empty(cpus_in_xmon); +	return !cpumask_empty(&cpus_in_xmon);  }  #endif  static inline int unrecoverable_excp(struct pt_regs *regs)  { -#ifdef CONFIG_4xx -	/* We have no MSR_RI bit on 4xx, so we simply return false */ +#if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E) +	/* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */  	return 0;  #else  	return ((regs->msr & MSR_RI) == 0); @@ -373,7 +385,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)  #ifdef CONFIG_SMP  	cpu = smp_processor_id(); -	if (cpu_isset(cpu, cpus_in_xmon)) { +	if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {  		get_output_lock();  		excprint(regs);  		printf("cpu 0x%x: Exception %lx %s in xmon, " @@ -396,10 +408,9 @@ static int xmon_core(struct pt_regs *regs, int fromipi)  	}  	xmon_fault_jmp[cpu] = recurse_jmp; -	cpu_set(cpu, cpus_in_xmon);  	bp = NULL; -	if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) +	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))  		bp = at_breakpoint(regs->nip);  	if (bp || unrecoverable_excp(regs))  		fromipi = 0; @@ -408,7 +419,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)  		get_output_lock();  		excprint(regs);  		if (bp) { -			printf("cpu 0x%x stopped at breakpoint 0x%x (", +			printf("cpu 0x%x stopped at breakpoint 0x%lx (",  			       cpu, BP_NUM(bp));  			xmon_print_symbol(regs->nip, " ", ")\n");  		} @@ -418,6 +429,8 @@ static int xmon_core(struct pt_regs *regs, int fromipi)  		release_output_lock();  	} +	cpumask_set_cpu(cpu, &cpus_in_xmon); +   waiting:  	secondary = 1;  	while (secondary && !xmon_gate) { @@ -437,10 +450,10 @@ static int xmon_core(struct pt_regs *regs, int fromipi)  		xmon_owner = cpu;  		mb();  		if (ncpus > 1) { -			smp_send_debugger_break(MSG_ALL_BUT_SELF); +			smp_send_debugger_break();  			/* wait for other cpus to come in */  			for (timeout = 100000000; timeout != 0; --timeout) { -				if (cpus_weight(cpus_in_xmon) >= ncpus) +				if (cpumask_weight(&cpus_in_xmon) >= ncpus)  					break;  				barrier();  			} @@ -484,7 +497,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)  		}  	}   leave: -	cpu_clear(cpu, cpus_in_xmon); +	cpumask_clear_cpu(cpu, &cpus_in_xmon);  	xmon_fault_jmp[cpu] = NULL;  #else  	/* UP is simple... */ @@ -500,7 +513,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)  		excprint(regs);  		bp = at_breakpoint(regs->nip);  		if (bp) { -			printf("Stopped at breakpoint %x (", BP_NUM(bp)); +			printf("Stopped at breakpoint %lx (", BP_NUM(bp));  			xmon_print_symbol(regs->nip, " ", ")\n");  		}  		if (unrecoverable_excp(regs)) @@ -529,7 +542,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)  		}  	}  #else -	if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) { +	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {  		bp = at_breakpoint(regs->nip);  		if (bp != NULL) {  			int stepped = emulate_step(regs, bp->instr[0]); @@ -578,7 +591,7 @@ static int xmon_bpt(struct pt_regs *regs)  	struct bpt *bp;  	unsigned long offset; -	if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) +	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))  		return 0;  	/* Are we at the trap at bp->instr[1] for some bp? */ @@ -607,9 +620,9 @@ static int xmon_sstep(struct pt_regs *regs)  	return 1;  } -static int xmon_dabr_match(struct pt_regs *regs) +static int xmon_break_match(struct pt_regs *regs)  { -	if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) +	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))  		return 0;  	if (dabr.enabled == 0)  		return 0; @@ -619,7 +632,7 @@ static int xmon_dabr_match(struct pt_regs *regs)  static int xmon_iabr_match(struct pt_regs *regs)  { -	if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) +	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))  		return 0;  	if (iabr == NULL)  		return 0; @@ -630,7 +643,7 @@ static int xmon_iabr_match(struct pt_regs *regs)  static int xmon_ipi(struct pt_regs *regs)  {  #ifdef CONFIG_SMP -	if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon)) +	if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))  		xmon_core(regs, 1);  #endif  	return 0; @@ -644,7 +657,7 @@ static int xmon_fault_handler(struct pt_regs *regs)  	if (in_xmon && catch_memory_errors)  		handle_fault(regs);	/* doesn't return */ -	if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) { +	if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {  		bp = in_breakpoint_table(regs->nip, &offset);  		if (bp != NULL) {  			regs->nip = bp->address + offset; @@ -740,8 +753,14 @@ static void insert_bpts(void)  static void insert_cpu_bpts(void)  { -	if (dabr.enabled) -		set_dabr(dabr.address | (dabr.enabled & 7)); +	struct arch_hw_breakpoint brk; + +	if (dabr.enabled) { +		brk.address = dabr.address; +		brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL; +		brk.len = 8; +		__set_breakpoint(&brk); +	}  	if (iabr && cpu_has_feature(CPU_FTR_IABR))  		mtspr(SPRN_IABR, iabr->address  			 | (iabr->enabled & (BP_IABR|BP_IABR_TE))); @@ -769,7 +788,7 @@ static void remove_bpts(void)  static void remove_cpu_bpts(void)  { -	set_dabr(0); +	hw_breakpoint_disable();  	if (cpu_has_feature(CPU_FTR_IABR))  		mtspr(SPRN_IABR, 0);  } @@ -821,7 +840,7 @@ cmds(struct pt_regs *excp)  				memzcan();  				break;  			case 'i': -				show_mem(); +				show_mem(0);  				break;  			default:  				termch = cmd; @@ -885,26 +904,24 @@ cmds(struct pt_regs *excp)  		case 'u':  			dump_segments();  			break; -#endif -#ifdef CONFIG_4xx +#elif defined(CONFIG_4xx)  		case 'u':  			dump_tlb_44x();  			break; -#endif -#ifdef CONFIG_PPC_BOOK3E +#elif defined(CONFIG_PPC_BOOK3E)  		case 'u':  			dump_tlb_book3e();  			break;  #endif  		default:  			printf("Unrecognized command: "); -		        do { +			do {  				if (' ' < cmd && cmd <= '~')  					putchar(cmd);  				else  					printf("\\x%x", cmd);  				cmd = inchar(); -		        } while (cmd != '\n');  +			} while (cmd != '\n');  			printf(" (type ? for help)\n");  			break;  		} @@ -929,7 +946,7 @@ static int do_step(struct pt_regs *regs)  	int stepped;  	/* check we are in 64-bit kernel mode, translation enabled */ -	if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) { +	if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {  		if (mread(regs->nip, &instr, 4) == 4) {  			stepped = emulate_step(regs, instr);  			if (stepped < 0) { @@ -967,32 +984,32 @@ static void bootcmds(void)  static int cpu_cmd(void)  {  #ifdef CONFIG_SMP -	unsigned long cpu; +	unsigned long cpu, first_cpu, last_cpu;  	int timeout; -	int count;  	if (!scanhex(&cpu)) {  		/* print cpus waiting or in xmon */  		printf("cpus stopped:"); -		count = 0; -		for (cpu = 0; cpu < NR_CPUS; ++cpu) { -			if (cpu_isset(cpu, cpus_in_xmon)) { -				if (count == 0) -					printf(" %x", cpu); -				++count; -			} else { -				if (count > 1) -					printf("-%x", cpu - 1); -				count = 0; +		last_cpu = first_cpu = NR_CPUS; +		for_each_possible_cpu(cpu) { +			if (cpumask_test_cpu(cpu, &cpus_in_xmon)) { +				if (cpu == last_cpu + 1) { +					last_cpu = cpu; +				} else { +					if (last_cpu != first_cpu) +						printf("-0x%lx", last_cpu); +					last_cpu = first_cpu = cpu; +					printf(" 0x%lx", cpu); +				}  			}  		} -		if (count > 1) -			printf("-%x", NR_CPUS - 1); +		if (last_cpu != first_cpu) +			printf("-0x%lx", last_cpu);  		printf("\n");  		return 0;  	}  	/* try to switch to cpu specified */ -	if (!cpu_isset(cpu, cpus_in_xmon)) { +	if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {  		printf("cpu 0x%x isn't in xmon\n", cpu);  		return 0;  	} @@ -1007,7 +1024,7 @@ static int cpu_cmd(void)  			/* take control back */  			mb();  			xmon_owner = smp_processor_id(); -			printf("cpu %u didn't take control\n", cpu); +			printf("cpu 0x%x didn't take control\n", cpu);  			return 0;  		}  		barrier(); @@ -1069,7 +1086,7 @@ csum(void)  	fcs = 0xffff;  	for (i = 0; i < ncsum; ++i) {  		if (mread(adrs+i, &v, 1) == 0) { -			printf("csum stopped at %x\n", adrs+i); +			printf("csum stopped at "REG"\n", adrs+i);  			break;  		}  		fcs = FCS(fcs, v); @@ -1101,7 +1118,7 @@ static long check_bp_loc(unsigned long addr)  	return 1;  } -static char *breakpoint_help_string =  +static char *breakpoint_help_string =      "Breakpoint command usage:\n"      "b                show breakpoints\n"      "b <addr> [cnt]   set breakpoint at given instr addr\n" @@ -1140,7 +1157,7 @@ bpt_cmds(void)  				printf(badaddr);  				break;  			} -			dabr.address &= ~7; +			dabr.address &= ~HW_BRK_TYPE_DABR;  			dabr.enabled = mode | BP_DABR;  		}  		break; @@ -1185,19 +1202,19 @@ bpt_cmds(void)  			/* assume a breakpoint address */  			bp = at_breakpoint(a);  			if (bp == NULL) { -				printf("No breakpoint at %x\n", a); +				printf("No breakpoint at %lx\n", a);  				break;  			}  		} -		printf("Cleared breakpoint %x (", BP_NUM(bp)); +		printf("Cleared breakpoint %lx (", BP_NUM(bp));  		xmon_print_symbol(bp->address, " ", ")\n");  		bp->enabled = 0;  		break;  	default:  		termch = cmd; -	        cmd = skipbl(); +		cmd = skipbl();  		if (cmd == '?') {  			printf(breakpoint_help_string);  			break; @@ -1251,11 +1268,18 @@ const char *getvecname(unsigned long vec)  	case 0x700:	ret = "(Program Check)"; break;  	case 0x800:	ret = "(FPU Unavailable)"; break;  	case 0x900:	ret = "(Decrementer)"; break; +	case 0x980:	ret = "(Hypervisor Decrementer)"; break; +	case 0xa00:	ret = "(Doorbell)"; break;  	case 0xc00:	ret = "(System Call)"; break;  	case 0xd00:	ret = "(Single Step)"; break; +	case 0xe40:	ret = "(Emulation Assist)"; break; +	case 0xe60:	ret = "(HMI)"; break; +	case 0xe80:	ret = "(Hypervisor Doorbell)"; break;  	case 0xf00:	ret = "(Performance Monitor)"; break;  	case 0xf20:	ret = "(Altivec Unavailable)"; break;  	case 0x1300:	ret = "(Instruction Breakpoint)"; break; +	case 0x1500:	ret = "(Denormalisation)"; break; +	case 0x1700:	ret = "(Altivec Assist)"; break;  	default: ret = "";  	}  	return ret; @@ -1283,27 +1307,19 @@ static void get_function_bounds(unsigned long pc, unsigned long *startp,  	catch_memory_errors = 0;  } -static int xmon_depth_to_print = 64; -  #define LRSAVE_OFFSET		(STACK_FRAME_LR_SAVE * sizeof(unsigned long))  #define MARKER_OFFSET		(STACK_FRAME_MARKER * sizeof(unsigned long)) -#ifdef __powerpc64__ -#define REGS_OFFSET		0x70 -#else -#define REGS_OFFSET		16 -#endif -  static void xmon_show_stack(unsigned long sp, unsigned long lr,  			    unsigned long pc)  { +	int max_to_print = 64;  	unsigned long ip;  	unsigned long newsp;  	unsigned long marker; -	int count = 0;  	struct pt_regs regs; -	do { +	while (max_to_print--) {  		if (sp < PAGE_OFFSET) {  			if (sp != 0)  				printf("SP (%lx) is in userspace\n", sp); @@ -1357,13 +1373,13 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,  		   an exception frame. */  		if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))  		    && marker == STACK_FRAME_REGS_MARKER) { -			if (mread(sp + REGS_OFFSET, ®s, sizeof(regs)) +			if (mread(sp + STACK_FRAME_OVERHEAD, ®s, sizeof(regs))  			    != sizeof(regs)) {  				printf("Couldn't read registers at %lx\n", -				       sp + REGS_OFFSET); +				       sp + STACK_FRAME_OVERHEAD);  				break;  			} -                        printf("--- Exception: %lx %s at ", regs.trap, +			printf("--- Exception: %lx %s at ", regs.trap,  			       getvecname(TRAP(®s)));  			pc = regs.nip;  			lr = regs.link; @@ -1374,7 +1390,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,  			break;  		sp = newsp; -	} while (count++ < xmon_depth_to_print); +	}  }  static void backtrace(struct pt_regs *excp) @@ -1433,7 +1449,7 @@ static void excprint(struct pt_regs *fp)  	printf("    sp: %lx\n", fp->gpr[1]);  	printf("   msr: %lx\n", fp->msr); -	if (trap == 0x300 || trap == 0x380 || trap == 0x600) { +	if (trap == 0x300 || trap == 0x380 || trap == 0x600 || trap == 0x200) {  		printf("   dar: %lx\n", fp->dar);  		if (trap != 0x380)  			printf(" dsisr: %lx\n", fp->dsisr); @@ -1441,7 +1457,8 @@ static void excprint(struct pt_regs *fp)  	printf("  current = 0x%lx\n", current);  #ifdef CONFIG_PPC64 -	printf("  paca    = 0x%lx\n", get_paca()); +	printf("  paca    = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n", +	       local_paca, local_paca->soft_enabled, local_paca->irq_happened);  #endif  	if (current) {  		printf("    pid   = %ld, comm = %s\n", @@ -1497,6 +1514,10 @@ static void prregs(struct pt_regs *fp)  #endif  	printf("pc  = ");  	xmon_print_symbol(fp->nip, " ", "\n"); +	if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) { +		printf("cfar= "); +		xmon_print_symbol(fp->orig_gpr3, " ", "\n"); +	}  	printf("lr  = ");  	xmon_print_symbol(fp->link, " ", "\n");  	printf("msr = "REG"   cr  = %.8lx\n", fp->msr, fp->ccr); @@ -1622,37 +1643,18 @@ static void super_regs(void)  	cmd = skipbl();  	if (cmd == '\n') { -	        unsigned long sp, toc; +		unsigned long sp, toc;  		asm("mr %0,1" : "=r" (sp) :);  		asm("mr %0,2" : "=r" (toc) :);  		printf("msr  = "REG"  sprg0= "REG"\n",  		       mfmsr(), mfspr(SPRN_SPRG0));  		printf("pvr  = "REG"  sprg1= "REG"\n", -		       mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));  +		       mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));  		printf("dec  = "REG"  sprg2= "REG"\n",  		       mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));  		printf("sp   = "REG"  sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));  		printf("toc  = "REG"  dar  = "REG"\n", toc, mfspr(SPRN_DAR)); -#ifdef CONFIG_PPC_ISERIES -		if (firmware_has_feature(FW_FEATURE_ISERIES)) { -			struct paca_struct *ptrPaca; -			struct lppaca *ptrLpPaca; - -			/* Dump out relevant Paca data areas. */ -			printf("Paca: \n"); -			ptrPaca = get_paca(); - -			printf("  Local Processor Control Area (LpPaca): \n"); -			ptrLpPaca = ptrPaca->lppaca_ptr; -			printf("    Saved Srr0=%.16lx  Saved Srr1=%.16lx \n", -			       ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); -			printf("    Saved Gpr3=%.16lx  Saved Gpr4=%.16lx \n", -			       ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); -			printf("    Saved Gpr5=%.16lx \n", -				ptrLpPaca->gpr5_dword.saved_gpr5); -		} -#endif  		return;  	} @@ -1744,7 +1746,7 @@ mwrite(unsigned long adrs, void *buf, int size)  		__delay(200);  		n = size;  	} else { -		printf("*** Error writing address %x\n", adrs + n); +		printf("*** Error writing address "REG"\n", adrs + n);  	}  	catch_memory_errors = 0;  	return n; @@ -1801,7 +1803,7 @@ byterev(unsigned char *val, int size)  static int brev;  static int mnoread; -static char *memex_help_string =  +static char *memex_help_string =      "Memory examine command usage:\n"      "m [addr] [flags] examine/change memory\n"      "  addr is optional.  will start where left off.\n" @@ -1816,7 +1818,7 @@ static char *memex_help_string =      "NOTE: flags are saved as defaults\n"      ""; -static char *memex_subcmd_help_string =  +static char *memex_subcmd_help_string =      "Memory examine subcommands:\n"      "  hexval   write this val to current location\n"      "  'string' write chars from string to this location\n" @@ -2026,6 +2028,99 @@ static void xmon_rawdump (unsigned long adrs, long ndump)  	printf("\n");  } +#ifdef CONFIG_PPC64 +static void dump_one_paca(int cpu) +{ +	struct paca_struct *p; + +	if (setjmp(bus_error_jmp) != 0) { +		printf("*** Error dumping paca for cpu 0x%x!\n", cpu); +		return; +	} + +	catch_memory_errors = 1; +	sync(); + +	p = &paca[cpu]; + +	printf("paca for cpu 0x%x @ %p:\n", cpu, p); + +	printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu) ? "yes" : "no"); +	printf(" %-*s = %s\n", 16, "present", cpu_present(cpu) ? "yes" : "no"); +	printf(" %-*s = %s\n", 16, "online", cpu_online(cpu) ? "yes" : "no"); + +#define DUMP(paca, name, format) \ +	printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \ +		offsetof(struct paca_struct, name)); + +	DUMP(p, lock_token, "x"); +	DUMP(p, paca_index, "x"); +	DUMP(p, kernel_toc, "lx"); +	DUMP(p, kernelbase, "lx"); +	DUMP(p, kernel_msr, "lx"); +#ifdef CONFIG_PPC_STD_MMU_64 +	DUMP(p, stab_real, "lx"); +	DUMP(p, stab_addr, "lx"); +#endif +	DUMP(p, emergency_sp, "p"); +#ifdef CONFIG_PPC_BOOK3S_64 +	DUMP(p, mc_emergency_sp, "p"); +	DUMP(p, in_mce, "x"); +#endif +	DUMP(p, data_offset, "lx"); +	DUMP(p, hw_cpu_id, "x"); +	DUMP(p, cpu_start, "x"); +	DUMP(p, kexec_state, "x"); +	DUMP(p, __current, "p"); +	DUMP(p, kstack, "lx"); +	DUMP(p, stab_rr, "lx"); +	DUMP(p, saved_r1, "lx"); +	DUMP(p, trap_save, "x"); +	DUMP(p, soft_enabled, "x"); +	DUMP(p, irq_happened, "x"); +	DUMP(p, io_sync, "x"); +	DUMP(p, irq_work_pending, "x"); +	DUMP(p, nap_state_lost, "x"); + +#undef DUMP + +	catch_memory_errors = 0; +	sync(); +} + +static void dump_all_pacas(void) +{ +	int cpu; + +	if (num_possible_cpus() == 0) { +		printf("No possible cpus, use 'dp #' to dump individual cpus\n"); +		return; +	} + +	for_each_possible_cpu(cpu) +		dump_one_paca(cpu); +} + +static void dump_pacas(void) +{ +	unsigned long num; +	int c; + +	c = inchar(); +	if (c == 'a') { +		dump_all_pacas(); +		return; +	} + +	termch = c;	/* Put c back, it wasn't 'a' */ + +	if (scanhex(&num)) +		dump_one_paca(num); +	else +		dump_one_paca(xmon_owner); +} +#endif +  #define isxdigit(c)	(('0' <= (c) && (c) <= '9') \  			 || ('a' <= (c) && (c) <= 'f') \  			 || ('A' <= (c) && (c) <= 'F')) @@ -2035,6 +2130,14 @@ dump(void)  	int c;  	c = inchar(); + +#ifdef CONFIG_PPC64 +	if (c == 'p') { +		dump_pacas(); +		return; +	} +#endif +  	if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')  		termch = c;  	scanhex((void *)&adrs); @@ -2082,7 +2185,7 @@ prdump(unsigned long adrs, long ndump)  		nr = mread(adrs, temp, r);  		adrs += nr;  		for (m = 0; m < r; ++m) { -		        if ((m & (sizeof(long) - 1)) == 0 && m > 0) +			if ((m & (sizeof(long) - 1)) == 0 && m > 0)  				putchar(' ');  			if (m < nr)  				printf("%.2x", temp[m]); @@ -2090,7 +2193,7 @@ prdump(unsigned long adrs, long ndump)  				printf("%s", fault_chars[fault_type]);  		}  		for (; m < 16; ++m) { -		        if ((m & (sizeof(long) - 1)) == 0) +			if ((m & (sizeof(long) - 1)) == 0)  				putchar(' ');  			printf("  ");  		} @@ -2166,45 +2269,28 @@ print_address(unsigned long addr)  void  dump_log_buf(void)  { -        const unsigned long size = 128; -        unsigned long end, addr; -        unsigned char buf[size + 1]; +	struct kmsg_dumper dumper = { .active = 1 }; +	unsigned char buf[128]; +	size_t len; -        addr = 0; -        buf[size] = '\0'; - -        if (setjmp(bus_error_jmp) != 0) { -                printf("Unable to lookup symbol __log_buf!\n"); -                return; -        } - -        catch_memory_errors = 1; -        sync(); -        addr = kallsyms_lookup_name("__log_buf"); - -        if (! addr) -                printf("Symbol __log_buf not found!\n"); -        else { -                end = addr + (1 << CONFIG_LOG_BUF_SHIFT); -                while (addr < end) { -                        if (! mread(addr, buf, size)) { -                                printf("Can't read memory at address 0x%lx\n", addr); -                                break; -                        } - -                        printf("%s", buf); +	if (setjmp(bus_error_jmp) != 0) { +		printf("Error dumping printk buffer!\n"); +		return; +	} -                        if (strlen(buf) < size) -                                break; +	catch_memory_errors = 1; +	sync(); -                        addr += size; -                } -        } +	kmsg_dump_rewind_nolock(&dumper); +	while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) { +		buf[len] = '\0'; +		printf("%s", buf); +	} -        sync(); -        /* wait a little while to see if we get a machine check */ -        __delay(200); -        catch_memory_errors = 0; +	sync(); +	/* wait a little while to see if we get a machine check */ +	__delay(200); +	catch_memory_errors = 0;  }  /* @@ -2349,7 +2435,7 @@ static void proccall(void)  		ret = func(args[0], args[1], args[2], args[3],  			   args[4], args[5], args[6], args[7]);  		sync(); -		printf("return value is %x\n", ret); +		printf("return value is 0x%lx\n", ret);  	} else {  		printf("*** %x exception occurred\n", fault_except);  	} @@ -2614,7 +2700,7 @@ static void dump_slb(void)  	unsigned long esid,vsid,valid;  	unsigned long llp; -	printf("SLB contents of cpu %x\n", smp_processor_id()); +	printf("SLB contents of cpu 0x%x\n", smp_processor_id());  	for (i = 0; i < mmu_slb_size; i++) {  		asm volatile("slbmfee  %0,%1" : "=r" (esid) : "r" (i)); @@ -2644,9 +2730,9 @@ static void dump_slb(void)  static void dump_stab(void)  {  	int i; -	unsigned long *tmp = (unsigned long *)get_paca()->stab_addr; +	unsigned long *tmp = (unsigned long *)local_paca->stab_addr; -	printf("Segment table contents of cpu %x\n", smp_processor_id()); +	printf("Segment table contents of cpu 0x%x\n", smp_processor_id());  	for (i = 0; i < PAGE_SIZE/16; i++) {  		unsigned long a, b; @@ -2663,7 +2749,7 @@ static void dump_stab(void)  void dump_segments(void)  { -	if (cpu_has_feature(CPU_FTR_SLB)) +	if (mmu_has_feature(MMU_FTR_SLB))  		dump_slb();  	else  		dump_stab(); @@ -2855,17 +2941,13 @@ static void dump_tlb_book3e(void)  static void xmon_init(int enable)  { -#ifdef CONFIG_PPC_ISERIES -	if (firmware_has_feature(FW_FEATURE_ISERIES)) -		return; -#endif  	if (enable) {  		__debugger = xmon;  		__debugger_ipi = xmon_ipi;  		__debugger_bpt = xmon_bpt;  		__debugger_sstep = xmon_sstep;  		__debugger_iabr_match = xmon_iabr_match; -		__debugger_dabr_match = xmon_dabr_match; +		__debugger_break_match = xmon_break_match;  		__debugger_fault_handler = xmon_fault_handler;  	} else {  		__debugger = NULL; @@ -2873,10 +2955,9 @@ static void xmon_init(int enable)  		__debugger_bpt = NULL;  		__debugger_sstep = NULL;  		__debugger_iabr_match = NULL; -		__debugger_dabr_match = NULL; +		__debugger_break_match = NULL;  		__debugger_fault_handler = NULL;  	} -	xmon_map_scc();  }  #ifdef CONFIG_MAGIC_SYSRQ @@ -2889,16 +2970,12 @@ static void sysrq_handle_xmon(int key)  static struct sysrq_key_op sysrq_xmon_op = {  	.handler =	sysrq_handle_xmon, -	.help_msg =	"Xmon", +	.help_msg =	"xmon(x)",  	.action_msg =	"Entering xmon",  };  static int __init setup_xmon_sysrq(void)  { -#ifdef CONFIG_PPC_ISERIES -	if (firmware_has_feature(FW_FEATURE_ISERIES)) -		return 0; -#endif  	register_sysrq_key('x', &sysrq_xmon_op);  	return 0;  }  | 
