cvmx-tra.c revision 215990
1/***********************license start***************
2 * Copyright (c) 2003-2010  Cavium Networks (support@cavium.com). All rights
3 * reserved.
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *   * Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 *
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.
17
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
21 *     permission.
22
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
26 * countries.
27
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**************************************/
39
40
41
42
43
44
45/**
46 * @file
47 *
48 * Interface to the Trace buffer hardware.
49 *
50 * <hr>$Revision: 30644 $<hr>
51 */
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>
56#else
57#include "cvmx.h"
58#include "cvmx-tra.h"
59#endif
60
61static const char *TYPE_ARRAY[] = {
62    "DWB - Don't write back",
63    "PL2 - Prefetch into L2",
64    "PSL1 - Dcache fill, skip L2",
65    "LDD - Dcache fill",
66    "LDI - Icache/IO fill",
67    "LDT - Icache/IO fill, skip L2",
68    "STF - Store full",
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",
76    "IOBST - IOB store",
77    "IOBDMA - Async IOB",
78    "SAA - Store atomic add",
79    "RSVD17",
80    "RSVD18",
81    "RSVD19",
82    "RSVD20",
83    "RSVD21",
84    "RSVD22",
85    "RSVD23",
86    "RSVD24",
87    "RSVD25",
88    "RSVD26",
89    "RSVD27",
90    "RSVD28",
91    "RSVD29",
92    "RSVD30",
93    "RSVD31"
94};
95
96static const char *TYPE_ARRAY2[] = {
97    "NOP - None",
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",
103    "RSVD6",
104    "RSVD7",
105    "LDD - Dcache fill",
106    "PSL1 - Prefetch L1, skip L2",
107    "RSVD10",
108    "RSVD11",
109    "RSVD12",
110    "RSVD13",
111    "RSVD14",
112    "IOBDMA - Async IOB",
113    "STF - Store full",
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",
124    "RSVD27",
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",
153    "RSVD56",
154    "RSVD57",
155    "FAA32 - 32bit Atomic fetch and add",
156    "FAA64 - 64bit Atomic fetch and add",
157    "RSVD60",
158    "RSVD61",
159    "SAA32 - 32bit Atomic add",
160    "SAA64 - 64bit Atomic add"
161};
162
163static const char *SOURCE_ARRAY[] = {
164    "PP0",
165    "PP1",
166    "PP2",
167    "PP3",
168    "PP4",
169    "PP5",
170    "PP6",
171    "PP7",
172    "PP8",
173    "PP9",
174    "PP10",
175    "PP11",
176    "PP12",
177    "PP13",
178    "PP14",
179    "PP15",
180    "PIP/IPD",
181    "PKO-R",
182    "FPA/TIM/DFA/PCI/ZIP/POW/PKO-W",
183    "DWB",
184    "RSVD20",
185    "RSVD21",
186    "RSVD22",
187    "RSVD23",
188    "RSVD24",
189    "RSVD25",
190    "RSVD26",
191    "RSVD27",
192    "RSVD28",
193    "RSVD29",
194    "RSVD30",
195    "RSVD31"
196};
197
198static const char *DEST_ARRAY[] = {
199    "CIU/GPIO",
200    "RSVD1",
201    "RSVD2",
202    "PCI/PCIe/SLI",
203    "KEY",
204    "FPA",
205    "DFA",
206    "ZIP",
207    "RNG",
208    "IPD",
209    "PKO",
210    "RSVD11",
211    "POW",
212    "USB0",
213    "RAD",
214    "RSVD15",
215    "RSVD16",
216    "RSVD17",
217    "RSVD18",
218    "RSVD19",
219    "RSVD20",
220    "RSVD21",
221    "RSVD22",
222    "RSVD23",
223    "RSVD24",
224    "RSVD25",
225    "RSVD26",
226    "DPI",
227    "RSVD28",
228    "RSVD29",
229    "FAU",
230    "RSVD31"
231};
232
233#define CVMX_TRA_SOURCE_MASK       (OCTEON_IS_MODEL(OCTEON_CN63XX) ? 0xf00ff : 0xfffff)
234#define CVMX_TRA_DESTINATION_MASK  0xfffffffful
235
236/**
237 * @INTERNAL
238 * Setup the trace buffer filter command mask. The bit position of filter commands
239 * are different for each Octeon model.
240 *
241 * @param filter    Which event to log
242 * @return          Bitmask of filter command based on the event.
243 */
244static uint64_t __cvmx_tra_set_filter_cmd_mask(cvmx_tra_filt_t filter)
245{
246    cvmx_tra_filt_cmd_t filter_command;
247
248    if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
249    {
250        /* Bit positions of filter commands are different, map it accordingly */
251        uint64_t cmd = 0;
252        if ((filter & CVMX_TRA_FILT_ALL) == -1ull)
253        {
254            if (OCTEON_IS_MODEL(OCTEON_CN5XXX))
255                cmd = 0x1ffff;
256            else
257                cmd = 0xffff;
258        }
259        if (filter & CVMX_TRA_FILT_DWB)
260            cmd |= 1ull<<0;
261        if (filter & CVMX_TRA_FILT_PL2)
262            cmd |= 1ull<<1;
263        if (filter & CVMX_TRA_FILT_PSL1)
264            cmd |= 1ull<<2;
265        if (filter & CVMX_TRA_FILT_LDD)
266            cmd |= 1ull<<3;
267        if (filter & CVMX_TRA_FILT_LDI)
268            cmd |= 1ull<<4;
269        if (filter & CVMX_TRA_FILT_LDT)
270            cmd |= 1ull<<5;
271        if (filter & CVMX_TRA_FILT_STF)
272            cmd |= 1ull<<6;
273        if (filter & CVMX_TRA_FILT_STC)
274            cmd |= 1ull<<7;
275        if (filter & CVMX_TRA_FILT_STP)
276            cmd |= 1ull<<8;
277        if (filter & CVMX_TRA_FILT_STT)
278            cmd |= 1ull<<9;
279        if (filter & CVMX_TRA_FILT_IOBLD8)
280            cmd |= 1ull<<10;
281        if (filter & CVMX_TRA_FILT_IOBLD16)
282            cmd |= 1ull<<11;
283        if (filter & CVMX_TRA_FILT_IOBLD32)
284            cmd |= 1ull<<12;
285        if (filter & CVMX_TRA_FILT_IOBLD64)
286            cmd |= 1ull<<13;
287        if (filter & CVMX_TRA_FILT_IOBST)
288            cmd |= 1ull<<14;
289        if (filter & CVMX_TRA_FILT_IOBDMA)
290            cmd |= 1ull<<15;
291        if (OCTEON_IS_MODEL(OCTEON_CN5XXX) && (filter & CVMX_TRA_FILT_SAA))
292            cmd |= 1ull<<16;
293
294        filter_command.u64 = cmd;
295    }
296    else
297    {
298        if ((filter & CVMX_TRA_FILT_ALL) == -1ull)
299            filter_command.u64 = CVMX_TRA_FILT_ALL;
300        else
301            filter_command.u64 = filter;
302
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;
307    }
308    return filter_command.u64;
309}
310
311
312/**
313 * Setup the TRA buffer for use
314 *
315 * @param control TRA control setup
316 * @param filter  Which events to log
317 * @param source_filter
318 *                Source match
319 * @param dest_filter
320 *                Destination match
321 * @param address Address compare
322 * @param address_mask
323 *                Address mask
324 */
325void 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)
328{
329    cvmx_tra_filt_cmd_t filt_cmd;
330    cvmx_tra_filt_sid_t filt_sid;
331    cvmx_tra_filt_did_t filt_did;
332
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;
336
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);
343}
344#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
345EXPORT_SYMBOL(cvmx_tra_setup);
346#endif
347
348
349/**
350 * Setup a TRA trigger. How the triggers are used should be
351 * setup using cvmx_tra_setup.
352 *
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
357 * @param dest_filter
358 *                Destination trigger match
359 * @param address Trigger address compare
360 * @param address_mask
361 *                Trigger address mask
362 */
363void 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)
366{
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;
370
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;
374
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);
380}
381#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
382EXPORT_SYMBOL(cvmx_tra_trig_setup);
383#endif
384
385
386/**
387 * Read an entry from the TRA buffer
388 *
389 * @return Value return. High bit will be zero if there wasn't any data
390 */
391cvmx_tra_data_t cvmx_tra_read(void)
392{
393    uint64_t address = CVMX_TRA_READ_DAT;
394    cvmx_tra_data_t result;
395
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))
399    {
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);
403    }
404    else
405    {
406        result.u128.data = cvmx_read_csr(address);
407        result.u128.datahi = 0;
408    }
409
410    return result;
411}
412
413/**
414 * Decode a TRA entry into human readable output
415 *
416 * @param tra_ctl Trace control setup
417 * @param data    Data to decode
418 */
419void cvmx_tra_decode_text(cvmx_tra_ctl_t tra_ctl, cvmx_tra_data_t data)
420{
421    if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
422    {
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;
426
427        if (type >= 0x1a)
428            type &= 0xf;
429
430        switch (type)
431        {
432            case 0:  /* DWB */
433            case 1:  /* PL2 */
434            case 2:  /* PSL1 */
435            case 3:  /* LDD */
436            case 4:  /* LDI */
437            case 5:  /* LDT */
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),
442                    TYPE_ARRAY[type],
443                    SOURCE_ARRAY[data.cmn.source],
444                    (unsigned long long)data.cmn.address);
445                break;
446            case 6:  /* STF */
447            case 7:  /* STC */
448            case 8:  /* STP */
449            case 9:  /* STT */
450            case 16: /* SAA */
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),
455                   TYPE_ARRAY[type],
456                   SOURCE_ARRAY[data.store.source],
457                   (unsigned int)data.store.mask,
458                   (unsigned long long)data.store.address << 3);
459                break;
460            case 10:  /* IOBLD8 */
461            case 11:  /* IOBLD16 */
462            case 12:  /* IOBLD32 */
463            case 13:  /* IOBLD64 */
464            case 14:  /* IOBST */
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),
469                   TYPE_ARRAY[type],
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);
474                break;
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),
480                   TYPE_ARRAY[type],
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);
485                break;
486            default:
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));
491                break;
492        }
493    }
494    else
495    {
496        int type;
497
498        type = data.cmn2.type;
499
500        switch (1ull<<type)
501        {
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),
528                   TYPE_ARRAY2[type],
529                   SOURCE_ARRAY[data.cmn2.source],
530                   (unsigned long long)data.cmn2.addresshi,
531                   (unsigned long long)data.cmn2.addresslo);
532                break;
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),
549                   TYPE_ARRAY2[type],
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);
554                break;
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),
567                   TYPE_ARRAY2[type],
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);
573                break;
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),
579                   TYPE_ARRAY2[type],
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);
585                break;
586            default:
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));
591                break;
592        }
593    }
594}
595
596/**
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
600 * that it created.
601 */
602void cvmx_tra_display(void)
603{
604    cvmx_tra_ctl_t tra_ctl;
605    cvmx_tra_data_t data;
606    int valid = 0;
607
608    tra_ctl.u64 = cvmx_read_csr(CVMX_TRA_CTL);
609
610    do
611    {
612        data = cvmx_tra_read();
613        if ((OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) && data.cmn.valid)
614            valid = 1;
615        else if (data.cmn2.valid)
616            valid = 1;
617        else
618            valid = 0;
619
620        if (valid)
621            cvmx_tra_decode_text(tra_ctl, data);
622
623    } while (valid);
624}
625#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
626EXPORT_SYMBOL(cvmx_tra_display);
627#endif
628