1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Trace commands File: cfe_trace.c 5 * 6 * A minimal interface for running the SB-1250 trace buffer under CFE 7 * 8 ********************************************************************* 9 * 10 * Copyright 2000,2001,2002,2003 11 * Broadcom Corporation. All rights reserved. 12 * 13 * This software is furnished under license and may be used and 14 * copied only in accordance with the following terms and 15 * conditions. Subject to these conditions, you may download, 16 * copy, install, use, modify and distribute modified or unmodified 17 * copies of this software in source and/or binary form. No title 18 * or ownership is transferred hereby. 19 * 20 * 1) Any source code used, modified or distributed must reproduce 21 * and retain this copyright notice and list of conditions 22 * as they appear in the source file. 23 * 24 * 2) No right is granted to use any trade name, trademark, or 25 * logo of Broadcom Corporation. The "Broadcom Corporation" 26 * name may not be used to endorse or promote products derived 27 * from this software without the prior written permission of 28 * Broadcom Corporation. 29 * 30 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 31 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 32 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 33 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 34 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 35 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 36 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 38 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 39 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 40 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 41 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 42 * THE POSSIBILITY OF SUCH DAMAGE. 43 ********************************************************************* */ 44 45 46#include "cfe.h" 47#include "sbmips.h" 48#include "sb1250_regs.h" 49#include "sb1250_scd.h" 50 51#include "ui_command.h" 52 53int ui_init_tracecmds(void); 54static int ui_cmd_tracestart(ui_cmdline_t *cmd,int argc,char *argv[]); 55static int ui_cmd_tracestop(ui_cmdline_t *cmd,int argc,char *argv[]); 56static int ui_cmd_tracefreeze(ui_cmdline_t *cmd,int argc,char *argv[]); 57static int ui_cmd_traceread(ui_cmdline_t *cmd,int argc,char *argv[]); 58 59 60int ui_init_tracecmds(void) 61{ 62 63 cmd_addcmd("trace start", 64 ui_cmd_tracestart, 65 NULL, 66 "Start trace buffer data collection", 67 "trace start [n [agent]]\n\n" 68 "Start tracing ZBbus transactions, using the n-th canned\n" 69 "trigger/filter condition\n" 70 " n = 0: <agent>-mastered transactions\n" 71 " n = 1: CPU0 accesses to LDT dual-hosted region\n", 72 ""); 73 cmd_addcmd("trace stop", 74 ui_cmd_tracestop, 75 NULL, 76 "Stop trace buffer data collection", 77 "trace stop\n\n" 78 "Stop tracing ZBbus transactions", 79 ""); 80 cmd_addcmd("trace freeze", 81 ui_cmd_tracefreeze, 82 NULL, 83 "Freeze trace buffer", 84 "trace freeze\n\n" 85 "Freeze the trace buffer", 86 ""); 87 cmd_addcmd("trace read", 88 ui_cmd_traceread, 89 NULL, 90 "Read trace buffer into memory", 91 "trace read\n\n" 92 "Allocate a block of memory, copy the unprocessed contents\n" 93 "of the trace buffer into it, and generate a command template\n" 94 "for writing it to a file via TFTP.", 95 ""); 96 97 return 0; 98} 99 100#define TB_SIZE (256*48) /* 256 entries, 384 bits/entry */ 101#define ZB_AGENT_CPU0 0 102#define ZB_AGENT_CPU1 1 103#define ZB_AGENT_IOB0 2 104#define ZB_AGENT_IOB1 3 105#define ZB_AGENT_SCD 4 106#define ZB_AGENT_L2C 6 107#define ZB_AGENT_MC 7 108 109static const struct { 110 const char *id; 111 int code; 112} agent_id[] = { 113 { "cpu0", ZB_AGENT_CPU0 }, 114 { "cpu1", ZB_AGENT_CPU1 }, 115 { "iob0", ZB_AGENT_IOB0 }, 116 { "iob1", ZB_AGENT_IOB1 }, 117 { "scd", ZB_AGENT_SCD }, 118 { "l2c", ZB_AGENT_L2C }, 119 { "mc", ZB_AGENT_MC }, 120 { NULL, 0 } 121}; 122 123static int 124getagentarg (const char *id, int *agent) 125{ 126 int i; 127 128 for (i = 0; agent_id[i].id != NULL; i++) { 129 if (strcmp(id, agent_id[i].id) == 0) { 130 *agent = agent_id[i].code; 131 return 1; 132 } 133 } 134 return 0; 135} 136 137static int 138getaddrarg (const char *x, long *addr) 139{ 140 int res; 141 142 res = 0; 143 *addr = 0; 144 145 if (x) { 146 /* 147 * Following gdb, we make 64-bit addresses expressed as 148 * 8-digit numbers sign extend automagically. Saves 149 * typing, but is very gross. 150 */ 151 int longaddr; 152 153 longaddr = strlen(x); 154 if (memcmp(x,"0x",2) == 0) longaddr -= 2; 155 156 *addr = (longaddr > 8) ? (long) xtoq(x) : (long) xtoi(x); 157 res = 1; 158 } 159 160 return res; 161} 162 163 164static int ui_cmd_tracestart(ui_cmdline_t *cmd, int argc, char *argv[]) 165{ 166 volatile uint64_t *tb_cfg; 167 168 tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG); 169 170 if (argc != 0) { 171 volatile uint64_t *at_down_0, *at_up_0, *at_cfg_0; 172 volatile uint64_t *tb_evt_0, *tb_evt_4; 173 volatile uint64_t *tb_seq_0, *tb_seq_4; 174 int i, n; 175 int found; 176 int agent; 177 178 /* Place holder: parse new trace spec (select an option for now) */ 179 180 n = atoi(cmd_getarg(cmd,0)); 181 182 at_down_0 = (volatile uint64_t *) PHYS_TO_K1(A_ADDR_TRAP_DOWN_0); 183 at_up_0 = (volatile uint64_t *) PHYS_TO_K1(A_ADDR_TRAP_UP_0); 184 at_cfg_0 = (volatile uint64_t *) PHYS_TO_K1(A_ADDR_TRAP_CFG_0); 185 186 tb_evt_0 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_EVENT_0); 187 tb_evt_4 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_EVENT_4); 188 tb_seq_0 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_SEQUENCE_0); 189 tb_seq_4 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_SEQUENCE_4); 190 191 /* Reset everything */ 192 *tb_cfg = M_SCD_TRACE_CFG_RESET; 193 __asm__ __volatile__ ("sync" : : : "memory"); 194 195 for (i = 0; i < 4; i++) { 196 tb_evt_0[i] = 0; tb_evt_4[i] = 0; 197 tb_seq_0[i] = 0; tb_seq_4[i] = 0; 198 } 199 __asm__ __volatile__ ("sync" : : : "memory"); 200 201 switch (n) { 202 case 0: 203 /* Filter on agent request or response */ 204 if (argc > 1) 205 found = getagentarg(cmd_getarg(cmd,1), &agent); 206 else 207 found = 0; 208 if (!found) 209 agent = ZB_AGENT_IOB0; /* temporary, for backward compat */ 210 211 tb_evt_0[0] = M_SCD_TREVT_REQID_MATCH 212 | (M_SCD_TREVT_READ | M_SCD_TREVT_WRITE) 213 | V_SCD_TREVT_REQID(agent); 214 tb_evt_0[1] = M_SCD_TREVT_DATAID_MATCH 215 | V_SCD_TREVT_DATAID(agent); 216 217 tb_seq_0[0] = 0x0fff 218 | M_SCD_TRSEQ_ASAMPLE; 219 tb_seq_0[1] = 0x1fff 220 | M_SCD_TRSEQ_DSAMPLE; 221 break; 222 case 1: 223 /* Filter on CPU accesses in LDT mirror region. */ 224 (void)getaddrarg; 225 226 at_down_0[0] = 0xe000000000; 227 at_up_0[0] = 0xefffffffff; 228 at_cfg_0[0] = M_ATRAP_CFG_ALL; 229 230 tb_evt_0[0] = M_SCD_TREVT_REQID_MATCH 231 | V_SCD_TREVT_ADDR_MATCH(0x1) /* addr trap 0 */ 232 | (M_SCD_TREVT_READ | M_SCD_TREVT_WRITE) 233 | V_SCD_TREVT_REQID(ZB_AGENT_CPU0); 234 tb_evt_0[1] = M_SCD_TREVT_RESPID_MATCH 235 | V_SCD_TREVT_RESPID(ZB_AGENT_IOB0); 236 237 tb_seq_0[0] = 0x0fff 238 | M_SCD_TRSEQ_ASAMPLE; 239 tb_seq_0[1] = 0x1fff 240 | M_SCD_TRSEQ_DSAMPLE; 241 break; 242 default: 243 break; 244 } 245 246 __asm__ __volatile__ ("sync" : : : "memory"); 247printf("trace start: trace 0: %llx 1: %llx\n", tb_evt_0[0], tb_evt_0[1]); 248printf(" seq 0: %llx 1: %llx\n", tb_seq_0[0], tb_seq_0[1]); 249 } 250 251 *tb_cfg = M_SCD_TRACE_CFG_START; 252 __asm__ __volatile__ ("sync" : : : "memory"); 253 254printf("trace start: cfg %llx\n", *tb_cfg); 255 return 0; 256} 257 258static int ui_cmd_tracestop(ui_cmdline_t *cmd, int argc, char *argv[]) 259{ 260 volatile uint64_t *tb_cfg; 261 262 tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG); 263 *tb_cfg = M_SCD_TRACE_CFG_STOP; 264 __asm__ __volatile__ ("sync" : : : "memory"); 265 266printf("trace stop: cfg %llx\n", *tb_cfg); 267 return 0; 268} 269 270static int ui_cmd_tracefreeze(ui_cmdline_t *cmd, int argc, char *argv[]) 271{ 272 volatile uint64_t *tb_cfg; 273 274 tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG); 275 *tb_cfg = M_SCD_TRACE_CFG_FREEZE; 276 __asm__ __volatile__ ("sync" : : : "memory"); 277 278printf("trace freeze: cfg %llx\n", *tb_cfg); 279 return 0; 280} 281 282/* read out trace buffer to dump to a file */ 283 284static int ui_cmd_traceread(ui_cmdline_t *cmd, int argc, char *argv[]) 285{ 286 uint64_t *p; 287 volatile uint64_t *tb_cfg; 288 volatile uint64_t *tb_read; 289 int i; 290 291 p = KMALLOC(TB_SIZE, 0); 292 if (!p) { 293 printf("trace read: buffer allocation failed\n"); 294 return -1; 295 } 296 297 tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG); 298 tb_read = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_READ); 299 300 while ((*tb_cfg & M_SCD_TRACE_CFG_FREEZE) == 0) { 301 *tb_cfg = M_SCD_TRACE_CFG_FREEZE; 302 __asm__ __volatile__ ("sync" : : : "memory"); 303 } 304 305 *tb_cfg = M_SCD_TRACE_CFG_START_READ; 306 __asm__ __volatile__ ("sync" : : : "memory"); 307 308 /* Loop runs backward because bundles are read out in reverse order. */ 309 for (i = 256*6; i > 0; i -= 6) { 310 /* Subscripts decrease to put bundle in order. */ 311 p[i-1] = *tb_read; /* t2 hi */ 312 p[i-2] = *tb_read; /* t2 lo */ 313 p[i-3] = *tb_read; /* t1 hi */ 314 p[i-4] = *tb_read; /* t1 lo */ 315 p[i-5] = *tb_read; /* t0 hi */ 316 p[i-6] = *tb_read; /* t0 lo */ 317 } 318 319 printf("save hardy:ehs/sample.trace %p 0x%lx\n", p, TB_SIZE); 320 321 return 0; 322} 323