1 /***********************license start***************
2 * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * * Neither the name of Cavium Networks nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
23 * This Software, including technical data, may be subject to U.S. export control
24 * laws, including the U.S. Export Administration Act and its associated
25 * regulations, and may be subject to export or import regulations in other
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
48 * Interface to the Trace buffer hardware.
50 * <hr>$Revision: 30644 $<hr>
52 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
53 #include <linux/module.h>
54 #include <asm/octeon/cvmx.h>
55 #include <asm/octeon/cvmx-tra.h>
61 static const char *TYPE_ARRAY[] = {
62 "DWB - Don't write back",
63 "PL2 - Prefetch into L2",
64 "PSL1 - Dcache fill, skip L2",
66 "LDI - Icache/IO fill",
67 "LDT - Icache/IO fill, skip L2",
69 "STC - Store conditional",
70 "STP - Store partial",
71 "STT - Store full, skip L2",
72 "IOBLD8 - IOB 8bit load",
73 "IOBLD16 - IOB 16bit load",
74 "IOBLD32 - IOB 32bit load",
75 "IOBLD64 - IOB 64bit load",
78 "SAA - Store atomic add",
96 static const char *TYPE_ARRAY2[] = {
98 "LDT - Icache/IO fill, skip L2",
99 "LDI - Icache/IO fill",
100 "PL2 - Prefetch into L2",
101 "RPL2 - Mark for replacement in L2",
102 "DWB - Don't write back",
106 "PSL1 - Prefetch L1, skip L2",
112 "IOBDMA - Async IOB",
114 "STT - Store full, skip L2",
115 "STP - Store partial",
116 "STC - Store conditional",
117 "STFIL1 - Store full, invalidate L1",
118 "STTIL1 - Store full, skip L2, invalidate L1",
119 "FAS32 - Atomic 32bit swap",
120 "FAS64 - Atomic 64bit swap",
121 "WBIL2i - Writeback, invalidate, by index/way",
122 "LTGL2i - Read tag@index/way",
123 "STGL2i - Write tag@index/way",
125 "INVL2 - Invalidate, by address",
126 "WBIL2 - Writeback, invalidate, by address",
127 "WBL2 - Writeback, by address",
128 "LCKL2 - Allocate, lock, by address",
129 "IOBLD8 - IOB 8bit load",
130 "IOBLD16 - IOB 16bit load",
131 "IOBLD32 - IOB 32bit load",
132 "IOBLD64 - IOB 64bit load",
133 "IOBST8 - IOB 8bit store",
134 "IOBST16 - IOB 16bit store",
135 "IOBST32 - IOB 32bit store",
136 "IOBST64 - IOB 64bit store",
137 "SET8 - 8bit Atomic swap with 1's",
138 "SET16 - 16bit Atomic swap with 1's",
139 "SET32 - 32bit Atomic swap with 1's",
140 "SET64 - 64bit Atomic swap with 1's",
141 "CLR8 - 8bit Atomic swap with 0's",
142 "CLR16 - 16bit Atomic swap with 0's",
143 "CLR32 - 32bit Atomic swap with 0's",
144 "CLR64 - 64bit Atomic swap with 0's",
145 "INCR8 - 8bit Atomic fetch & add by 1",
146 "INCR16 - 16bit Atomic fetch & add by 1",
147 "INCR32 - 32bit Atomic fetch & add by 1",
148 "INCR64 - 64bit Atomic fetch & add by 1",
149 "DECR8 - 8bit Atomic fetch & add by -1",
150 "DECR16 - 16bit Atomic fetch & add by -1",
151 "DECR32 - 32bit Atomic fetch & add by -1",
152 "DECR64 - 64bit Atomic fetch & add by -1",
155 "FAA32 - 32bit Atomic fetch and add",
156 "FAA64 - 64bit Atomic fetch and add",
159 "SAA32 - 32bit Atomic add",
160 "SAA64 - 64bit Atomic add"
163 static const char *SOURCE_ARRAY[] = {
182 "FPA/TIM/DFA/PCI/ZIP/POW/PKO-W",
198 static const char *DEST_ARRAY[] = {
233 #define CVMX_TRA_SOURCE_MASK (OCTEON_IS_MODEL(OCTEON_CN63XX) ? 0xf00ff : 0xfffff)
234 #define CVMX_TRA_DESTINATION_MASK 0xfffffffful
238 * Setup the trace buffer filter command mask. The bit position of filter commands
239 * are different for each Octeon model.
241 * @param filter Which event to log
242 * @return Bitmask of filter command based on the event.
244 static uint64_t __cvmx_tra_set_filter_cmd_mask(cvmx_tra_filt_t filter)
246 cvmx_tra_filt_cmd_t filter_command;
248 if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
250 /* Bit positions of filter commands are different, map it accordingly */
252 if ((filter & CVMX_TRA_FILT_ALL) == -1ull)
254 if (OCTEON_IS_MODEL(OCTEON_CN5XXX))
259 if (filter & CVMX_TRA_FILT_DWB)
261 if (filter & CVMX_TRA_FILT_PL2)
263 if (filter & CVMX_TRA_FILT_PSL1)
265 if (filter & CVMX_TRA_FILT_LDD)
267 if (filter & CVMX_TRA_FILT_LDI)
269 if (filter & CVMX_TRA_FILT_LDT)
271 if (filter & CVMX_TRA_FILT_STF)
273 if (filter & CVMX_TRA_FILT_STC)
275 if (filter & CVMX_TRA_FILT_STP)
277 if (filter & CVMX_TRA_FILT_STT)
279 if (filter & CVMX_TRA_FILT_IOBLD8)
281 if (filter & CVMX_TRA_FILT_IOBLD16)
283 if (filter & CVMX_TRA_FILT_IOBLD32)
285 if (filter & CVMX_TRA_FILT_IOBLD64)
287 if (filter & CVMX_TRA_FILT_IOBST)
289 if (filter & CVMX_TRA_FILT_IOBDMA)
291 if (OCTEON_IS_MODEL(OCTEON_CN5XXX) && (filter & CVMX_TRA_FILT_SAA))
294 filter_command.u64 = cmd;
298 if ((filter & CVMX_TRA_FILT_ALL) == -1ull)
299 filter_command.u64 = CVMX_TRA_FILT_ALL;
301 filter_command.u64 = filter;
303 filter_command.cn63xx.reserved_60_61 = 0;
304 filter_command.cn63xx.reserved_56_57 = 0;
305 filter_command.cn63xx.reserved_10_14 = 0;
306 filter_command.cn63xx.reserved_6_7 = 0;
308 return filter_command.u64;
313 * Setup the TRA buffer for use
315 * @param control TRA control setup
316 * @param filter Which events to log
317 * @param source_filter
321 * @param address Address compare
322 * @param address_mask
325 void cvmx_tra_setup(cvmx_tra_ctl_t control, cvmx_tra_filt_t filter,
326 cvmx_tra_sid_t source_filter, cvmx_tra_did_t dest_filter,
327 uint64_t address, uint64_t address_mask)
329 cvmx_tra_filt_cmd_t filt_cmd;
330 cvmx_tra_filt_sid_t filt_sid;
331 cvmx_tra_filt_did_t filt_did;
333 filt_cmd.u64 = __cvmx_tra_set_filter_cmd_mask(filter);
334 filt_sid.u64 = source_filter & CVMX_TRA_SOURCE_MASK;
335 filt_did.u64 = dest_filter & CVMX_TRA_DESTINATION_MASK;
337 cvmx_write_csr(CVMX_TRA_CTL, control.u64);
338 cvmx_write_csr(CVMX_TRA_FILT_CMD, filt_cmd.u64);
339 cvmx_write_csr(CVMX_TRA_FILT_SID, filt_sid.u64);
340 cvmx_write_csr(CVMX_TRA_FILT_DID, filt_did.u64);
341 cvmx_write_csr(CVMX_TRA_FILT_ADR_ADR, address);
342 cvmx_write_csr(CVMX_TRA_FILT_ADR_MSK, address_mask);
344 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
345 EXPORT_SYMBOL(cvmx_tra_setup);
350 * Setup a TRA trigger. How the triggers are used should be
351 * setup using cvmx_tra_setup.
353 * @param trigger Trigger to setup (0 or 1)
354 * @param filter Which types of events to trigger on
355 * @param source_filter
356 * Source trigger match
358 * Destination trigger match
359 * @param address Trigger address compare
360 * @param address_mask
361 * Trigger address mask
363 void cvmx_tra_trig_setup(uint64_t trigger, cvmx_tra_filt_t filter,
364 cvmx_tra_sid_t source_filter, cvmx_tra_did_t dest_filter,
365 uint64_t address, uint64_t address_mask)
367 cvmx_tra_filt_cmd_t tra_filt_cmd;
368 cvmx_tra_filt_sid_t tra_filt_sid;
369 cvmx_tra_filt_did_t tra_filt_did;
371 tra_filt_cmd.u64 = __cvmx_tra_set_filter_cmd_mask(filter);
372 tra_filt_sid.u64 = source_filter & CVMX_TRA_SOURCE_MASK;
373 tra_filt_did.u64 = dest_filter & CVMX_TRA_DESTINATION_MASK;
375 cvmx_write_csr(CVMX_TRA_TRIG0_CMD + trigger * 64, tra_filt_cmd.u64);
376 cvmx_write_csr(CVMX_TRA_TRIG0_SID + trigger * 64, tra_filt_sid.u64);
377 cvmx_write_csr(CVMX_TRA_TRIG0_DID + trigger * 64, tra_filt_did.u64);
378 cvmx_write_csr(CVMX_TRA_TRIG0_ADR_ADR + trigger * 64, address);
379 cvmx_write_csr(CVMX_TRA_TRIG0_ADR_MSK + trigger * 64, address_mask);
381 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
382 EXPORT_SYMBOL(cvmx_tra_trig_setup);
387 * Read an entry from the TRA buffer
389 * @return Value return. High bit will be zero if there wasn't any data
391 cvmx_tra_data_t cvmx_tra_read(void)
393 uint64_t address = CVMX_TRA_READ_DAT;
394 cvmx_tra_data_t result;
396 /* The trace buffer format is wider than 64-bits in Octeon2 model,
397 read the register again to get the second part of the data. */
398 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) && !OCTEON_IS_MODEL(OCTEON_CN5XXX))
400 /* These reads need to be as close as possible to each other */
401 result.u128.data = cvmx_read_csr(address);
402 result.u128.datahi = cvmx_read_csr(address);
406 result.u128.data = cvmx_read_csr(address);
407 result.u128.datahi = 0;
414 * Decode a TRA entry into human readable output
416 * @param tra_ctl Trace control setup
417 * @param data Data to decode
419 void cvmx_tra_decode_text(cvmx_tra_ctl_t tra_ctl, cvmx_tra_data_t data)
421 if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
423 /* The type is a five bit field for some entries and 4 for other. The four
424 bit entries can be mis-typed if the top is set */
425 int type = data.cmn.type;
438 cvmx_dprintf("0x%016llx %c%+10d %s %s 0x%016llx\n",
439 (unsigned long long)data.u128.data,
440 (data.cmn.discontinuity) ? 'D' : ' ',
441 data.cmn.timestamp << (tra_ctl.s.time_grn*3),
443 SOURCE_ARRAY[data.cmn.source],
444 (unsigned long long)data.cmn.address);
451 cvmx_dprintf("0x%016llx %c%+10d %s %s mask=0x%02x 0x%016llx\n",
452 (unsigned long long)data.u128.data,
453 (data.cmn.discontinuity) ? 'D' : ' ',
454 data.cmn.timestamp << (tra_ctl.s.time_grn*3),
456 SOURCE_ARRAY[data.store.source],
457 (unsigned int)data.store.mask,
458 (unsigned long long)data.store.address << 3);
460 case 10: /* IOBLD8 */
461 case 11: /* IOBLD16 */
462 case 12: /* IOBLD32 */
463 case 13: /* IOBLD64 */
465 cvmx_dprintf("0x%016llx %c%+10d %s %s->%s subdid=0x%x 0x%016llx\n",
466 (unsigned long long)data.u128.data,
467 (data.cmn.discontinuity) ? 'D' : ' ',
468 data.cmn.timestamp << (tra_ctl.s.time_grn*3),
470 SOURCE_ARRAY[data.iobld.source],
471 DEST_ARRAY[data.iobld.dest],
472 (unsigned int)data.iobld.subid,
473 (unsigned long long)data.iobld.address);
475 case 15: /* IOBDMA */
476 cvmx_dprintf("0x%016llx %c%+10d %s %s->%s len=0x%x 0x%016llx\n",
477 (unsigned long long)data.u128.data,
478 (data.cmn.discontinuity) ? 'D' : ' ',
479 data.cmn.timestamp << (tra_ctl.s.time_grn*3),
481 SOURCE_ARRAY[data.iob.source],
482 DEST_ARRAY[data.iob.dest],
483 (unsigned int)data.iob.mask,
484 (unsigned long long)data.iob.address << 3);
487 cvmx_dprintf("0x%016llx %c%+10d Unknown format\n",
488 (unsigned long long)data.u128.data,
489 (data.cmn.discontinuity) ? 'D' : ' ',
490 data.cmn.timestamp << (tra_ctl.s.time_grn*3));
498 type = data.cmn2.type;
502 case CVMX_TRA_FILT_DECR64:
503 case CVMX_TRA_FILT_DECR32:
504 case CVMX_TRA_FILT_DECR16:
505 case CVMX_TRA_FILT_DECR8:
506 case CVMX_TRA_FILT_INCR64:
507 case CVMX_TRA_FILT_INCR32:
508 case CVMX_TRA_FILT_INCR16:
509 case CVMX_TRA_FILT_INCR8:
510 case CVMX_TRA_FILT_CLR64:
511 case CVMX_TRA_FILT_CLR32:
512 case CVMX_TRA_FILT_CLR16:
513 case CVMX_TRA_FILT_CLR8:
514 case CVMX_TRA_FILT_SET64:
515 case CVMX_TRA_FILT_SET32:
516 case CVMX_TRA_FILT_SET16:
517 case CVMX_TRA_FILT_SET8:
518 case CVMX_TRA_FILT_WBL2:
519 case CVMX_TRA_FILT_DWB:
520 case CVMX_TRA_FILT_RPL2:
521 case CVMX_TRA_FILT_PL2:
522 case CVMX_TRA_FILT_LDI:
523 case CVMX_TRA_FILT_LDT:
524 cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s 0x%016llx%llx\n",
525 (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data,
526 (data.cmn2.discontinuity) ? 'D' : ' ',
527 data.cmn2.timestamp << (tra_ctl.s.time_grn*3),
529 SOURCE_ARRAY[data.cmn2.source],
530 (unsigned long long)data.cmn2.addresshi,
531 (unsigned long long)data.cmn2.addresslo);
533 case CVMX_TRA_FILT_PSL1:
534 case CVMX_TRA_FILT_LDD:
535 case CVMX_TRA_FILT_FAS64:
536 case CVMX_TRA_FILT_FAS32:
537 case CVMX_TRA_FILT_FAA64:
538 case CVMX_TRA_FILT_FAA32:
539 case CVMX_TRA_FILT_SAA64:
540 case CVMX_TRA_FILT_SAA32:
541 case CVMX_TRA_FILT_STC:
542 case CVMX_TRA_FILT_STF:
543 case CVMX_TRA_FILT_STP:
544 case CVMX_TRA_FILT_STT:
545 cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s mask=0x%02x 0x%016llx%llx\n",
546 (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data,
547 (data.cmn2.discontinuity) ? 'D' : ' ',
548 data.cmn2.timestamp << (tra_ctl.s.time_grn*3),
550 SOURCE_ARRAY[data.store2.source],
551 (unsigned int)data.store2.mask,
552 (unsigned long long)data.store2.addresshi,
553 (unsigned long long)data.store2.addresslo);
555 case CVMX_TRA_FILT_IOBST64:
556 case CVMX_TRA_FILT_IOBST32:
557 case CVMX_TRA_FILT_IOBST16:
558 case CVMX_TRA_FILT_IOBST8:
559 case CVMX_TRA_FILT_IOBLD64:
560 case CVMX_TRA_FILT_IOBLD32:
561 case CVMX_TRA_FILT_IOBLD16:
562 case CVMX_TRA_FILT_IOBLD8:
563 cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s->%s subdid=0x%x 0x%016llx%llx\n",
564 (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data,
565 (data.cmn2.discontinuity) ? 'D' : ' ',
566 data.cmn2.timestamp << (tra_ctl.s.time_grn*3),
568 SOURCE_ARRAY[data.iobld2.source],
569 DEST_ARRAY[data.iobld2.dest],
570 (unsigned int)data.iobld2.subid,
571 (unsigned long long)data.iobld2.addresshi,
572 (unsigned long long)data.iobld2.addresslo);
574 case CVMX_TRA_FILT_IOBDMA:
575 cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s->%s len=0x%x 0x%016llx%llx\n",
576 (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data,
577 (data.iob2.discontinuity) ? 'D' : ' ',
578 data.iob2.timestamp << (tra_ctl.s.time_grn*3),
580 SOURCE_ARRAY[data.iob2.source],
581 DEST_ARRAY[data.iob2.dest],
582 (unsigned int)data.iob2.mask,
583 (unsigned long long)data.iob2.addresshi << 3,
584 (unsigned long long)data.iob2.addresslo << 3);
587 cvmx_dprintf("0x%016llx%016llx %c%+10d Unknown format\n",
588 (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data,
589 (data.cmn2.discontinuity) ? 'D' : ' ',
590 data.cmn2.timestamp << (tra_ctl.s.time_grn*3));
597 * Display the entire trace buffer. It is advised that you
598 * disable the trace buffer before calling this routine
599 * otherwise it could infinitely loop displaying trace data
602 void cvmx_tra_display(void)
604 cvmx_tra_ctl_t tra_ctl;
605 cvmx_tra_data_t data;
608 tra_ctl.u64 = cvmx_read_csr(CVMX_TRA_CTL);
612 data = cvmx_tra_read();
613 if ((OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) && data.cmn.valid)
615 else if (data.cmn2.valid)
621 cvmx_tra_decode_text(tra_ctl, data);
625 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
626 EXPORT_SYMBOL(cvmx_tra_display);