diff options
Diffstat (limited to 'sys/contrib/octeon-sdk/cvmx-tra.c')
-rw-r--r-- | sys/contrib/octeon-sdk/cvmx-tra.c | 943 |
1 files changed, 943 insertions, 0 deletions
diff --git a/sys/contrib/octeon-sdk/cvmx-tra.c b/sys/contrib/octeon-sdk/cvmx-tra.c new file mode 100644 index 0000000..4bf8f45 --- /dev/null +++ b/sys/contrib/octeon-sdk/cvmx-tra.c @@ -0,0 +1,943 @@ +/***********************license start*************** + * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights + * reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + + * * Neither the name of Cavium Inc. nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + + * This Software, including technical data, may be subject to U.S. export control + * laws, including the U.S. Export Administration Act and its associated + * regulations, and may be subject to export or import regulations in other + * countries. + + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" + * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR + * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO + * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR + * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM + * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, + * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF + * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR + * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR + * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. + ***********************license end**************************************/ + + + + + + +/** + * @file + * + * Interface to the Trace buffer hardware. + * + * <hr>$Revision: 30644 $<hr> + */ +#ifdef CVMX_BUILD_FOR_LINUX_KERNEL +#include <linux/module.h> +#include <asm/octeon/cvmx.h> +#include <asm/octeon/cvmx-tra.h> +#include <asm/octeon/cvmx-l2c.h> +#else +#include "cvmx.h" +#include "cvmx-tra.h" +#include "cvmx-l2c.h" +#endif + +static const char *TYPE_ARRAY[] = { + "DWB - Don't write back", + "PL2 - Prefetch into L2", + "PSL1 - Dcache fill, skip L2", + "LDD - Dcache fill", + "LDI - Icache/IO fill", + "LDT - Icache/IO fill, skip L2", + "STF - Store full", + "STC - Store conditional", + "STP - Store partial", + "STT - Store full, skip L2", + "IOBLD8 - IOB 8bit load", + "IOBLD16 - IOB 16bit load", + "IOBLD32 - IOB 32bit load", + "IOBLD64 - IOB 64bit load", + "IOBST - IOB store", + "IOBDMA - Async IOB", + "SAA - Store atomic add", + "RSVD17", + "RSVD18", + "RSVD19", + "RSVD20", + "RSVD21", + "RSVD22", + "RSVD23", + "RSVD24", + "RSVD25", + "RSVD26", + "RSVD27", + "RSVD28", + "RSVD29", + "RSVD30", + "RSVD31" +}; + +static const char *TYPE_ARRAY2[] = { + "NOP - None", + "LDT - Icache/IO fill, skip L2", + "LDI - Icache/IO fill", + "PL2 - Prefetch into L2", + "RPL2 - Mark for replacement in L2", + "DWB - Don't write back", + "RSVD6", + "RSVD7", + "LDD - Dcache fill", + "PSL1 - Prefetch L1, skip L2", + "RSVD10", + "RSVD11", + "RSVD12", + "RSVD13", + "RSVD14", + "IOBDMA - Async IOB", + "STF - Store full", + "STT - Store full, skip L2", + "STP - Store partial", + "STC - Store conditional", + "STFIL1 - Store full, invalidate L1", + "STTIL1 - Store full, skip L2, invalidate L1", + "FAS32 - Atomic 32bit swap", + "FAS64 - Atomic 64bit swap", + "WBIL2i - Writeback, invalidate, by index/way", + "LTGL2i - Read tag@index/way", + "STGL2i - Write tag@index/way", + "RSVD27", + "INVL2 - Invalidate, by address", + "WBIL2 - Writeback, invalidate, by address", + "WBL2 - Writeback, by address", + "LCKL2 - Allocate, lock, by address", + "IOBLD8 - IOB 8bit load", + "IOBLD16 - IOB 16bit load", + "IOBLD32 - IOB 32bit load", + "IOBLD64 - IOB 64bit load", + "IOBST8 - IOB 8bit store", + "IOBST16 - IOB 16bit store", + "IOBST32 - IOB 32bit store", + "IOBST64 - IOB 64bit store", + "SET8 - 8bit Atomic swap with 1's", + "SET16 - 16bit Atomic swap with 1's", + "SET32 - 32bit Atomic swap with 1's", + "SET64 - 64bit Atomic swap with 1's", + "CLR8 - 8bit Atomic swap with 0's", + "CLR16 - 16bit Atomic swap with 0's", + "CLR32 - 32bit Atomic swap with 0's", + "CLR64 - 64bit Atomic swap with 0's", + "INCR8 - 8bit Atomic fetch & add by 1", + "INCR16 - 16bit Atomic fetch & add by 1", + "INCR32 - 32bit Atomic fetch & add by 1", + "INCR64 - 64bit Atomic fetch & add by 1", + "DECR8 - 8bit Atomic fetch & add by -1", + "DECR16 - 16bit Atomic fetch & add by -1", + "DECR32 - 32bit Atomic fetch & add by -1", + "DECR64 - 64bit Atomic fetch & add by -1", + "RSVD56", + "RSVD57", + "FAA32 - 32bit Atomic fetch and add", + "FAA64 - 64bit Atomic fetch and add", + "RSVD60", + "RSVD61", + "SAA32 - 32bit Atomic add", + "SAA64 - 64bit Atomic add" +}; + +static const char *SOURCE_ARRAY[] = { + "PP0", + "PP1", + "PP2", + "PP3", + "PP4", + "PP5", + "PP6", + "PP7", + "PP8", + "PP9", + "PP10", + "PP11", + "PP12", + "PP13", + "PP14", + "PP15", + "PIP/IPD", + "PKO-R", + "FPA/TIM/DFA/PCI/ZIP/POW/PKO-W", + "DWB", + "RSVD20", + "RSVD21", + "RSVD22", + "RSVD23", + "RSVD24", + "RSVD25", + "RSVD26", + "RSVD27", + "RSVD28", + "RSVD29", + "RSVD30", + "RSVD31", + "PP16", + "PP17", + "PP18", + "PP19", + "PP20", + "PP21", + "PP22", + "PP23", + "PP24", + "PP25", + "PP26", + "PP27", + "PP28", + "PP29", + "PP30", + "PP31" +}; + +static const char *DEST_ARRAY[] = { + "CIU/GPIO", + "RSVD1", + "RSVD2", + "PCI/PCIe/SLI", + "KEY", + "FPA", + "DFA", + "ZIP", + "RNG", + "IPD", + "PKO", + "RSVD11", + "POW", + "USB0", + "RAD", + "RSVD15", + "RSVD16", + "RSVD17", + "RSVD18", + "RSVD19", + "RSVD20", + "RSVD21", + "RSVD22", + "RSVD23", + "RSVD24", + "RSVD25", + "RSVD26", + "DPI", + "RSVD28", + "RSVD29", + "FAU", + "RSVD31" +}; + +int _cvmx_tra_unit = 0; + +#define CVMX_TRA_SOURCE_MASK (OCTEON_IS_MODEL(OCTEON_CN63XX) ? 0xf00ff : 0xfffff) +#define CVMX_TRA_DESTINATION_MASK 0xfffffffful + +/** + * @INTERNAL + * Setup the trace buffer filter command mask. The bit position of filter commands + * are different for each Octeon model. + * + * @param filter Which event to log + * @return Bitmask of filter command based on the event. + */ +static uint64_t __cvmx_tra_set_filter_cmd_mask(cvmx_tra_filt_t filter) +{ + cvmx_tra_filt_cmd_t filter_command; + + if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) + { + /* Bit positions of filter commands are different, map it accordingly */ + uint64_t cmd = 0; + if ((filter & CVMX_TRA_FILT_ALL) == -1ull) + { + if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) + cmd = 0x1ffff; + else + cmd = 0xffff; + } + if (filter & CVMX_TRA_FILT_DWB) + cmd |= 1ull<<0; + if (filter & CVMX_TRA_FILT_PL2) + cmd |= 1ull<<1; + if (filter & CVMX_TRA_FILT_PSL1) + cmd |= 1ull<<2; + if (filter & CVMX_TRA_FILT_LDD) + cmd |= 1ull<<3; + if (filter & CVMX_TRA_FILT_LDI) + cmd |= 1ull<<4; + if (filter & CVMX_TRA_FILT_LDT) + cmd |= 1ull<<5; + if (filter & CVMX_TRA_FILT_STF) + cmd |= 1ull<<6; + if (filter & CVMX_TRA_FILT_STC) + cmd |= 1ull<<7; + if (filter & CVMX_TRA_FILT_STP) + cmd |= 1ull<<8; + if (filter & CVMX_TRA_FILT_STT) + cmd |= 1ull<<9; + if (filter & CVMX_TRA_FILT_IOBLD8) + cmd |= 1ull<<10; + if (filter & CVMX_TRA_FILT_IOBLD16) + cmd |= 1ull<<11; + if (filter & CVMX_TRA_FILT_IOBLD32) + cmd |= 1ull<<12; + if (filter & CVMX_TRA_FILT_IOBLD64) + cmd |= 1ull<<13; + if (filter & CVMX_TRA_FILT_IOBST) + cmd |= 1ull<<14; + if (filter & CVMX_TRA_FILT_IOBDMA) + cmd |= 1ull<<15; + if (OCTEON_IS_MODEL(OCTEON_CN5XXX) && (filter & CVMX_TRA_FILT_SAA)) + cmd |= 1ull<<16; + + filter_command.u64 = cmd; + } + else + { + if ((filter & CVMX_TRA_FILT_ALL) == -1ull) + filter_command.u64 = CVMX_TRA_FILT_ALL; + else + filter_command.u64 = filter; + + filter_command.cn63xx.reserved_60_61 = 0; + filter_command.cn63xx.reserved_56_57 = 0; + filter_command.cn63xx.reserved_27_27 = 0; + filter_command.cn63xx.reserved_10_14 = 0; + filter_command.cn63xx.reserved_6_7 = 0; + } + return filter_command.u64; +} + + +/** + * Setup the TRA buffer for use + * + * @param control TRA control setup + * @param filter Which events to log + * @param source_filter + * Source match + * @param dest_filter + * Destination match + * @param address Address compare + * @param address_mask + * Address mask + */ +void cvmx_tra_setup(cvmx_tra_ctl_t control, cvmx_tra_filt_t filter, + cvmx_tra_sid_t source_filter, cvmx_tra_did_t dest_filter, + uint64_t address, uint64_t address_mask) +{ + cvmx_tra_filt_cmd_t filt_cmd; + cvmx_tra_filt_sid_t filt_sid; + cvmx_tra_filt_did_t filt_did; + int tad; + + filt_cmd.u64 = __cvmx_tra_set_filter_cmd_mask(filter); + filt_sid.u64 = source_filter & CVMX_TRA_SOURCE_MASK; + filt_did.u64 = dest_filter & CVMX_TRA_DESTINATION_MASK; + + /* Address filtering does not work when IOBDMA filter command is enabled + because of some caveats. Disable the IOBDMA filter command. */ + if ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) + && ((filt_cmd.u64 & CVMX_TRA_FILT_IOBDMA) == CVMX_TRA_FILT_IOBDMA) + && address_mask != 0) + { + cvmx_dprintf("The address-based filtering does not work with IOBDMAs, disabling the filter command.\n"); + filt_cmd.u64 &= ~(CVMX_TRA_FILT_IOBDMA); + } + + /* In OcteonII pass2, the mode bit is added to enable reading the trace + buffer data from different registers for lower and upper 64-bit value. + This bit is reserved in other Octeon models. */ + control.s.rdat_md = 1; + + for (tad = 0; tad < CVMX_L2C_TADS; tad++) + { + cvmx_write_csr(CVMX_TRAX_CTL(tad), control.u64); + cvmx_write_csr(CVMX_TRAX_FILT_CMD(tad), filt_cmd.u64); + cvmx_write_csr(CVMX_TRAX_FILT_SID(tad), filt_sid.u64); + cvmx_write_csr(CVMX_TRAX_FILT_DID(tad), filt_did.u64); + cvmx_write_csr(CVMX_TRAX_FILT_ADR_ADR(tad), address); + cvmx_write_csr(CVMX_TRAX_FILT_ADR_MSK(tad), address_mask); + } +} +#ifdef CVMX_BUILD_FOR_LINUX_KERNEL +EXPORT_SYMBOL(cvmx_tra_setup); +#endif + +/** + * Setup each TRA buffer for use + * + * @param tra Which TRA buffer to use (0-3) + * @param control TRA control setup + * @param filter Which events to log + * @param source_filter + * Source match + * @param dest_filter + * Destination match + * @param address Address compare + * @param address_mask + * Address mask + */ +void cvmx_tra_setup_v2(int tra, cvmx_tra_ctl_t control, cvmx_tra_filt_t filter, + cvmx_tra_sid_t source_filter, cvmx_tra_did_t dest_filter, + uint64_t address, uint64_t address_mask) +{ + cvmx_tra_filt_cmd_t filt_cmd; + cvmx_tra_filt_sid_t filt_sid; + cvmx_tra_filt_did_t filt_did; + + if ((tra + 1) > CVMX_L2C_TADS) + { + cvmx_dprintf("cvmx_tra_setup_per_tra: Invalid tra(%d), max allowed (%d)\n", tra, CVMX_L2C_TADS - 1); + tra = 0; + } + + filt_cmd.u64 = __cvmx_tra_set_filter_cmd_mask(filter); + filt_sid.u64 = source_filter & CVMX_TRA_SOURCE_MASK; + filt_did.u64 = dest_filter & CVMX_TRA_DESTINATION_MASK; + + /* Address filtering does not work when IOBDMA filter command is enabled + because of some caveats. Disable the IOBDMA filter command. */ + if ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) + && ((filt_cmd.u64 & CVMX_TRA_FILT_IOBDMA) == CVMX_TRA_FILT_IOBDMA) + && address_mask != 0) + { + cvmx_dprintf("The address-based filtering does not work with IOBDMAs, disabling the filter command.\n"); + filt_cmd.u64 &= ~(CVMX_TRA_FILT_IOBDMA); + } + + /* In OcteonII pass2, the mode bit is added to enable reading the trace + buffer data from different registers for lower and upper 64-bit value. + This bit is reserved in other Octeon models. */ + control.s.rdat_md = 1; + + cvmx_write_csr(CVMX_TRAX_CTL(tra), control.u64); + cvmx_write_csr(CVMX_TRAX_FILT_CMD(tra), filt_cmd.u64); + cvmx_write_csr(CVMX_TRAX_FILT_SID(tra), filt_sid.u64); + cvmx_write_csr(CVMX_TRAX_FILT_DID(tra), filt_did.u64); + cvmx_write_csr(CVMX_TRAX_FILT_ADR_ADR(tra), address); + cvmx_write_csr(CVMX_TRAX_FILT_ADR_MSK(tra), address_mask); +} +#ifdef CVMX_BUILD_FOR_LINUX_KERNEL +EXPORT_SYMBOL(cvmx_tra_setup_v2); +#endif + +/** + * Setup a TRA trigger. How the triggers are used should be + * setup using cvmx_tra_setup. + * + * @param trigger Trigger to setup (0 or 1) + * @param filter Which types of events to trigger on + * @param source_filter + * Source trigger match + * @param dest_filter + * Destination trigger match + * @param address Trigger address compare + * @param address_mask + * Trigger address mask + */ +void cvmx_tra_trig_setup(uint64_t trigger, cvmx_tra_filt_t filter, + cvmx_tra_sid_t source_filter, cvmx_tra_did_t dest_filter, + uint64_t address, uint64_t address_mask) +{ + cvmx_tra_filt_cmd_t tra_filt_cmd; + cvmx_tra_filt_sid_t tra_filt_sid; + cvmx_tra_filt_did_t tra_filt_did; + int tad; + + tra_filt_cmd.u64 = __cvmx_tra_set_filter_cmd_mask(filter); + tra_filt_sid.u64 = source_filter & CVMX_TRA_SOURCE_MASK; + tra_filt_did.u64 = dest_filter & CVMX_TRA_DESTINATION_MASK; + + /* Address filtering does not work when IOBDMA filter command is enabled + because of some caveats. Disable the IOBDMA filter command. */ + if ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) + && ((tra_filt_cmd.u64 & CVMX_TRA_FILT_IOBDMA) == CVMX_TRA_FILT_IOBDMA) + && address_mask != 0) + { + cvmx_dprintf("The address-based filtering does not work with IOBDMAs, disabling the filter command.\n"); + tra_filt_cmd.u64 &= ~(CVMX_TRA_FILT_IOBDMA); + } + + for (tad = 0; tad < CVMX_L2C_TADS; tad++) + { + cvmx_write_csr(CVMX_TRAX_TRIG0_CMD(tad) + trigger * 64, tra_filt_cmd.u64); + cvmx_write_csr(CVMX_TRAX_TRIG0_SID(tad) + trigger * 64, tra_filt_sid.u64); + cvmx_write_csr(CVMX_TRAX_TRIG0_DID(tad) + trigger * 64, tra_filt_did.u64); + cvmx_write_csr(CVMX_TRAX_TRIG0_ADR_ADR(tad) + trigger * 64, address); + cvmx_write_csr(CVMX_TRAX_TRIG0_ADR_MSK(tad) + trigger * 64, address_mask); + } +} +#ifdef CVMX_BUILD_FOR_LINUX_KERNEL +EXPORT_SYMBOL(cvmx_tra_trig_setup); +#endif + +/** + * Setup each TRA trigger. How the triggers are used should be + * setup using cvmx_tra_setup. + * + * @param tra Which TRA buffer to use (0-3) + * @param trigger Trigger to setup (0 or 1) + * @param filter Which types of events to trigger on + * @param source_filter + * Source trigger match + * @param dest_filter + * Destination trigger match + * @param address Trigger address compare + * @param address_mask + * Trigger address mask + */ +void cvmx_tra_trig_setup_v2(int tra, uint64_t trigger, cvmx_tra_filt_t filter, + cvmx_tra_sid_t source_filter, cvmx_tra_did_t dest_filter, + uint64_t address, uint64_t address_mask) +{ + cvmx_tra_filt_cmd_t tra_filt_cmd; + cvmx_tra_filt_sid_t tra_filt_sid; + cvmx_tra_filt_did_t tra_filt_did; + + tra_filt_cmd.u64 = __cvmx_tra_set_filter_cmd_mask(filter); + tra_filt_sid.u64 = source_filter & CVMX_TRA_SOURCE_MASK; + tra_filt_did.u64 = dest_filter & CVMX_TRA_DESTINATION_MASK; + + /* Address filtering does not work when IOBDMA filter command is enabled + because of some caveats. Disable the IOBDMA filter command. */ + if ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) + && ((tra_filt_cmd.u64 & CVMX_TRA_FILT_IOBDMA) == CVMX_TRA_FILT_IOBDMA) + && address_mask != 0) + { + cvmx_dprintf("The address-based filtering does not work with IOBDMAs, disabling the filter command.\n"); + tra_filt_cmd.u64 &= ~(CVMX_TRA_FILT_IOBDMA); + } + + cvmx_write_csr(CVMX_TRAX_TRIG0_CMD(tra) + trigger * 64, tra_filt_cmd.u64); + cvmx_write_csr(CVMX_TRAX_TRIG0_SID(tra) + trigger * 64, tra_filt_sid.u64); + cvmx_write_csr(CVMX_TRAX_TRIG0_DID(tra) + trigger * 64, tra_filt_did.u64); + cvmx_write_csr(CVMX_TRAX_TRIG0_ADR_ADR(tra) + trigger * 64, address); + cvmx_write_csr(CVMX_TRAX_TRIG0_ADR_MSK(tra) + trigger * 64, address_mask); +} +#ifdef CVMX_BUILD_FOR_LINUX_KERNEL +EXPORT_SYMBOL(cvmx_tra_trig_setup_v2); +#endif + +/** + * Read an entry from the TRA buffer + * + * @return Value return. High bit will be zero if there wasn't any data + */ +cvmx_tra_data_t cvmx_tra_read(void) +{ + uint64_t address = CVMX_TRA_READ_DAT; + cvmx_tra_data_t result; + + /* The trace buffer format is wider than 64-bits in OcteonII model, + read the register again to get the second part of the data. */ + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) + { + /* These reads need to be as close as possible to each other */ + result.u128.data = cvmx_read_csr(address); + result.u128.datahi = cvmx_read_csr(address); + } + else if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) && !OCTEON_IS_MODEL(OCTEON_CN5XXX)) + { + /* OcteonII pass2 uses different trace buffer data register for reading + lower and upper 64-bit values */ + result.u128.data = cvmx_read_csr(address); + result.u128.datahi = cvmx_read_csr(CVMX_TRA_READ_DAT_HI); + } + else + { + result.u128.data = cvmx_read_csr(address); + result.u128.datahi = 0; + } + + return result; +} + +/** + * Read an entry from the TRA buffer from a given TRA unit. + * + * @param tra_unit Trace buffer unit to read + * + * @return Value return. High bit will be zero if there wasn't any data + */ +cvmx_tra_data_t cvmx_tra_read_v2(int tra_unit) +{ + cvmx_tra_data_t result; + + result.u128.data = cvmx_read_csr(CVMX_TRAX_READ_DAT(tra_unit)); + result.u128.datahi = cvmx_read_csr(CVMX_TRAX_READ_DAT_HI(tra_unit)); + + return result; +} + +/** + * Decode a TRA entry into human readable output + * + * @param tra_ctl Trace control setup + * @param data Data to decode + */ +void cvmx_tra_decode_text(cvmx_tra_ctl_t tra_ctl, cvmx_tra_data_t data) +{ + if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) + { + /* The type is a five bit field for some entries and 4 for other. The four + bit entries can be mis-typed if the top is set */ + int type = data.cmn.type; + + if (type >= 0x1a) + type &= 0xf; + + switch (type) + { + case 0: /* DWB */ + case 1: /* PL2 */ + case 2: /* PSL1 */ + case 3: /* LDD */ + case 4: /* LDI */ + case 5: /* LDT */ + cvmx_dprintf("0x%016llx %c%+10d %s %s 0x%016llx\n", + (unsigned long long)data.u128.data, + (data.cmn.discontinuity) ? 'D' : ' ', + data.cmn.timestamp << (tra_ctl.s.time_grn*3), + TYPE_ARRAY[type], + SOURCE_ARRAY[data.cmn.source], + (unsigned long long)data.cmn.address); + break; + case 6: /* STF */ + case 7: /* STC */ + case 8: /* STP */ + case 9: /* STT */ + case 16: /* SAA */ + cvmx_dprintf("0x%016llx %c%+10d %s %s mask=0x%02x 0x%016llx\n", + (unsigned long long)data.u128.data, + (data.cmn.discontinuity) ? 'D' : ' ', + data.cmn.timestamp << (tra_ctl.s.time_grn*3), + TYPE_ARRAY[type], + SOURCE_ARRAY[data.store.source], + (unsigned int)data.store.mask, + (unsigned long long)data.store.address << 3); + break; + case 10: /* IOBLD8 */ + case 11: /* IOBLD16 */ + case 12: /* IOBLD32 */ + case 13: /* IOBLD64 */ + case 14: /* IOBST */ + cvmx_dprintf("0x%016llx %c%+10d %s %s->%s subdid=0x%x 0x%016llx\n", + (unsigned long long)data.u128.data, + (data.cmn.discontinuity) ? 'D' : ' ', + data.cmn.timestamp << (tra_ctl.s.time_grn*3), + TYPE_ARRAY[type], + SOURCE_ARRAY[data.iobld.source], + DEST_ARRAY[data.iobld.dest], + (unsigned int)data.iobld.subid, + (unsigned long long)data.iobld.address); + break; + case 15: /* IOBDMA */ + cvmx_dprintf("0x%016llx %c%+10d %s %s->%s len=0x%x 0x%016llx\n", + (unsigned long long)data.u128.data, + (data.cmn.discontinuity) ? 'D' : ' ', + data.cmn.timestamp << (tra_ctl.s.time_grn*3), + TYPE_ARRAY[type], + SOURCE_ARRAY[data.iob.source], + DEST_ARRAY[data.iob.dest], + (unsigned int)data.iob.mask, + (unsigned long long)data.iob.address << 3); + break; + default: + cvmx_dprintf("0x%016llx %c%+10d Unknown format\n", + (unsigned long long)data.u128.data, + (data.cmn.discontinuity) ? 'D' : ' ', + data.cmn.timestamp << (tra_ctl.s.time_grn*3)); + break; + } + } + else + { + int type; + int srcId; + + type = data.cmn2.type; + + switch (1ull<<type) + { + case CVMX_TRA_FILT_DECR64: + case CVMX_TRA_FILT_DECR32: + case CVMX_TRA_FILT_DECR16: + case CVMX_TRA_FILT_DECR8: + case CVMX_TRA_FILT_INCR64: + case CVMX_TRA_FILT_INCR32: + case CVMX_TRA_FILT_INCR16: + case CVMX_TRA_FILT_INCR8: + case CVMX_TRA_FILT_CLR64: + case CVMX_TRA_FILT_CLR32: + case CVMX_TRA_FILT_CLR16: + case CVMX_TRA_FILT_CLR8: + case CVMX_TRA_FILT_SET64: + case CVMX_TRA_FILT_SET32: + case CVMX_TRA_FILT_SET16: + case CVMX_TRA_FILT_SET8: + case CVMX_TRA_FILT_LCKL2: + case CVMX_TRA_FILT_WBIL2: + case CVMX_TRA_FILT_INVL2: + case CVMX_TRA_FILT_STGL2I: + case CVMX_TRA_FILT_LTGL2I: + case CVMX_TRA_FILT_WBIL2I: + case CVMX_TRA_FILT_WBL2: + case CVMX_TRA_FILT_DWB: + case CVMX_TRA_FILT_RPL2: + case CVMX_TRA_FILT_PL2: + case CVMX_TRA_FILT_LDI: + case CVMX_TRA_FILT_LDT: + /* CN68XX has 32 cores which are distributed to use different + trace buffers, decode the core that has data */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + { + if (data.cmn2.source <= 7) + { + srcId = _cvmx_tra_unit + (data.cmn2.source * 4); + if (srcId >= 16) + srcId += 16; + } + else + srcId = (data.cmn2.source); + } + else + srcId = (data.cmn2.source); + + cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s 0x%016llx%llx\n", + (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data, + (data.cmn2.discontinuity) ? 'D' : ' ', + data.cmn2.timestamp << (tra_ctl.s.time_grn*3), + TYPE_ARRAY2[type], + SOURCE_ARRAY[srcId], + (unsigned long long)data.cmn2.addresshi, + (unsigned long long)data.cmn2.addresslo); + break; + case CVMX_TRA_FILT_PSL1: + case CVMX_TRA_FILT_LDD: + case CVMX_TRA_FILT_FAS64: + case CVMX_TRA_FILT_FAS32: + case CVMX_TRA_FILT_FAA64: + case CVMX_TRA_FILT_FAA32: + case CVMX_TRA_FILT_SAA64: + case CVMX_TRA_FILT_SAA32: + case CVMX_TRA_FILT_STC: + case CVMX_TRA_FILT_STF: + case CVMX_TRA_FILT_STP: + case CVMX_TRA_FILT_STT: + case CVMX_TRA_FILT_STTIL1: + case CVMX_TRA_FILT_STFIL1: + /* CN68XX has 32 cores which are distributed to use different + trace buffers, decode the core that has data */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + { + if (data.store2.source <= 7) + { + srcId = _cvmx_tra_unit + (data.store2.source * 4); + if (srcId >= 16) + srcId += 16; + } + else + srcId = data.store2.source; + } + else + srcId = data.store2.source; + + cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s mask=0x%02x 0x%016llx%llx\n", + (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data, + (data.cmn2.discontinuity) ? 'D' : ' ', + data.cmn2.timestamp << (tra_ctl.s.time_grn*3), + TYPE_ARRAY2[type], + SOURCE_ARRAY[srcId], + (unsigned int)data.store2.mask, + (unsigned long long)data.store2.addresshi, + (unsigned long long)data.store2.addresslo); + break; + case CVMX_TRA_FILT_IOBST64: + case CVMX_TRA_FILT_IOBST32: + case CVMX_TRA_FILT_IOBST16: + case CVMX_TRA_FILT_IOBST8: + case CVMX_TRA_FILT_IOBLD64: + case CVMX_TRA_FILT_IOBLD32: + case CVMX_TRA_FILT_IOBLD16: + case CVMX_TRA_FILT_IOBLD8: + /* CN68XX has 32 cores which are distributed to use different + trace buffers, decode the core that has data */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + { + if (data.iobld2.source <= 7) + { + srcId = _cvmx_tra_unit + (data.iobld2.source * 4); + if (srcId >= 16) + srcId += 16; + } + else + srcId = data.iobld2.source; + } + else + srcId = data.iobld2.source; + + cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s->%s subdid=0x%x 0x%016llx%llx\n", + (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data, + (data.cmn2.discontinuity) ? 'D' : ' ', + data.cmn2.timestamp << (tra_ctl.s.time_grn*3), + TYPE_ARRAY2[type], + SOURCE_ARRAY[srcId], + DEST_ARRAY[data.iobld2.dest], + (unsigned int)data.iobld2.subid, + (unsigned long long)data.iobld2.addresshi, + (unsigned long long)data.iobld2.addresslo); + break; + case CVMX_TRA_FILT_IOBDMA: + /* CN68XX has 32 cores which are distributed to use different + trace buffers, decode the core that has data */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + { + if (data.iob2.source <= 7) + { + srcId = _cvmx_tra_unit + (data.iob2.source * 4); + if (srcId >= 16) + srcId += 16; + } + else + srcId = data.iob2.source; + } + else + srcId = data.iob2.source; + + cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s->%s len=0x%x 0x%016llx%llx\n", + (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data, + (data.iob2.discontinuity) ? 'D' : ' ', + data.iob2.timestamp << (tra_ctl.s.time_grn*3), + TYPE_ARRAY2[type], + SOURCE_ARRAY[srcId], + DEST_ARRAY[data.iob2.dest], + (unsigned int)data.iob2.mask, + (unsigned long long)data.iob2.addresshi << 3, + (unsigned long long)data.iob2.addresslo << 3); + break; + default: + cvmx_dprintf("0x%016llx%016llx %c%+10d Unknown format\n", + (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data, + (data.cmn2.discontinuity) ? 'D' : ' ', + data.cmn2.timestamp << (tra_ctl.s.time_grn*3)); + break; + } + } +} + +/** + * Display the entire trace buffer. It is advised that you + * disable the trace buffer before calling this routine + * otherwise it could infinitely loop displaying trace data + * that it created. + */ +void cvmx_tra_display(void) +{ + int valid = 0; + + /* Collect data from each TRA unit for decoding */ + if (CVMX_L2C_TADS > 1) + { + cvmx_trax_ctl_t tra_ctl; + cvmx_tra_data_t data[4]; + int tad; + do + { + valid = 0; + for (tad = 0; tad < CVMX_L2C_TADS; tad++) + data[tad] = cvmx_tra_read_v2(tad); + + for (tad = 0; tad < CVMX_L2C_TADS; tad++) + { + tra_ctl.u64 = cvmx_read_csr(CVMX_TRAX_CTL(tad)); + + if (data[tad].cmn2.valid) + { + _cvmx_tra_unit = tad; + cvmx_tra_decode_text(tra_ctl, data[tad]); + valid = 1; + } + } + } while (valid); + } + else + { + cvmx_tra_ctl_t tra_ctl; + cvmx_tra_data_t data; + + tra_ctl.u64 = cvmx_read_csr(CVMX_TRA_CTL); + + do + { + data = cvmx_tra_read(); + if ((OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) && data.cmn.valid) + valid = 1; + else if (data.cmn2.valid) + valid = 1; + else + valid = 0; + + if (valid) + cvmx_tra_decode_text(tra_ctl, data); + + } while (valid); + } +} +#ifdef CVMX_BUILD_FOR_LINUX_KERNEL +EXPORT_SYMBOL(cvmx_tra_display); +#endif + +/** + * Display the entire trace buffer. It is advised that you + * disable the trace buffer before calling this routine + * otherwise it could infinitely loop displaying trace data + * that it created. + * + * @param tra_unit Which TRA buffer to use. + */ +void cvmx_tra_display_v2(int tra_unit) +{ + int valid = 0; + + cvmx_trax_ctl_t tra_ctl; + cvmx_tra_data_t data; + + valid = 0; + tra_ctl.u64 = cvmx_read_csr(CVMX_TRAX_CTL(tra_unit)); + + do + { + data = cvmx_tra_read_v2(tra_unit); + if (data.cmn2.valid) + { + _cvmx_tra_unit = tra_unit; + cvmx_tra_decode_text(tra_ctl, data); + valid = 1; + } + } while (valid); +} +#ifdef CVMX_BUILD_FOR_LINUX_KERNEL +EXPORT_SYMBOL(cvmx_tra_display_v2); +#endif |