[ppc64] xmon breakpoint and single step on LPAR fixes from John Rose Xmon changes to make breakpoints and single-stepping work on pSeries LPARs. Also changed help text to reflect obsolete cmds. --- arch/ppc64/xmon/xmon.c | 38 +++++++++++++++++++++++++++----------- 1 files changed, 27 insertions(+), 11 deletions(-) diff -puN arch/ppc64/xmon/xmon.c~ppc64-xmon_fixes arch/ppc64/xmon/xmon.c --- 25/arch/ppc64/xmon/xmon.c~ppc64-xmon_fixes 2004-01-13 23:23:16.000000000 -0800 +++ 25-akpm/arch/ppc64/xmon/xmon.c 2004-01-13 23:23:16.000000000 -0800 @@ -37,9 +37,10 @@ #define skipbl xmon_skipbl #ifdef CONFIG_SMP -unsigned long cpus_in_xmon = 0; +volatile unsigned long cpus_in_xmon = 0; static unsigned long got_xmon = 0; static volatile int take_xmon = -1; +static volatile int leaving_xmon = 0; #endif /* CONFIG_SMP */ static unsigned long adrs; @@ -162,7 +163,6 @@ Commands:\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\ @@ -227,7 +227,7 @@ void xmon(struct pt_regs *excp) { struct pt_regs regs; - int cmd; + int cmd = 0; unsigned long msr; if (excp == NULL) { @@ -285,9 +285,15 @@ xmon(struct pt_regs *excp) xmon_regs[smp_processor_id()] = excp; excprint(excp); #ifdef CONFIG_SMP - if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon)) + leaving_xmon = 0; + /* possible race condition here if a CPU is held up and gets + * here while we are exiting */ + if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon)) { + /* xmon probably caused an exception itself */ + printf("We are already in xmon\n"); for (;;) ; + } while (test_and_set_bit(0, &got_xmon)) { if (take_xmon == smp_processor_id()) { take_xmon = -1; @@ -304,6 +310,9 @@ xmon(struct pt_regs *excp) if (cmd == 's') { xmon_trace[smp_processor_id()] = SSTEP; excp->msr |= MSR_SE; +#ifdef CONFIG_SMP + take_xmon = smp_processor_id(); +#endif } else if (at_breakpoint(excp->nip)) { xmon_trace[smp_processor_id()] = BRSTEP; excp->msr |= MSR_SE; @@ -313,7 +322,9 @@ xmon(struct pt_regs *excp) } xmon_regs[smp_processor_id()] = 0; #ifdef CONFIG_SMP - clear_bit(0, &got_xmon); + leaving_xmon = 1; + if (cmd != 's') + clear_bit(0, &got_xmon); clear_bit(smp_processor_id(), &cpus_in_xmon); #endif /* CONFIG_SMP */ set_msrd(msr); /* restore interrupt enable */ @@ -421,8 +432,6 @@ insert_bpts() int i; struct bpt *bp; - if (systemcfg->platform != PLATFORM_PSERIES) - return; bp = bpts; for (i = 0; i < NBPTS; ++i, ++bp) { if (!bp->enabled) @@ -450,9 +459,6 @@ remove_bpts() struct bpt *bp; unsigned instr; - if (systemcfg->platform != PLATFORM_PSERIES) - return; - if ((cur_cpu_spec->cpu_features & CPU_FTR_DABR)) set_dabr(0); if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR)) @@ -478,11 +484,15 @@ static char *last_cmd; static int cmds(struct pt_regs *excp) { - int cmd; + int cmd = 0; last_cmd = NULL; for(;;) { #ifdef CONFIG_SMP + /* Need to check if we should take any commands on + this CPU. */ + if (leaving_xmon) + return cmd; printf("%d:", smp_processor_id()); #endif /* CONFIG_SMP */ printf("mon> "); @@ -832,6 +842,12 @@ bpt_cmds(void) } break; } + + if (!(systemcfg->platform & PLATFORM_PSERIES)) { + printf("Not supported for this platform\n"); + break; + } + bp = at_breakpoint(a); if (bp == 0) { for (bp = bpts; bp < &bpts[NBPTS]; ++bp) _