From patchwork Fri May 30 12:10:23 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anshuman Khandual X-Patchwork-Id: 354108 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 86BBA1400E2 for ; Fri, 30 May 2014 22:14:13 +1000 (EST) Received: from ozlabs.org (ozlabs.org [103.22.144.67]) by lists.ozlabs.org (Postfix) with ESMTP id 77C601A0965 for ; Fri, 30 May 2014 22:14:13 +1000 (EST) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Received: from ozlabs.org (ozlabs.org [103.22.144.67]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 67C651A0701 for ; Fri, 30 May 2014 22:13:38 +1000 (EST) Received: by ozlabs.org (Postfix) id 4FEFE1400F5; Fri, 30 May 2014 22:13:38 +1000 (EST) Delivered-To: linuxppc-dev@ozlabs.org Received: from e28smtp02.in.ibm.com (e28smtp02.in.ibm.com [122.248.162.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id BC4251400E5 for ; Fri, 30 May 2014 22:13:37 +1000 (EST) Received: from /spool/local by e28smtp02.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 30 May 2014 17:43:32 +0530 Received: from d28dlp03.in.ibm.com (9.184.220.128) by e28smtp02.in.ibm.com (192.168.1.132) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 30 May 2014 17:43:30 +0530 Received: from d28relay03.in.ibm.com (d28relay03.in.ibm.com [9.184.220.60]) by d28dlp03.in.ibm.com (Postfix) with ESMTP id 45A7C1258048 for ; Fri, 30 May 2014 17:42:43 +0530 (IST) Received: from d28av04.in.ibm.com (d28av04.in.ibm.com [9.184.220.66]) by d28relay03.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s4UCE53c66519276 for ; Fri, 30 May 2014 17:44:06 +0530 Received: from d28av04.in.ibm.com (localhost [127.0.0.1]) by d28av04.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s4UCDRpt030082 for ; Fri, 30 May 2014 17:43:28 +0530 Received: from polynomials.in.ibm.com (polynomials.in.ibm.com [9.124.35.190]) by d28av04.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id s4UCDRn5030070; Fri, 30 May 2014 17:43:27 +0530 From: Anshuman Khandual To: linuxppc-dev@ozlabs.org Subject: [PATCH] powerpc, xmon: Enable hardware instruction breakpoint support on POWER8 Date: Fri, 30 May 2014 17:40:23 +0530 Message-Id: <1401451823-25547-1-git-send-email-khandual@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.11.7 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 14053012-5816-0000-0000-00000E55C6A5 Cc: mikey@neuling.org, Anshuman Khandual X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" 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 --- 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 #include +#include #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 [cnt] set breakpoint at given instr addr\n" "bc clear all breakpoints\n" "bc clear breakpoint number n or at addr\n" - "bi [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n" + "bi [cnt] set hardware instr breakpoint (POWER3/RS64/POWER8 only)\n" "bd [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; + } + } + if (iabr) { iabr->enabled &= ~(BP_IABR | BP_IABR_TE); iabr = NULL; @@ -1178,7 +1222,12 @@ bpt_cmds(void) break; bp = new_breakpoint(a); if (bp != NULL) { - bp->enabled |= BP_IABR | BP_IABR_TE; + if (cpu_has_feature(CPU_FTR_ARCH_207S)) { + bp->enabled |= BP_CIABR; + ciabr_used = true; + } + else + bp->enabled |= BP_IABR | BP_IABR_TE; iabr = bp; } break; @@ -1191,6 +1240,7 @@ bpt_cmds(void) bpts[i].enabled = 0; iabr = NULL; dabr.enabled = 0; + ciabr_used = false; printf("All breakpoints cleared\n"); break; } @@ -1207,6 +1257,9 @@ bpt_cmds(void) } } + if (bp->enabled & BP_CIABR) + ciabr_used = false; + printf("Cleared breakpoint %lx (", BP_NUM(bp)); xmon_print_symbol(bp->address, " ", ")\n"); bp->enabled = 0; @@ -1235,7 +1288,8 @@ bpt_cmds(void) if (!bp->enabled) continue; printf("%2x %s ", BP_NUM(bp), - (bp->enabled & BP_IABR)? "inst": "trap"); + (bp->enabled & (BP_IABR | BP_CIABR))? + "inst": "trap"); xmon_print_symbol(bp->address, " ", "\n"); } break;