summaryrefslogtreecommitdiffstats
path: root/sbe/tools/ppetracepp/ppe2fsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbe/tools/ppetracepp/ppe2fsp.c')
-rwxr-xr-xsbe/tools/ppetracepp/ppe2fsp.c532
1 files changed, 0 insertions, 532 deletions
diff --git a/sbe/tools/ppetracepp/ppe2fsp.c b/sbe/tools/ppetracepp/ppe2fsp.c
deleted file mode 100755
index 469ceced..00000000
--- a/sbe/tools/ppetracepp/ppe2fsp.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: sbe/tools/ppetracepp/ppe2fsp.c $ */
-/* */
-/* OpenPOWER sbe Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2016 */
-/* */
-/* */
-/* Licensed under the Apache License, Version 2.0 (the "License"); */
-/* you may not use this file except in compliance with the License. */
-/* You may obtain a copy of the License at */
-/* */
-/* http://www.apache.org/licenses/LICENSE-2.0 */
-/* */
-/* Unless required by applicable law or agreed to in writing, software */
-/* distributed under the License is distributed on an "AS IS" BASIS, */
-/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
-/* implied. See the License for the specific language governing */
-/* permissions and limitations under the License. */
-/* */
-/* IBM_PROLOG_END_TAG */
-#include "pk_trace.h"
-#include "ppe2fsp.h"
-#include "trac_interface.h"
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdint.h>
-
-#define TRACE_BUF_VERSION 0x01 /*!< Trace buffer version */
-#define TRACE_FIELDTRACE 0x4654 /*!< Field Trace - "FT" */
-#define TRACE_FIELDBIN 0x4644 /*!< Binary Field Trace - "FD" */
-
-#define TRAC_TIME_REAL 0 // upper 32 = seconds, lower 32 = nanoseconds
-#define TRAC_TIME_50MHZ 1
-#define TRAC_TIME_200MHZ 2
-#define TRAC_TIME_167MHZ 3 // 166666667Hz
-
-typedef struct
-{
- trace_entry_stamp_t stamp;
- trace_entry_head_t head;
- union
- {
- uint8_t data[PK_TRACE_MAX_BINARY + 1]; //add 1 byte for padding
- uint32_t parms[PK_TRACE_MAX_PARMS];
- };
- uint32_t size;
-}largest_fsp_entry_t;
-
-typedef struct
-{
- union
- {
- uint8_t binary_data[PK_TRACE_MAX_BINARY + 1];
- struct
- {
- uint8_t rsvd[(PK_TRACE_MAX_BINARY + 1) - (PK_TRACE_MAX_PARMS * sizeof(uint32_t))];
- uint32_t parms[PK_TRACE_MAX_PARMS];
- };
- };
- PkTraceEntryFooter footer;
-}LargestPpeEntry;
-
-//convert a ppe timestamp to an fsp trace timestamp
-uint64_t ppe2fsp_time(uint64_t ppe_time, uint32_t hz)
-{
- uint32_t seconds;
- uint32_t remainder;
- uint32_t nseconds;
-
- //convert from ppe ticks to seconds and nanoseconds
- seconds = ppe_time / hz;
- remainder = ppe_time - (((uint64_t)seconds) * hz);
- nseconds = (((uint64_t)remainder) * 1000000000) / hz;
- return (((uint64_t)seconds) << 32) | nseconds;
-}
-
-//Writes an fsp trace entry to the fsp trace buffer
-void fsp_put_entry(trace_buf_head_t* tb, largest_fsp_entry_t* fte, size_t entry_size, uint32_t bytes_left)
-{
- char* buffer = ((char*)tb) + sizeof(trace_buf_head_t);
- char* tb_start;
- char* fte_start;
- uint32_t copy_bytes;
-
- if(entry_size <= bytes_left)
- {
- tb_start = buffer + bytes_left - entry_size;
- fte_start = (char*)fte;
- copy_bytes = entry_size;
- }
- else
- {
- tb_start = buffer;
- fte_start = ((char*)fte) + (entry_size - bytes_left);
- copy_bytes = bytes_left;
- }
-
- memcpy(tb_start, fte_start, copy_bytes);
-}
-
-
-//convert a ppe trace entry to an fsp trace entry
-size_t pte2fte(PkTraceBuffer* ptb,
- LargestPpeEntry* pte,
- size_t pte_size,
- largest_fsp_entry_t* fte,
- uint64_t ppe_time64)
-{
- size_t entry_size;
- PkTraceGeneric* pte_footer = &pte->footer.generic;
- uint32_t format;
- uint32_t hash32;
- uint32_t hash32_partial;
- uint32_t* parm_start;
- uint32_t parm_bytes;
- uint64_t fsp_time64;
-
- //convert the ppe trace time to an fsp trace time
- fsp_time64 = ppe2fsp_time(ppe_time64, ntohl(ptb->hz));
-
- //fill in the 64 bit timestamp
- fte->stamp.tbh = htonl((uint32_t)(fsp_time64 >> 32));
- fte->stamp.tbl = htonl((uint32_t)(fsp_time64 & 0x00000000ffffffffull));
-
- //use the ppe instance id as the thread id.
- fte->stamp.tid = htonl((uint32_t)ntohs(ptb->instance_id));
-
- //merge the hash prefix and the string_id fields together for a 32 bit hash value
- hash32 = ((uint32_t)ntohs(ptb->hash_prefix)) << 16;
- hash32 |= pte_footer->string_id;
- fte->head.hash = htonl(hash32);
-
- //generate the 32bit hash value for a partial trace entry in case it's needed
- hash32_partial = ((uint32_t)ntohs(ptb->hash_prefix)) << 16;
- hash32_partial |= ntohs(ptb->partial_trace_hash);
-
- //set the line number to 1
- fte->head.line = htonl(1);
-
- //determine the FSP trace format
- format = PK_GET_TRACE_FORMAT(pte_footer->time_format.word32);
- if(format == PK_TRACE_FORMAT_BINARY)
- {
- fte->head.tag = htons(TRACE_FIELDBIN);
- }
- else
- {
- fte->head.tag = htons(TRACE_FIELDTRACE);
- }
-
- parm_start = (uint32_t*)(((char*)pte) + (sizeof(LargestPpeEntry) - pte_size));
-
- //fill in the parameters/binary data and size at the end
- switch(format)
- {
-
- case PK_TRACE_FORMAT_TINY:
- //one or 0 parameters
- entry_size = sizeof(trace_entry_stamp_t) +
- sizeof(trace_entry_head_t) +
- sizeof(uint32_t);
- fte->parms[0] = htonl((uint32_t)(pte_footer->parm16));
- fte->head.length = htons(sizeof(uint32_t));
- parm_bytes = 0;
- break;
-
- case PK_TRACE_FORMAT_BIG:
- //1 - 4 parameters
- //
- //If the trace entry data is incomplete (not all parm data
- //had been written at the time the trace was captured) then
- //we will write a trace to the fsp buffer that says
- //"PARTIAL TRACE ENTRY. HASH_ID = %d"
- if(pte_footer->complete)
- {
- parm_bytes = pte_footer->bytes_or_parms_count * sizeof(uint32_t);
- fte->head.length = htons(parm_bytes + sizeof(uint32_t));
- entry_size = sizeof(trace_entry_stamp_t) +
- sizeof(trace_entry_head_t) +
- parm_bytes + sizeof(uint32_t);
- }
- else
- {
- parm_bytes = 0;
- entry_size = sizeof(trace_entry_stamp_t) +
- sizeof(trace_entry_head_t) +
- sizeof(uint32_t);
- fte->parms[0] = fte->head.hash; //already corrected for endianess
- fte->head.hash = htonl(hash32_partial);
- fte->head.length = htons(sizeof(uint32_t));
- }
- break;
-
- case PK_TRACE_FORMAT_BINARY:
- //If the trace entry data is incomplete (not all parm data
- //had been written at the time the trace was captured) then
- //we will write a trace to the fsp buffer that says
- //"PARTIAL TRACE ENTRY. HASH_ID = %d"
- if(pte_footer->complete)
- {
- parm_bytes = pte_footer->bytes_or_parms_count;
- fte->head.length = htons((uint16_t)parm_bytes);
- entry_size = sizeof(trace_entry_stamp_t) +
- sizeof(trace_entry_head_t) +
- parm_bytes;
-
- //pad to 4 byte boundary
- entry_size = (entry_size + 3) & ~3;
- }
- else
- {
- parm_bytes = 0;
- entry_size = sizeof(trace_entry_stamp_t) +
- sizeof(trace_entry_head_t) +
- sizeof(uint32_t);
- fte->parms[0] = fte->head.hash;
- fte->head.hash = htonl(hash32_partial);
- fte->head.length = htons(sizeof(uint32_t));
- fte->head.tag = htons(TRACE_FIELDTRACE);
- }
- break;
-
-
- default:
- entry_size = 0;
- parm_bytes = 0;
- break;
- }
-
- //copy parameter bytes to the fsp entry if necessary
- if(parm_bytes)
- {
- memcpy(fte->data, parm_start, parm_bytes);
- }
-
- //add the entry size to the end
- if(entry_size)
- {
- uint32_t new_entry_size = entry_size + sizeof(uint32_t);
- *((uint32_t*)(((char*)fte) + entry_size)) = htonl(new_entry_size);
- entry_size = new_entry_size;
- }
-
- return entry_size;
-}
-
-//retrieve a ppe trace entry from a ppe trace buffer
-size_t ppe_get_entry(PkTraceBuffer* tb, uint32_t offset, LargestPpeEntry* pte)
-{
- uint32_t mask = ntohs(tb->size) - 1;
- PkTraceEntryFooter* footer;
- size_t entry_size;
- size_t parm_size;
- char* dest = (char*)pte;
- uint32_t format;
- uint32_t start_index;
- uint32_t bytes_left;
- uint32_t bytes_to_copy;
-
- //Find the footer in the circular buffer
- footer = (PkTraceEntryFooter*)(&tb->cb[(offset - sizeof(PkTraceEntryFooter)) & mask]);
-
- //always correct endianess for the time and string id words
- pte->footer.generic.time_format.word32 = ntohl(footer->generic.time_format.word32);
- pte->footer.generic.string_id = ntohs(footer->generic.string_id);
-
- //only need to byte swap the parm16 value if this is a tiny format
- pte->footer.generic.parm16 = footer->generic.parm16;
-
- //use footer data to determine the length of the binary data or parameters
- format = PK_GET_TRACE_FORMAT(pte->footer.generic.time_format.word32);
- switch(format)
- {
- case PK_TRACE_FORMAT_TINY:
- pte->footer.generic.parm16 = ntohs(pte->footer.generic.parm16);
- parm_size = 0;
- entry_size = sizeof(PkTraceEntryFooter);
- break;
-
- case PK_TRACE_FORMAT_BIG:
- parm_size = pte->footer.generic.bytes_or_parms_count * sizeof(uint32_t);
- entry_size = sizeof(PkTraceEntryFooter);
- break;
-
- case PK_TRACE_FORMAT_BINARY:
- parm_size = pte->footer.generic.bytes_or_parms_count;
- entry_size = sizeof(PkTraceEntryFooter);
- break;
-
- default:
- entry_size = 0;
- parm_size = 0;
- break;
- }
-
- //pad to 8 byte boundary
- parm_size = (parm_size + 7) & ~0x00000007ul;
-
- //add the parameter size to the total entry size
- entry_size += parm_size;
-
- //copy the entry from the circular buffer to pte
- start_index = (offset - entry_size) & mask;
- bytes_left = ntohs(tb->size) - start_index;
-
- //only copy up to the end of the circular buffer
- if(parm_size < bytes_left)
- {
- bytes_to_copy = parm_size;
- }
- else
- {
- bytes_to_copy = bytes_left;
- }
-
- dest += sizeof(LargestPpeEntry) - entry_size;
- memcpy(dest, &tb->cb[start_index], bytes_to_copy);
-
- //now copy the rest of the data starting from the beginning of the
- //circular buffer.
- if(bytes_to_copy < parm_size)
- {
- memcpy(dest + bytes_to_copy, tb->cb, parm_size - bytes_to_copy);
- }
-
- //return the size of the entry
- return entry_size;
-}
-
-//convert a ppe trace buffer to an fsp trace buffer
-int ppe2fsp(void* in, size_t in_size, void* out, size_t* 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;
- 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;
- }
-
- //check that the input buffer is large enough to have a ppe trace buffer
- if(in_size < (((uintptr_t)(&ptb->cb[0])) - (uintptr_t)(ptb)))
- {
- rc = P2F_INPUT_BUFFER_TOO_SMALL;
- break;
- }
-
- //initialize some locals
- 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;
- }
-
- //make sure the ppe buffer size is a power of two
- if((ppe_bytes_left - 1) & ppe_bytes_left)
- {
- //size is not a power of two
- rc = P2F_INVALID_INPUT_SIZE;
- break;
- }
-
- //The ppe bytes field should always be a multiple of 8
- if(ptb_offset & 0x7)
- {
- rc = P2F_INVALID_PPE_OFFSET;
- break;
- }
-
- //make sure there is enough room for the fsp header
- if(*io_size < sizeof(trace_buf_head_t))
- {
- rc = P2F_OUTPUT_BUFFER_TOO_SMALL;
- break;
- }
-
-
- //initialize the fsp header
- ftb->ver = TRACE_BUF_VERSION;
- ftb->hdr_len = sizeof(trace_buf_head_t);
- ftb->time_flg = TRAC_TIME_REAL;
- ftb->endian_flg = 'B'; //big endian
- 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);
-
- //find the latest timestamp so that we can work back from there
- 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;
-
- //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.
- while(1)
- {
- //check if we have enough data for a ppe footer
- if(ppe_bytes_left < sizeof(PkTraceEntryFooter))
- {
- break;
- }
-
- //get the next ppe entry
- pte_size = ppe_get_entry(ptb, ptb_offset, &pte);
-
- //Stop if there are no more entries to retrieve from the ppe trace buffer
- if(!pte_size)
- {
- break;
- }
- pte_footer = &pte.footer.generic;
-
- //mark the entry as incomplete if we didn't have enough data
- //for the entire entry
- if(pte_size > ppe_bytes_left)
- {
- pte_footer->complete = 0;
- ppe_bytes_left = 0;
- }
- else
- {
- ppe_bytes_left -= pte_size;
- ptb_offset -= pte_size;
- }
-
- //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).
- 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;
- }
-
- //save off the lower 32bit timestamp for the next iteration
- prev_time32 = new_time32;
-
- //convert the ppe trace entry to an fsp trace entry
- fte_size = pte2fte(ptb, &pte, pte_size, &fte, ppe_time64 + time_adj64);
-
- //fit as much of the entry into the fsp trace buffer as possible
- fsp_put_entry(ftb, &fte, fte_size, fsp_bytes_left);
-
- //update the fsp trace entry count
- fsp_te_count++;
-
- //stop if there is no more room left in the fsp trace buffer
- if(fte_size >= fsp_bytes_left)
- {
- fsp_bytes_left = 0;
- ftb->times_wrap = htonl(1);
- break;
- }
- else
- {
- fsp_bytes_left -= fte_size;
- }
- }//while(1)
-
-
- //shift the trace data up if there is space to do so
- 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);
- }
-
- //update the fsp header to reflect the true size and entry count
- ftb->te_count = htonl(fsp_te_count);
-
- //inform the caller of how many bytes were actually used
- *io_size -= fsp_bytes_left;
-
- //shrink the size field to what we actually ended up using
- ftb->size = htonl(*io_size);
-
- }while(0);
-
- return rc;
-}
-
-
-
OpenPOWER on IntegriCloud