/***********************license start*************** * Copyright (c) 2003-2008 Cavium Networks (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 Networks nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" * AND WITH ALL FAULTS AND CAVIUM NETWORKS 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. * * * For any questions regarding licensing please contact marketing@caviumnetworks.com * ***********************license end**************************************/ /** * @file * * Interface to the Trace buffer hardware. * *
$Revision: 30644 $
*/ #include "cvmx.h" #include "cvmx-tra.h" 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 *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" }; static const char *DEST_ARRAY[] = { "CIU/GPIO", "RSVD1", "RSVD2", "PCI/PCIe", "KEY", "FPA", "DFA", "ZIP", "RNG", "IPD", "PKO", "RSVD11", "POW", "RSVD13", "RSVD14", "RSVD15", "RSVD16", "RSVD17", "RSVD18", "RSVD19", "RSVD20", "RSVD21", "RSVD22", "RSVD23", "RSVD24", "RSVD25", "RSVD26", "RSVD27", "RSVD28", "RSVD29", "RSVD30", "RSVD31" }; /** * 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_cmd_t filter, cvmx_tra_filt_sid_t source_filter, cvmx_tra_filt_did_t dest_filter, uint64_t address, uint64_t address_mask) { cvmx_write_csr(CVMX_TRA_CTL, control.u64); cvmx_write_csr(CVMX_TRA_FILT_CMD, filter.u64); cvmx_write_csr(CVMX_TRA_FILT_SID, source_filter.u64); cvmx_write_csr(CVMX_TRA_FILT_DID, dest_filter.u64); cvmx_write_csr(CVMX_TRA_FILT_ADR_ADR, address); cvmx_write_csr(CVMX_TRA_FILT_ADR_MSK, address_mask); } /** * 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_cmd_t filter, cvmx_tra_filt_sid_t source_filter, cvmx_tra_trig0_did_t dest_filter, uint64_t address, uint64_t address_mask) { cvmx_write_csr(CVMX_TRA_TRIG0_CMD + trigger * 64, filter.u64); cvmx_write_csr(CVMX_TRA_TRIG0_SID + trigger * 64, source_filter.u64); cvmx_write_csr(CVMX_TRA_TRIG0_DID + trigger * 64, dest_filter.u64); cvmx_write_csr(CVMX_TRA_TRIG0_ADR_ADR + trigger * 64, address); cvmx_write_csr(CVMX_TRA_TRIG0_ADR_MSK + trigger * 64, address_mask); } /** * 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) { cvmx_tra_data_t result; result.u64 = cvmx_read_csr(CVMX_TRA_READ_DAT); 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) { /* 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 CVMX_TRA_DATA_DWB: case CVMX_TRA_DATA_PL2: case CVMX_TRA_DATA_PSL1: case CVMX_TRA_DATA_LDD: case CVMX_TRA_DATA_LDI: case CVMX_TRA_DATA_LDT: cvmx_dprintf("0x%016llx %c%+10d %s %s 0x%016llx\n", (unsigned long long)data.u64, (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 CVMX_TRA_DATA_STC: case CVMX_TRA_DATA_STF: case CVMX_TRA_DATA_STP: case CVMX_TRA_DATA_STT: case CVMX_TRA_DATA_SAA: cvmx_dprintf("0x%016llx %c%+10d %s %s mask=0x%02x 0x%016llx\n", (unsigned long long)data.u64, (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 CVMX_TRA_DATA_IOBLD8: case CVMX_TRA_DATA_IOBLD16: case CVMX_TRA_DATA_IOBLD32: case CVMX_TRA_DATA_IOBLD64: case CVMX_TRA_DATA_IOBST: cvmx_dprintf("0x%016llx %c%+10d %s %s->%s subdid=0x%x 0x%016llx\n", (unsigned long long)data.u64, (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 CVMX_TRA_DATA_IOBDMA: cvmx_dprintf("0x%016llx %c%+10d %s %s->%s len=0x%x 0x%016llx\n", (unsigned long long)data.u64, (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.u64, (data.cmn.discontinuity) ? 'D' : ' ', data.cmn.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) { 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 (data.cmn.valid) cvmx_tra_decode_text(tra_ctl, data); } while (data.cmn.valid); }