src/ppe/tools/ppetracepp/ppe2fsp.c
//convert a ppe trace buffer to an fsp trace buffer
convert a ppe trace buffer to an fsp trace buffer
convert a ppe trace buffer to an fsp trace buffer
int ppe2fsp(void* in, unsigned long in_size, void* out, unsigned long* io_size)
{
    PkTraceBuffer*              ptb = (PkTraceBuffer*)in;
    trace_buf_head_t*           ftb = (trace_buf_head_t*)out;
    uint32_t                    ppe_bytes_left;
    uint32_t                    fsp_bytes_left;
    int                         rc = 0;
    uint32_t                    ptb_offset;
    PkTraceEntryFooter*         ptb_te;
    uint64_t                    ppe_time64;
    uint32_t                    fte_size, pte_size;
    uint32_t                    fsp_te_count = 0;
    uint32_t                    time_diff32, prev_time32, new_time32;
    PkTraceGeneric*             pte_footer;
    largest_fsp_entry_t         fte;
    LargestPpeEntry             pte;
    uint64_t                    time_adj64;
    do
    {
        if(!ptb || !ftb || !io_size)
        {
            rc = P2F_NULL_POINTER;
            break;
        }
        if(ntohs(ptb->version) != PK_TRACE_VERSION)
        {
            rc = P2F_INVALID_VERSION;
            break;
        }
        if(in_size < (((uint32_t)(&ptb->cb[0])) - (uint32_t)(ptb)))
        {
            rc = P2F_INPUT_BUFFER_TOO_SMALL;
            break;
        }
        fsp_bytes_left = *io_size - sizeof(trace_buf_head_t);
        ppe_bytes_left = ntohs(ptb->size);
        ptb_offset = ntohl(ptb->state.offset);
        if(htonl(1) == 1)
        {
            time_adj64 = ptb->time_adj64;
        }
        else
        {
            time_adj64 = ntohl((uint32_t)(ptb->time_adj64 >> 32));
            time_adj64 |= ((uint64_t)(ntohl((uint32_t)(ptb->time_adj64 & 0x00000000ffffffff)))) << 32;
        }
        if((ppe_bytes_left - 1) & ppe_bytes_left)
        {
            rc = P2F_INVALID_INPUT_SIZE;
            break;
        }
        if(ptb_offset & 0x7)
        {
            rc = P2F_INVALID_PPE_OFFSET;
            break;
        }
        if(*io_size < sizeof(trace_buf_head_t))
        {
            rc = P2F_OUTPUT_BUFFER_TOO_SMALL;
            break;
        }
        ftb->ver = TRACE_BUF_VERSION;
        ftb->hdr_len = sizeof(trace_buf_head_t);
        ftb->time_flg = TRAC_TIME_REAL;
        ftb->endian_flg = 'B'; 
        memcpy(ftb->comp, ptb->image_str, sizeof(ftb->comp));
        ftb->times_wrap = htonl(1);
        ftb->size = htonl(sizeof(trace_buf_head_t) + sizeof(uint32_t));
        ftb->next_free = htonl(sizeof(trace_buf_head_t));
        ftb->extracted = htonl(0);
        ftb->te_count = htonl(0);
        ppe_time64 = ((uint64_t)(ntohl(ptb->state.tbu32) & 0xefffffff)) << 32;
        pte_size = ppe_get_entry(ptb, ptb_offset, &pte);
        prev_time32 = PK_GET_TRACE_TIME(pte.footer.generic.time_format.word32);
        ppe_time64 |= prev_time32;
        while(1)
        {
            if(ppe_bytes_left < sizeof(PkTraceEntryFooter))
            {
                break;
            }
            pte_size = ppe_get_entry(ptb, ptb_offset, &pte);
            if(!pte_size)
            {
                break;
            }
            pte_footer = &pte.footer.generic;
            if(pte_size > ppe_bytes_left)
            {
                pte_footer->complete = 0;
                ppe_bytes_left = 0;
            }
            else
            {
                ppe_bytes_left -= pte_size;
                ptb_offset -= pte_size;
            }
            new_time32 = PK_GET_TRACE_TIME(pte_footer->time_format.word32);
            time_diff32 = prev_time32 - new_time32;
            if(time_diff32 > ntohl(ptb->max_time_change))
            {
                time_diff32 = new_time32 - prev_time32;
                ppe_time64 += time_diff32;
            }
            else
            {
                ppe_time64 -= time_diff32;
            }
            prev_time32 = new_time32;
            fte_size = pte2fte(ptb, &pte, pte_size, &fte, ppe_time64 + time_adj64);
            fsp_put_entry(ftb, &fte, fte_size, fsp_bytes_left);
            fsp_te_count++;
            if(fte_size >= fsp_bytes_left)
            {
                fsp_bytes_left = 0;
                ftb->times_wrap = htonl(1);
                break;
            }
            else
            {
                fsp_bytes_left -= fte_size;
            }
        }
        if(fsp_bytes_left)
        {
            char* dest = ((char*)ftb) + sizeof(trace_buf_head_t);
            char* src = dest + fsp_bytes_left;
            size_t data_size = *io_size - sizeof(trace_buf_head_t) - fsp_bytes_left;
            memmove(dest, src, data_size);
        }
        ftb->te_count = htonl(fsp_te_count);
        *io_size -= fsp_bytes_left;
        ftb->size = htonl(*io_size);
    }while(0);
    return rc;
}
int ppe2fsp ( void * in , unsigned long in_size , void * out , unsigned long * io_size ) { PkTraceBuffer * ptb = ( PkTraceBuffer * ) in ; trace_buf_head_t * ftb = ( trace_buf_head_t * ) out ; uint32_t ppe_bytes_left ; uint32_t fsp_bytes_left ; int rc = 0 ; uint32_t ptb_offset ; PkTraceEntryFooter * ptb_te ; uint64_t ppe_time64 ; uint32_t fte_size , pte_size ; uint32_t fsp_te_count = 0 ; uint32_t time_diff32 , prev_time32 , new_time32 ; PkTraceGeneric * pte_footer ; largest_fsp_entry_t fte ; LargestPpeEntry pte ; uint64_t time_adj64 ; do { if ( ! ptb || ! ftb || ! io_size ) { rc = P2F_NULL_POINTER ; break ; } if ( ntohs ( ptb -> version ) != PK_TRACE_VERSION ) { rc = P2F_INVALID_VERSION ; break ; } if ( in_size < ( ( ( uint32_t ) ( & ptb -> cb [ 0 ] ) ) - ( uint32_t ) ( ptb ) ) ) { rc = P2F_INPUT_BUFFER_TOO_SMALL ; break ; } fsp_bytes_left = * io_size - sizeof ( trace_buf_head_t ) ; ppe_bytes_left = ntohs ( ptb -> size ) ; ptb_offset = ntohl ( ptb -> state . offset ) ; if ( htonl ( 1 ) == 1 ) { time_adj64 = ptb -> time_adj64 ; } else { time_adj64 = ntohl ( ( uint32_t ) ( ptb -> time_adj64 >> 32 ) ) ; time_adj64 |= ( ( uint64_t ) ( ntohl ( ( uint32_t ) ( ptb -> time_adj64 & 0x00000000ffffffff ) ) ) ) << 32 ; } if ( ( ppe_bytes_left - 1 ) & ppe_bytes_left ) { rc = P2F_INVALID_INPUT_SIZE ; break ; } if ( ptb_offset & 0x7 ) { rc = P2F_INVALID_PPE_OFFSET ; break ; } if ( * io_size < sizeof ( trace_buf_head_t ) ) { rc = P2F_OUTPUT_BUFFER_TOO_SMALL ; break ; } ftb -> ver = TRACE_BUF_VERSION ; ftb -> hdr_len = sizeof ( trace_buf_head_t ) ; ftb -> time_flg = TRAC_TIME_REAL ; ftb -> endian_flg = ' ' ; memcpy ( ftb -> comp , ptb -> image_str , sizeof ( ftb -> comp ) ) ; ftb -> times_wrap = htonl ( 1 ) ; ftb -> size = htonl ( sizeof ( trace_buf_head_t ) + sizeof ( uint32_t ) ) ; ftb -> next_free = htonl ( sizeof ( trace_buf_head_t ) ) ; ftb -> extracted = htonl ( 0 ) ; ftb -> te_count = htonl ( 0 ) ; ppe_time64 = ( ( uint64_t ) ( ntohl ( ptb -> state . tbu32 ) & 0xefffffff ) ) << 32 ; pte_size = ppe_get_entry ( ptb , ptb_offset , & pte ) ; prev_time32 = PK_GET_TRACE_TIME ( pte . footer . generic . time_format . word32 ) ; ppe_time64 |= prev_time32 ; while ( 1 ) { if ( ppe_bytes_left < sizeof ( PkTraceEntryFooter ) ) { break ; } pte_size = ppe_get_entry ( ptb , ptb_offset , & pte ) ; if ( ! pte_size ) { break ; } pte_footer = & pte . footer . generic ; if ( pte_size > ppe_bytes_left ) { pte_footer -> complete = 0 ; ppe_bytes_left = 0 ; } else { ppe_bytes_left -= pte_size ; ptb_offset -= pte_size ; } new_time32 = PK_GET_TRACE_TIME ( pte_footer -> time_format . word32 ) ; time_diff32 = prev_time32 - new_time32 ; if ( time_diff32 > ntohl ( ptb -> max_time_change ) ) { time_diff32 = new_time32 - prev_time32 ; ppe_time64 += time_diff32 ; } else { ppe_time64 -= time_diff32 ; } prev_time32 = new_time32 ; fte_size = pte2fte ( ptb , & pte , pte_size , & fte , ppe_time64 + time_adj64 ) ; fsp_put_entry ( ftb , & fte , fte_size , fsp_bytes_left ) ; fsp_te_count ++ ; if ( fte_size >= fsp_bytes_left ) { fsp_bytes_left = 0 ; ftb -> times_wrap = htonl ( 1 ) ; break ; } else { fsp_bytes_left -= fte_size ; } } if ( fsp_bytes_left ) { char * dest = ( ( char * ) ftb ) + sizeof ( trace_buf_head_t ) ; char * src = dest + fsp_bytes_left ; size_t data_size = * io_size - sizeof ( trace_buf_head_t ) - fsp_bytes_left ; memmove ( dest , src , data_size ) ; } ftb -> te_count = htonl ( fsp_te_count ) ; * io_size -= fsp_bytes_left ; ftb -> size = htonl ( * io_size ) ; } while ( 0 ) ; return rc ; }
convert a ppe trace buffer to an fsp trace buffer
convert a ppe trace buffer to an fsp trace buffer
//check that the input buffer is large enough to have a ppe trace buffer //initialize some locals //make sure the ppe buffer size is a power of two //size is not a power of two //The ppe bytes field should always be a multiple of 8 //make sure there is enough room for the fsp header //initialize the fsp header //big endian //find the latest timestamp so that we can work back from there //process all of the input bytes one trace entry at a time //from newest to oldest (backwards) until we run out of input bytes or //we run out of output space. //check if we have enough data for a ppe footer //get the next ppe entry //Stop if there are no more entries to retrieve from the ppe trace buffer //mark the entry as incomplete if we didn't have enough data //for the entire entry //Calculate the 64 bit timestamp for this entry.... //On PPE, getting the timestamp is not done atomically with writing //the entry to the buffer.  This means that an entry with an older //timestamp could possibly be added to the buffer after an entry //with a newer timestamp.  Detect this condition by checking if the //time difference is bigger than the max difference.  The max //difference is enforced by the PPE having a trace added on a //shorter time boundary (using a timer). //save off the lower 32bit timestamp for the next iteration //convert the ppe trace entry to an fsp trace entry //fit as much of the entry into the fsp trace buffer as possible //update the fsp trace entry count //stop if there is no more room left in the fsp trace buffer //while(1) //shift the trace data up if there is space to do so //update the fsp header to reflect the true size and entry count //inform the caller of how many bytes were actually used //shrink the size field to what we actually ended up using