diff options
Diffstat (limited to 'src/usr/trace/trace.C')
| -rw-r--r-- | src/usr/trace/trace.C | 134 |
1 files changed, 110 insertions, 24 deletions
diff --git a/src/usr/trace/trace.C b/src/usr/trace/trace.C index e43c8661a..398f6c418 100644 --- a/src/usr/trace/trace.C +++ b/src/usr/trace/trace.C @@ -54,8 +54,7 @@ #include <assert.h> #include <trace/trace.H> - - +#include "tracedaemon.H" /******************************************************************************/ @@ -125,21 +124,24 @@ mixed_trace_info_t g_tracBinaryInfo[2]; struct vpo_con_trigger_t { - uint64_t trig; // bit0 = trigger signalling bit1:63 = trace buffer addr - uint64_t len; // length of trace buffer with valid trace data. + volatile uint64_t trig; // bit0 = trig signalling bit1:63 = trace buff addr + uint32_t len; // length of trace buffer with valid trace data. + uint32_t seq; }; struct vpo_cont_support_t { vpo_con_trigger_t triggers[2]; - uint64_t disable; // clear by VPO script to enable continous trace + uint64_t enable; // VPO script sets it to 2 + // SIMICS hap handler sets it to 0 + // Compiler sets it to 1 for Mbox }; -// This structure is monitored by VPO script. The disable variable is set -// at compile time to 1. The VPO script clears the disable variable at thei +// This structure is monitored by VPO script. The enable variable is set +// at compile time to 1. The VPO script set the enable variable at the // start to enable the continuous trace support for VPO. It then montiors the // trigger active bit of each buffer and take action. -vpo_cont_support_t g_cont_trace_trigger_info = { { { 0, 0 }, { 0, 0 } }, 1 }; +vpo_cont_support_t g_cont_trace_trigger_info = { { {0,0,0}, {0,0,0} }, 1 }; const uint64_t TRIGGER_ACTIVE_BIT = 0x8000000000000000; @@ -190,6 +192,10 @@ Trace::Trace() reinterpret_cast<uint64_t>(g_tracBinaryInfo[i].pBuffer); } + // if this code is running under simics, call the hap handler to set + // g_cont_trace_trigger_info.enable to 0. Otherwise, this will be noop + MAGIC_INSTRUCTION(MAGIC_CONTINUOUS_TRACE); + // tracBINARY buffer appending is always on. // TODO figure a way to control continuous trace on/off, perhaps // unregister the hap handler for it. @@ -197,6 +203,11 @@ Trace::Trace() // select buffer0 initially iv_CurBuf = 0; + // initialize seq number + iv_seqNum = 0; + + // Create the daemon. + iv_daemon = new TraceDaemon(); } /******************************************************************************/ @@ -204,7 +215,8 @@ Trace::Trace() /******************************************************************************/ Trace::~Trace() { - + // Delete the daemon. + delete iv_daemon; } @@ -344,23 +356,66 @@ void Trace::initValuesBuffer( trace_desc_t *o_buf, // ManageContTraceBuffers // This function manages the usage of the two ping-pong buffers for handling // the continuous trace support. +// +// 1) Under VPO/VBU (g_cont_trace_trigger_info.enable = 2) +// The handshake between Hostboot code and VPO/VBU script is shown belows +// _______________________ +// Trigger_Avtive ____/ \__________ +// _________________________ +// ScomReg_Active _______/ \______ +// +// Hostboot code (this function) sets Trigger_Active, then ScomReg_Active, +// VPO/VBU script detects ScomReg_Active active, off-load the trigger buffer, +// and clears Trigger_Active. Hostboot code detects a trigger-state buffer +// with Trigger_Active cleared, reset ScomReg_Active. Two-level trigger is +// desired. The ScomReg trigger allows VPO script to sample at no expense +// of simclocks, thus avoiding spending extra simclocks associated with the +// flushing of L2/L3 to read the memory trigger. +// +// 2) Under Simics with hap handler (g_cont_trace_trigger_info.enable = 0) +// The handshake between Hostboot code and the hap handler is shown belows +// _______________________ +// Trigger_Avtive ____/ \__________ +// +// Hostboot code (this function) sets Trigger_Active, then invokes the hap +// handler. The hap handler off-loads the trigger buffer, and clears the +// Trigger_Active. +// +// 3) Under Simics/HW with FSP mbox (g_cont_trace_trigger_info.enable = 1) +// _______________________ +// Trigger_Avtive ____/ \__________ +// +// Hostboot code (this function) sets Trigger_Active, then schedule a thread +// to use mbox DMA MSG to off-load the trigger buffer to FSP, and clears the +// Trigger_Active. +// /******************************************************************************/ void Trace::ManageContTraceBuffers(uint64_t i_cbRequired) { uint8_t l_AltBuf = (iv_CurBuf + 1) % 2; + bool needScomReset = false; // Reset TriggerActive if the buffer has been offloaded by VPO // script when running under VBU Awan environment - for (size_t i = 0; (!(g_cont_trace_trigger_info.disable)) && (i < 2); i++) + for (size_t i = 0; (g_cont_trace_trigger_info.enable > 1) && (i < 2); i++) { if ((g_tracBinaryInfo[i].TriggerActive != 0) && (!(g_cont_trace_trigger_info.triggers[i].trig & TRIGGER_ACTIVE_BIT))) { g_tracBinaryInfo[i].TriggerActive = 0; + needScomReset = true; } } + if (needScomReset) + { + msg_t* l_msg = msg_allocate(); + l_msg->type = TraceDaemon::UPDATE_SCRATCH_REG; + l_msg->data[0] = 0; + msg_send(iv_daemon->iv_msgQ, l_msg); + } + // we should never have the current buffer in the trigger state assert (g_tracBinaryInfo[iv_CurBuf].TriggerActive == 0); @@ -372,19 +427,38 @@ void Trace::ManageContTraceBuffers(uint64_t i_cbRequired) // current buffer entering trigger state g_tracBinaryInfo[iv_CurBuf].TriggerActive = 1; - if (!(g_cont_trace_trigger_info.disable)) + if (g_cont_trace_trigger_info.enable > 1) { + if (g_tracBinaryInfo[l_AltBuf].TriggerActive == 1) + { + // If the alternate buffer's trigger is active, wait for a + // chance to get offloaded before it is reused. + uint64_t l_wait = 0x100000; + while (g_cont_trace_trigger_info.triggers[l_AltBuf].trig & + TRIGGER_ACTIVE_BIT) + { + if (--l_wait == 0) + { + break; + } + } + // If alternate buffer has been offloaded, exit trigger state. + if (l_wait != 0) + { + g_tracBinaryInfo[l_AltBuf].TriggerActive = 0; + } + } + + g_cont_trace_trigger_info.triggers[iv_CurBuf].seq = iv_seqNum++; // Turn on the current buffer's trigger g_cont_trace_trigger_info.triggers[iv_CurBuf].trig |= TRIGGER_ACTIVE_BIT; - // If the alternate buffer's trigger is active and - // the buffer will now be reused, so reset the trigger - if (g_cont_trace_trigger_info.triggers[l_AltBuf].trig & - TRIGGER_ACTIVE_BIT) - { - g_cont_trace_trigger_info.triggers[l_AltBuf].trig &= - ~TRIGGER_ACTIVE_BIT; - } + + msg_t* l_msg = msg_allocate(); + l_msg->type = TraceDaemon::UPDATE_SCRATCH_REG; + l_msg->data[0] = 0x13579BDF00000000; + l_msg->data[0] += (iv_seqNum * 0x100000000); + msg_send(iv_daemon->iv_msgQ, l_msg); } // If the alternate buffer is in trigger state, move it out of @@ -395,9 +469,23 @@ void Trace::ManageContTraceBuffers(uint64_t i_cbRequired) g_tracBinaryInfo[l_AltBuf].TriggerActive = 0; } // Now switching to alternate buffer and reset the usage count + uint8_t l_cur = iv_CurBuf; + uint64_t l_len = g_tracBinaryInfo[l_cur].cbUsed; iv_CurBuf = l_AltBuf; g_tracBinaryInfo[iv_CurBuf].cbUsed = 1; + // For FSP mbox method. + if (g_cont_trace_trigger_info.enable == 1) + { + msg_t* l_msg = msg_allocate(); + l_msg->type = TraceDaemon::SEND_TRACE_BUFFER; + l_msg->data[1] = TRAC_BINARY_SIZE; + l_msg->extra_data = malloc(TRAC_BINARY_SIZE); + memcpy( l_msg->extra_data, g_tracBinaryInfo[l_cur].pBuffer, l_len ); + msg_send(iv_daemon->iv_msgQ, l_msg); + g_tracBinaryInfo[l_cur].TriggerActive = 0; + } + MAGIC_INSTRUCTION(MAGIC_CONTINUOUS_TRACE); } } @@ -462,8 +550,7 @@ void Trace::_trace_adal_write_all(trace_desc_t *io_td, // Sum the sizes of the items in i_args in order to know how big to // allocate the entry. - const size_t fmt_len = strlen(_fmt); - for (size_t i = 0; i <= fmt_len; i++) + for (size_t i = 0; i <= strlen(_fmt); i++) { if ('%' == _fmt[i]) { @@ -693,7 +780,7 @@ void Trace::_trace_adal_write_all(trace_desc_t *io_td, g_tracBinaryInfo[iv_CurBuf].cbUsed += l_cbRequired; // maintain the buffer's actually used bytes for VPO script - if ((!g_cont_trace_trigger_info.disable)) + if (g_cont_trace_trigger_info.enable > 1) { g_cont_trace_trigger_info.triggers[iv_CurBuf].len = g_tracBinaryInfo[iv_CurBuf].cbUsed; @@ -847,7 +934,7 @@ void Trace::_trace_adal_write_bin(trace_desc_t *io_td,const trace_hash_val i_has g_tracBinaryInfo[iv_CurBuf].cbUsed += l_cbRequired; // maintain the buffer's actually used bytes for VPO script - if ((!g_cont_trace_trigger_info.disable)) + if (g_cont_trace_trigger_info.enable > 1) { g_cont_trace_trigger_info.triggers[iv_CurBuf].len = g_tracBinaryInfo[iv_CurBuf].cbUsed; @@ -1390,7 +1477,6 @@ void Trace::clearAllBuffers() - #if 0 /******************************************************************************/ // resetBuf - TODO |

