summaryrefslogtreecommitdiffstats
path: root/src/usr/trace/trace.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/trace/trace.C')
-rw-r--r--src/usr/trace/trace.C134
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
OpenPOWER on IntegriCloud