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 "sbmips.h" 47#include "sb1250_regs.h" 48#include "sb1250_scd.h" 49 50#include "lib_types.h" 51#include "lib_string.h" 52#include "lib_malloc.h" 53#include "lib_printf.h" 54 55#include "ui_command.h" 56 57int ui_init_tracecmds(void); 58static int ui_cmd_tracestart(ui_cmdline_t *cmd,int argc,char *argv[]); 59static int ui_cmd_tracestop(ui_cmdline_t *cmd,int argc,char *argv[]); 60static int ui_cmd_tracefreeze(ui_cmdline_t *cmd,int argc,char *argv[]); 61static int ui_cmd_traceread(ui_cmdline_t *cmd,int argc,char *argv[]); 62 63 64int ui_init_tracecmds(void) 65{ 66 67 cmd_addcmd("trace start", 68 ui_cmd_tracestart, 69 NULL, 70 "Start trace buffer data collection", 71 "trace start [n [agent]]\n\n" 72 "Start tracing ZBbus transactions, using the n-th canned\n" 73 "trigger/filter condition\n" 74 " n = 0: <agent>-mastered transactions\n" 75 " n = 1: CPU0 accesses to LDT dual-hosted region\n", 76 ""); 77 cmd_addcmd("trace stop", 78 ui_cmd_tracestop, 79 NULL, 80 "Stop trace buffer data collection", 81 "trace stop\n\n" 82 "Stop tracing ZBbus transactions", 83 ""); 84 cmd_addcmd("trace freeze", 85 ui_cmd_tracefreeze, 86 NULL, 87 "Freeze trace buffer", 88 "trace freeze\n\n" 89 "Freeze the trace buffer", 90 ""); 91 cmd_addcmd("trace read", 92 ui_cmd_traceread, 93 NULL, 94 "Read trace buffer into memory", 95 "trace read\n\n" 96 "Allocate a block of memory, copy the unprocessed contents\n" 97 "of the trace buffer into it, and generate a command template\n" 98 "for writing it to a file via TFTP.", 99 ""); 100 101 return 0; 102} 103 104#define TB_SIZE (256*48) /* 256 entries, 384 bits/entry */ 105#define ZB_AGENT_CPU0 0 106#define ZB_AGENT_CPU1 1 107#define ZB_AGENT_IOB0 2 108#define ZB_AGENT_IOB1 3 109#define ZB_AGENT_SCD 4 110#define ZB_AGENT_L2C 6 111#define ZB_AGENT_MC 7 112 113static const struct { 114 const char *id; 115 int code; 116} agent_id[] = { 117 { "cpu0", ZB_AGENT_CPU0 }, 118 { "cpu1", ZB_AGENT_CPU1 }, 119 { "iob0", ZB_AGENT_IOB0 }, 120 { "iob1", ZB_AGENT_IOB1 }, 121 { "scd", ZB_AGENT_SCD }, 122 { "l2c", ZB_AGENT_L2C }, 123 { "mc", ZB_AGENT_MC }, 124 { NULL, 0 } 125}; 126 127static int 128getagentarg (const char *id, int *agent) 129{ 130 int i; 131 132 for (i = 0; agent_id[i].id != NULL; i++) { 133 if (strcmp(id, agent_id[i].id) == 0) { 134 *agent = agent_id[i].code; 135 return 1; 136 } 137 } 138 return 0; 139} 140 141static int 142getaddrarg (const char *x, long *addr) 143{ 144 int res; 145 146 res = 0; 147 *addr = 0; 148 149 if (x) { 150 /* 151 * Following gdb, we make 64-bit addresses expressed as 152 * 8-digit numbers sign extend automagically. Saves 153 * typing, but is very gross. 154 */ 155 int longaddr; 156 157 longaddr = strlen(x); 158 if (memcmp(x,"0x",2) == 0) longaddr -= 2; 159 160 *addr = (longaddr > 8) ? (long) xtoq(x) : (long) xtoi(x); 161 res = 1; 162 } 163 164 return res; 165} 166 167 168static int ui_cmd_tracestart(ui_cmdline_t *cmd, int argc, char *argv[]) 169{ 170 volatile uint64_t *tb_cfg; 171 172 tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG); 173 174 if (argc != 0) { 175 volatile uint64_t *at_down_0, *at_up_0, *at_cfg_0; 176 volatile uint64_t *tb_evt_0, *tb_evt_4; 177 volatile uint64_t *tb_seq_0, *tb_seq_4; 178 int i, n; 179 int found; 180 int agent; 181 182 /* Place holder: parse new trace spec (select an option for now) */ 183 184 n = atoi(cmd_getarg(cmd,0)); 185 186 at_down_0 = (volatile uint64_t *) PHYS_TO_K1(A_ADDR_TRAP_DOWN_0); 187 at_up_0 = (volatile uint64_t *) PHYS_TO_K1(A_ADDR_TRAP_UP_0); 188 at_cfg_0 = (volatile uint64_t *) PHYS_TO_K1(A_ADDR_TRAP_CFG_0); 189 190 tb_evt_0 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_EVENT_0); 191 tb_evt_4 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_EVENT_4); 192 tb_seq_0 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_SEQUENCE_0); 193 tb_seq_4 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_SEQUENCE_4); 194 195 /* Reset everything */ 196 *tb_cfg = M_SCD_TRACE_CFG_RESET; 197 __asm__ __volatile__ ("sync" : : : "memory"); 198 199 for (i = 0; i < 4; i++) { 200 tb_evt_0[i] = 0; tb_evt_4[i] = 0; 201 tb_seq_0[i] = 0; tb_seq_4[i] = 0; 202 } 203 __asm__ __volatile__ ("sync" : : : "memory"); 204 205 switch (n) { 206 case 0: 207 /* Filter on agent request or response */ 208 if (argc > 1) 209 found = getagentarg(cmd_getarg(cmd,1), &agent); 210 else 211 found = 0; 212 if (!found) 213 agent = ZB_AGENT_IOB0; /* temporary, for backward compat */ 214 215 tb_evt_0[0] = M_SCD_TREVT_REQID_MATCH 216 | (M_SCD_TREVT_READ | M_SCD_TREVT_WRITE) 217 | V_SCD_TREVT_REQID(agent); 218 tb_evt_0[1] = M_SCD_TREVT_DATAID_MATCH 219 | V_SCD_TREVT_DATAID(agent); 220 221 tb_seq_0[0] = 0x0fff 222 | M_SCD_TRSEQ_ASAMPLE; 223 tb_seq_0[1] = 0x1fff 224 | M_SCD_TRSEQ_DSAMPLE; 225 break; 226 case 1: 227 /* Filter on CPU accesses in LDT mirror region. */ 228 (void)getaddrarg; 229 230 at_down_0[0] = 0xe000000000; 231 at_up_0[0] = 0xefffffffff; 232 at_cfg_0[0] = M_ATRAP_CFG_ALL; 233 234 tb_evt_0[0] = M_SCD_TREVT_REQID_MATCH 235 | V_SCD_TREVT_ADDR_MATCH(0x1) /* addr trap 0 */ 236 | (M_SCD_TREVT_READ | M_SCD_TREVT_WRITE) 237 | V_SCD_TREVT_REQID(ZB_AGENT_CPU0); 238 tb_evt_0[1] = M_SCD_TREVT_RESPID_MATCH 239 | V_SCD_TREVT_RESPID(ZB_AGENT_IOB0); 240 241 tb_seq_0[0] = 0x0fff 242 | M_SCD_TRSEQ_ASAMPLE; 243 tb_seq_0[1] = 0x1fff 244 | M_SCD_TRSEQ_DSAMPLE; 245 break; 246 default: 247 break; 248 } 249 250 __asm__ __volatile__ ("sync" : : : "memory"); 251printf("trace start: trace 0: %llx 1: %llx\n", tb_evt_0[0], tb_evt_0[1]); 252printf(" seq 0: %llx 1: %llx\n", tb_seq_0[0], tb_seq_0[1]); 253 } 254 255 *tb_cfg = M_SCD_TRACE_CFG_START; 256 __asm__ __volatile__ ("sync" : : : "memory"); 257 258printf("trace start: cfg %llx\n", *tb_cfg); 259 return 0; 260} 261 262static int ui_cmd_tracestop(ui_cmdline_t *cmd, int argc, char *argv[]) 263{ 264 volatile uint64_t *tb_cfg; 265 266 tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG); 267 *tb_cfg = M_SCD_TRACE_CFG_STOP; 268 __asm__ __volatile__ ("sync" : : : "memory"); 269 270printf("trace stop: cfg %llx\n", *tb_cfg); 271 return 0; 272} 273 274static int ui_cmd_tracefreeze(ui_cmdline_t *cmd, int argc, char *argv[]) 275{ 276 volatile uint64_t *tb_cfg; 277 278 tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG); 279 *tb_cfg = M_SCD_TRACE_CFG_FREEZE; 280 __asm__ __volatile__ ("sync" : : : "memory"); 281 282printf("trace freeze: cfg %llx\n", *tb_cfg); 283 return 0; 284} 285 286/* read out trace buffer to dump to a file */ 287 288static int ui_cmd_traceread(ui_cmdline_t *cmd, int argc, char *argv[]) 289{ 290 uint64_t *p; 291 volatile uint64_t *tb_cfg; 292 volatile uint64_t *tb_read; 293 int i; 294 295 p = KMALLOC(TB_SIZE, 0); 296 if (!p) { 297 printf("trace read: buffer allocation failed\n"); 298 return -1; 299 } 300 301 tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG); 302 tb_read = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_READ); 303 304 while ((*tb_cfg & M_SCD_TRACE_CFG_FREEZE) == 0) { 305 *tb_cfg = M_SCD_TRACE_CFG_FREEZE; 306 __asm__ __volatile__ ("sync" : : : "memory"); 307 } 308 309 *tb_cfg = M_SCD_TRACE_CFG_START_READ; 310 __asm__ __volatile__ ("sync" : : : "memory"); 311 312 /* Loop runs backward because bundles are read out in reverse order. */ 313 for (i = 256*6; i > 0; i -= 6) { 314 /* Subscripts decrease to put bundle in order. */ 315 p[i-1] = *tb_read; /* t2 hi */ 316 p[i-2] = *tb_read; /* t2 lo */ 317 p[i-3] = *tb_read; /* t1 hi */ 318 p[i-4] = *tb_read; /* t1 lo */ 319 p[i-5] = *tb_read; /* t0 hi */ 320 p[i-6] = *tb_read; /* t0 lo */ 321 } 322 323 printf("save hardy:ehs/sample.trace %p 0x%lx\n", p, TB_SIZE); 324 325 return 0; 326} 327