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

Reply via email to