On 06/04/2014 02:18 PM, Anshuman Khandual wrote: > On 06/03/2014 11:33 AM, Anshuman Khandual wrote: >> On 05/30/2014 07:12 PM, Aneesh Kumar K.V wrote: >>>> Anshuman Khandual <khand...@linux.vnet.ibm.com> writes: >>>> >>>>>> This patch enables support for hardware instruction breakpoints on >>>>>> POWER8 with >>>>>> the help of a new register called CIABR (Completed Instruction Address >>>>>> Breakpoint >>>>>> Register). With this patch, single hardware instruction breakpoint can >>>>>> be added >>>>>> and cleared during any active xmon debug session. This hardware based >>>>>> instruction >>>>>> breakpoint mechanism works correctly along with the existing TRAP based >>>>>> instruction >>>>>> breakpoints available on xmon. Example usage as follows. >>>>>> >>>>>> (A) Start xmon: >>>>>> $echo x > /proc/sysrq-trigger >>>>>> SysRq : Entering xmon >>>>>> cpu 0x0: Vector: 0 at [c000001f6c67f960] >>>>>> pc: c000000000072078: .sysrq_handle_xmon+0x58/0x60 >>>>>> lr: c000000000072078: .sysrq_handle_xmon+0x58/0x60 >>>>>> sp: c000001f6c67fac0 >>>>>> msr: 9000000000009032 >>>>>> current = 0xc000001f6e709ac0 >>>>>> paca = 0xc00000000fffa000 softe: 0 irq_happened: 0x00 >>>>>> pid = 3250, comm = bash >>>>>> enter ? for help >>>>>> 0:mon> b >>>>>> type address >>>>>> >>>>>> (B) Set the breakpoint: >>>>>> 0:mon> ls .power_pmu_add >>>>>> .power_pmu_add: c000000000078f50 >>>>>> 0:mon> bi c000000000078f50 >>>>>> 0:mon> b >>>>>> type address >>>>>> 1 inst c000000000078f50 .power_pmu_add+0x0/0x2e0 >>>>>> 0:mon> ls .perf_event_interrupt >>>>>> .perf_event_interrupt: c00000000007aee0 >>>>>> 0:mon> bi c00000000007aee0 >>>>>> One instruction breakpoint possible with CIABR >>>>>> 0:mon> x >>>>>> >>>>>> (C) Run the workload (with the breakpoint): >>>>>> $./perf record ls >>>>>> cpu 0x2: Vector: d00 (Single Step) at [c000001f718133a0] >>>>>> pc: c000000000078f54: .power_pmu_add+0x4/0x2e0 >>>>>> lr: c000000000155be0: .event_sched_in+0x90/0x1d0 >>>>>> sp: c000001f71813620 >>>>>> msr: 9000000040109032 >>>>>> current = 0xc000001f6ce30000 >>>>>> paca = 0xc00000000fffa600 softe: 0 irq_happened: 0x01 >>>>>> pid = 3270, comm = ls >>>>>> std r22,-80(r1) >>>>>> enter ? for help >>>>>> >>>>>> (D) Clear the breakpoint: >>>>>> 2:mon> bc >>>>>> All breakpoints cleared >>>>>> 2:mon> x >>>>>> [ perf record: Woken up 1 times to write data ] >>>>>> [ perf record: Captured and wrote 0.002 MB perf.data (~66 samples) ] >>>>>> >>>>>> (E) Run the workload again (without any breakpoints): >>>>>> $./perf record ls >>>>>> [ perf record: Woken up 1 times to write data ] >>>>>> [ perf record: Captured and wrote 0.001 MB perf.data (~61 samples) ] >>>>>> >>>>>> Signed-off-by: Anshuman Khandual <khand...@linux.vnet.ibm.com> >>>>>> --- >>>>>> arch/powerpc/xmon/xmon.c | 62 >>>>>> ++++++++++++++++++++++++++++++++++++++++++++---- >>>>>> 1 file changed, 58 insertions(+), 4 deletions(-) >>>>>> >>>>>> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c >>>>>> index 3fd1d9a..f74ec83 100644 >>>>>> --- a/arch/powerpc/xmon/xmon.c >>>>>> +++ b/arch/powerpc/xmon/xmon.c >>>>>> @@ -48,6 +48,7 @@ >>>>>> #ifdef CONFIG_PPC64 >>>>>> #include <asm/hvcall.h> >>>>>> #include <asm/paca.h> >>>>>> +#include <asm/plpar_wrappers.h> >>>>>> #endif >>>>>> >>>>>> #include "nonstdio.h" >>>>>> @@ -89,6 +90,7 @@ struct bpt { >>>>>> /* Bits in bpt.enabled */ >>>>>> #define BP_IABR_TE 1 /* IABR translation enabled */ >>>>>> #define BP_IABR 2 >>>>>> +#define BP_CIABR 4 >>>>>> #define BP_TRAP 8 >>>>>> #define BP_DABR 0x10 >>>>>> >>>>>> @@ -97,6 +99,7 @@ static struct bpt bpts[NBPTS]; >>>>>> static struct bpt dabr; >>>>>> static struct bpt *iabr; >>>>>> static unsigned bpinstr = 0x7fe00008; /* trap */ >>>>>> +static bool ciabr_used = false; /* CIABR instruction breakpoint >>>>>> */ >>>>>> >>>>>> #define BP_NUM(bp) ((bp) - bpts + 1) >>>>>> >>>>>> @@ -269,6 +272,34 @@ static inline void cinval(void *p) >>>>>> asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p)); >>>>>> } >>>>>> >>>>>> +static void write_ciabr(unsigned long ciabr) >>>>>> +{ >>>>>> + if (cpu_has_feature(CPU_FTR_HVMODE)) { >>>>>> + mtspr(SPRN_CIABR, ciabr); >>>>>> + return; >>>>>> + } >>>>>> + >>>>>> +#ifdef CONFIG_PPC64 >>>>>> + plapr_set_ciabr(ciabr); >>>>>> +#endif >>>>>> +} >>>>>> + >>>>>> +static void set_ciabr(unsigned long addr) >>>>>> +{ >>>>>> + addr &= ~CIABR_PRIV; >>>>>> + if (cpu_has_feature(CPU_FTR_HVMODE)) >>>>>> + addr |= CIABR_PRIV_HYPER; >>>>>> + else >>>>>> + addr |= CIABR_PRIV_SUPER; >>>>>> + write_ciabr(addr); >>>>>> +} >>>>>> + >>>>>> +static void clear_ciabr(void) >>>>>> +{ >>>>>> + if (cpu_has_feature(CPU_FTR_ARCH_207S)) >>>>>> + write_ciabr(0); >>>>>> +} >>>>>> + >>>>>> /* >>>>>> * Disable surveillance (the service processor watchdog function) >>>>>> * while we are in xmon. >>>>>> @@ -764,6 +795,9 @@ static void insert_cpu_bpts(void) >>>>>> if (iabr && cpu_has_feature(CPU_FTR_IABR)) >>>>>> mtspr(SPRN_IABR, iabr->address >>>>>> | (iabr->enabled & (BP_IABR|BP_IABR_TE))); >>>>>> + >>>>>> + if (iabr && cpu_has_feature(CPU_FTR_ARCH_207S)) >>>>>> + set_ciabr(iabr->address); >>>>>> } >>>>>> >>>>>> static void remove_bpts(void) >>>>>> @@ -791,6 +825,7 @@ static void remove_cpu_bpts(void) >>>>>> hw_breakpoint_disable(); >>>>>> if (cpu_has_feature(CPU_FTR_IABR)) >>>>>> mtspr(SPRN_IABR, 0); >>>>>> + clear_ciabr(); >>>>>> } >>>>>> >>>>>> /* Command interpreting routine */ >>>>>> @@ -1124,7 +1159,7 @@ static char *breakpoint_help_string = >>>>>> "b <addr> [cnt] set breakpoint at given instr addr\n" >>>>>> "bc clear all breakpoints\n" >>>>>> "bc <n/addr> clear breakpoint number n or at addr\n" >>>>>> - "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 >>>>>> only)\n" >>>>>> + "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64/POWER8 >>>>>> only)\n" >>>>>> "bd <addr> [cnt] set hardware data breakpoint\n" >>>>>> ""; >>>>>> >>>>>> @@ -1163,11 +1198,20 @@ bpt_cmds(void) >>>>>> break; >>>>>> >>>>>> case 'i': /* bi - hardware instr breakpoint */ >>>>>> - if (!cpu_has_feature(CPU_FTR_IABR)) { >>>>>> + if (!cpu_has_feature(CPU_FTR_IABR) && >>>>>> !cpu_has_feature(CPU_FTR_ARCH_207S)) { >>>>>> printf("Hardware instruction breakpoint " >>>>>> "not supported on this cpu\n"); >>>>>> break; >>>>>> } >>>>>> + >>>>>> + if (cpu_has_feature(CPU_FTR_ARCH_207S)) { >>>>>> + if (ciabr_used) { >>>>>> + printf("One instruction breakpoint " >>>>>> + "possible with CIABR\n"); >>>>>> + break; >>>>>> + } >>>> >>>> We don't seem to do that with iabr ? Why keep ciabr different > >> Right now with the IABR implementation if we try to set hardware instruction >> breakpoint while one is already there, it just get overridden with the new >> address without complaining. I thought with this at least for CIABR cases, >> it will complain about it and require the user to clear the breakpoint >> explicitly before allowing a new breakpoint. Okay will remove this. >> > > I tried removing the "ciabr_used" variable and all related checks/assignments > on it. > Then I was able to add all these three address as hardware instruction > breakpoint > and xmon never complained that it might override the existing actual > checkpoint > implemented with CIABR. It accepted all the three addresses which can later be > listed as below. > > 0:mon> b > type address > 1 inst c0000000000830d0 .power_pmu_add+0x0/0x2e0 > > 2 inst c000000000084690 .power_pmu_del+0x0/0x3a0 > > 3 inst c000000000085060 .perf_event_interrupt+0x0/0x480 > > But in reality, only perf_event_interrupt function's address got written into > CIABR > register and got triggered with the workload. I dont have a system which has > IABR > support to test it's behaviour for this situation. But this does not sound > okay, > we should explicitly inform the user that the hardware instruction breakpoint > has > been overridden with the latest command or reject the attempt. Looking for > some > suggestions in this regard. Thank you.
Hey Ben/MPE, Any suggestions on this ^^^^^^^^^^^^ ? _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev