diff options
Diffstat (limited to 'src/usr/trace')
-rw-r--r-- | src/usr/trace/bufferpage.C | 4 | ||||
-rw-r--r-- | src/usr/trace/daemon/daemon.C | 3 | ||||
-rw-r--r-- | src/usr/trace/runtime/rt_rsvdtracebuffer.C | 154 | ||||
-rw-r--r-- | src/usr/trace/runtime/rt_rsvdtracebuffer.H | 79 | ||||
-rw-r--r-- | src/usr/trace/runtime/rt_rsvdtracebufservice.C | 8 | ||||
-rw-r--r-- | src/usr/trace/runtime/test/testrsvdtracebuf.H | 270 | ||||
-rw-r--r-- | src/usr/trace/service.C | 3 |
7 files changed, 414 insertions, 107 deletions
diff --git a/src/usr/trace/bufferpage.C b/src/usr/trace/bufferpage.C index c6cfb57e0..27feb9bd7 100644 --- a/src/usr/trace/bufferpage.C +++ b/src/usr/trace/bufferpage.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2017 */ +/* Contributors Listed Below - COPYRIGHT 2012,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -41,7 +41,7 @@ namespace TRACE uint64_t l_usedSize = this->usedSize; // Verify there is enough space. - while ((usedSize + i_size) < (PAGESIZE - sizeof(BufferPage))) + while ((l_usedSize + i_size) < (PAGESIZE - sizeof(BufferPage))) { // Atomically attempt to claim i_size worth. uint64_t newSize = l_usedSize + i_size; diff --git a/src/usr/trace/daemon/daemon.C b/src/usr/trace/daemon/daemon.C index a70ad2997..dffe118b8 100644 --- a/src/usr/trace/daemon/daemon.C +++ b/src/usr/trace/daemon/daemon.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2018 */ +/* Contributors Listed Below - COPYRIGHT 2012,2019 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -47,7 +47,6 @@ #include <devicefw/userif.H> #include <mbox/mboxif.H> -#include <config.h> #include <console/consoleif.H> #include <util/utilmbox_scratch.H> #include <debugpointers.H> diff --git a/src/usr/trace/runtime/rt_rsvdtracebuffer.C b/src/usr/trace/runtime/rt_rsvdtracebuffer.C index b9d21b774..175850ff8 100644 --- a/src/usr/trace/runtime/rt_rsvdtracebuffer.C +++ b/src/usr/trace/runtime/rt_rsvdtracebuffer.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017,2018 */ +/* Contributors Listed Below - COPYRIGHT 2017,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -28,6 +28,18 @@ namespace TRACE { + +/// Some constants to help keep track of the structure of the buffer +/// Have these build on each other +// A pointer of where the reserved memory points to itself. Helps to determine +// if the buffer has been relocated +const uint32_t RESERVED_MEMORY_POINTER_OFFSET = 0; +// The location of the buffer for Entries. +const uint32_t BUFFER_BEGINNINIG_BOUNDARY_OFFSET = + sizeof(uintptr_t) + RESERVED_MEMORY_POINTER_OFFSET; +// Minimum size of the buffer, based on the buffers needs to be functional +const uint32_t MINIMUM_SIZE_OF_BUFFER_IN_BYTES = + BUFFER_BEGINNINIG_BOUNDARY_OFFSET; /** * ctor */ @@ -48,17 +60,27 @@ void RsvdTraceBuffer::init(uint32_t i_bufferSize, uintptr_t i_addressToBuffer, uintptr_t* i_addressToHead) { - // If buffer is not already initilaized and incoming data is legit + // If buffer is not already initialized and incoming data is legit if ( (false == isBufferValid()) && - (i_bufferSize > 0 ) && + (i_bufferSize > MINIMUM_SIZE_OF_BUFFER_IN_BYTES ) && (i_addressToBuffer > 0) && (nullptr != i_addressToHead) ) { - setBeginningBoundary(convertToCharPointer(i_addressToBuffer)); - setEndingBoundary(convertToCharPointer(i_addressToBuffer + - i_bufferSize - 1)); + // Set the list head pointer. This needs to be set first. setListHeadPtr(i_addressToHead); + // Set the reserved memory pointer + iv_ptrToRsvdMem = reinterpret_cast<uintptr_t*> + (i_addressToBuffer + RESERVED_MEMORY_POINTER_OFFSET); + + setBeginningBoundary(convertToCharPointer + (i_addressToBuffer + BUFFER_BEGINNINIG_BOUNDARY_OFFSET)); + setEndingBoundary(convertToCharPointer + (i_addressToBuffer + i_bufferSize - 1)); + + // Check if buffer has moved and if so, realign the pointers + checkBuffer(); + // Now that there is an actual/real buffer to point to, the buffer is // valid, although it may/may not have any entries associated with it. setBufferValidity(true); @@ -66,6 +88,60 @@ void RsvdTraceBuffer::init(uint32_t i_bufferSize, } /** + * checkBuffer + */ +void RsvdTraceBuffer::checkBuffer() +{ + intptr_t l_offset(0); + + // If the reserved memory data is not zero, meaning that buffer is being + // revisited again, and the memory does not match the current pointer of + // the reserved memory data, then the buffer has been relocated and the + // pointer info in the buffer needs to be realigned/corrected. + // The buffer gets revisited to pull data when a crash happens. Please + // see the details section for the class in the .H file. + if ((0 != iv_ptrToRsvdMem[0]) && + (reinterpret_cast<uintptr_t>(iv_ptrToRsvdMem) != iv_ptrToRsvdMem[0])) + { + // Get the difference in memory location + l_offset = reinterpret_cast<uintptr_t> + (iv_ptrToRsvdMem) - iv_ptrToRsvdMem[0]; + + realignListPointers(l_offset); + } + + // Persist the current buffer location + iv_ptrToRsvdMem[0] = reinterpret_cast<uintptr_t>(iv_ptrToRsvdMem); +} + +/** + * realignListPointers + */ +void RsvdTraceBuffer::realignListPointers(intptr_t l_offset) +{ + // Verify that there is actual data to realign + Entry* l_head = getListHead(); + if (l_head) + { + // Update the pointer to the list + *iv_ptrToHead = *iv_ptrToHead + l_offset; + + // Get the the head of list to traverse over and correct pointers + Entry* l_entry = l_head = getListHead(); + do + { + // Update the pointers of Entry item + l_entry->next = reinterpret_cast<Entry *>( + reinterpret_cast<uintptr_t>(l_entry->next) + l_offset); + l_entry->prev = reinterpret_cast<Entry *>( + reinterpret_cast<uintptr_t>(l_entry->prev) + l_offset); + + l_entry = l_entry->next; + } while (l_entry != l_head); + } +} + +/** * insertEntry */ Entry* RsvdTraceBuffer::insertEntry(uint32_t i_dataSize) @@ -83,9 +159,11 @@ Entry* RsvdTraceBuffer::insertEntry(uint32_t i_dataSize) // (Alignment is needed so that Entry's members can be atomically // updated). uint32_t l_entrySize = getAlignedSizeOfEntry(i_dataSize); - if (makeSpaceForEntry(l_entrySize, l_availableAddress) && l_availableAddress) + if (makeSpaceForEntry(l_entrySize, l_availableAddress) && + l_availableAddress) { - // Set entry if space was created and an avilable address is returned + // Set entry if space was created and an available address + // is returned l_entry = reinterpret_cast<Entry*>(l_availableAddress); setListTail(l_entry); @@ -104,7 +182,8 @@ uint32_t RsvdTraceBuffer::makeSpaceForEntry(uint32_t i_spaceNeeded, o_availableAddress = nullptr; uint32_t l_spaceAvailable = 0; - // Only look for space if requested space is less or equal to buffer size + // Only look for space if requested space is less than + // or equal to buffer size if (i_spaceNeeded <= getBufferSize()) { l_spaceAvailable = getAvailableSpace(i_spaceNeeded, o_availableAddress); @@ -112,7 +191,7 @@ uint32_t RsvdTraceBuffer::makeSpaceForEntry(uint32_t i_spaceNeeded, // Keep requesting for space until we get the space that is asked for while (l_spaceAvailable < i_spaceNeeded) { - // If we can't remove any entries, then we exhausted all efforts + // If we can't remove any entries, then we exhausted all efforts. // Should not happen, because the space requested should be less // than or equal to buffer size if (!removeOldestEntry()) @@ -167,7 +246,7 @@ uint32_t RsvdTraceBuffer::getAvailableSpace(uint32_t i_spaceNeeded, // space needed, then return that value else return the space // available at the beginning of the buffer. If the space at the // end does not have enough of the needed space, then space will - // ultimately be made at the beginning of the + // ultimately be made at the beginning of the buffer. // // Right now, you are probably thinking, what if I only need 5 free // spaces and if the end has 10 available and the beginning has 7 @@ -215,7 +294,7 @@ bool RsvdTraceBuffer::removeOldestEntry() if (!isListEmpty()) { // Get a handle to the head - Entry* l_head = getListHead(); + Entry* l_head(getListHead()); // Is there only one entry? if (l_head->next == l_head) @@ -252,12 +331,17 @@ uint32_t RsvdTraceBuffer::getTrace(void* o_data, uint32_t i_dataSize) const // Before continuing, make sure the buffer is valid if (isBufferValid()) { + // If caller passed in a nullptr for the data or zero for the data size, + // then that signals the user only wants to ascertain the size + // requirement to hold all the data associated with the entries. if ((nullptr == o_data) || (0 == i_dataSize)) { + // Caller wants to ascertain size requirements for data l_sizeOfBufferExtracted = getAggregateSizeOfEntries(); } else { + // Caller wants to collect data - enough data to fill data size l_sizeOfBufferExtracted = getTraceEntries(o_data, i_dataSize); } } @@ -273,7 +357,7 @@ uint32_t RsvdTraceBuffer::getAggregateSizeOfEntries() const uint32_t l_aggregatedSize(0); // Get a handle to the head - Entry* l_head = getListHead(); + Entry* l_head(getListHead()); // Make sure the list is not null if (l_head) @@ -283,8 +367,8 @@ uint32_t RsvdTraceBuffer::getAggregateSizeOfEntries() const { // Need to add to the size, the size of an uint32_t. The uint32_t // will hold the size of the data that is to be returned along - // with the returned data. This is why it is added. - l_aggregatedSize += l_entry->size + sizeof(uint32_t); + // with the returned data. + l_aggregatedSize += ALIGN_8(l_entry->size) + sizeof(uint32_t); l_entry = l_entry->next; } while (l_entry != l_head); } @@ -304,12 +388,12 @@ uint32_t RsvdTraceBuffer::getTraceEntries(void* o_data, uint32_t i_dataSize) con if ((nullptr != o_data) && (i_dataSize >= sizeof(trace_buf_head_t)) ) { + // Clear the outgoing data before populating it + memset(o_data, 0, i_dataSize); + // Get a useful "trace buffer head" handle to the data buffer passed in trace_buf_head_t* l_header =reinterpret_cast<trace_buf_head_t*>(o_data); - // Now that we have an easy handle to the data, let's clear it for now - memset(l_header, '\0', sizeof(trace_buf_head_t)); - // Now populate the trace buffer header with some useful info l_header->ver = TRACE_BUF_VERSION; l_header->hdr_len = l_header->size = sizeof(trace_buf_head_t); @@ -318,35 +402,42 @@ uint32_t RsvdTraceBuffer::getTraceEntries(void* o_data, uint32_t i_dataSize) con l_header->endian_flg = 'B'; // Big Endian. // Get a handle to the head - Entry* l_head = getListHead(); + Entry* l_head(getListHead()); // Extract the trace info from this class' internal buffer // If the list is not empty and have data then extract the trace info if (l_head) { - // Keep a tally of the size of the data that can be copied over - uint32_t l_totalSize(l_head->size); + // Keep a tally of the size of the data that can be copied over. + // Also account for the trace_buf_head_t that is at the beginning + // of buffer o_data. + uint32_t l_totalSize(sizeof(trace_buf_head_t)); // Keep a tally of the number of entries that can be extracted uint32_t l_entriesToExtract(0); // The entry size as data type uint32_t; for code up keep uint32_t l_entrySize(0); // Get a handle on the last entry on the list - Entry* l_entry = l_head->prev; + Entry* l_entry(l_head->prev); - // Calculate the number of entries that can be stuffed into data buffer - // starting with newest entry (tail) to oldest entry (head) + // Calculate the number of entries that can be stuffed into the data + // buffer - starting with newest entry (tail) to oldest entry (head) do { - // Calculate the size: add the size of the data, that will be - // copied over, plus the size of the type of the entry size, - // that will hold the size of the data being copied over. - if ((l_totalSize + l_entry->size + sizeof(l_entrySize)) <= i_dataSize) + // Calculate the size: add the size of the data (that will be + // copied over) plus the size of the type of the entry size + // (that will hold the size of the data being copied over). + if ((l_totalSize + ALIGN_8(l_entry->size) + sizeof(l_entrySize)) + <= i_dataSize) { - l_totalSize += l_entry->size + sizeof(l_entrySize); + l_totalSize += ALIGN_8(l_entry->size) + sizeof(l_entrySize); ++l_entriesToExtract; } else // Can't retrieve this entry; it breaks the size limitation { + // Although we are done here, we still need to point to + // the previous item. The continuation of this algorithm + // depends on it (expects to be one behind the needed data) + l_entry = l_entry->prev; break; } @@ -368,17 +459,18 @@ uint32_t RsvdTraceBuffer::getTraceEntries(void* o_data, uint32_t i_dataSize) con // Copy entry data. memcpy(&l_data[l_header->size], l_entry->data, l_entry->size); - l_header->size += l_entry->size; + l_header->size += ALIGN_8(l_entry->size); // Copy entry size. l_entrySize = l_entry->size + sizeof(l_entrySize); memcpy(&l_data[l_header->size], &l_entrySize, sizeof(l_entrySize)); l_header->size += sizeof(l_entrySize); + // increment/decrements our counters ++l_header->te_count; --l_entriesToExtract; } // end while (l_entriesToExtract) - } // end if (!isListEmpty()) + } // end if (l_head) // Update the size of the entries retrieved and the // next free memory location in header trace buffer diff --git a/src/usr/trace/runtime/rt_rsvdtracebuffer.H b/src/usr/trace/runtime/rt_rsvdtracebuffer.H index 24c9204cf..e804a41ed 100644 --- a/src/usr/trace/runtime/rt_rsvdtracebuffer.H +++ b/src/usr/trace/runtime/rt_rsvdtracebuffer.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2018 */ +/* Contributors Listed Below - COPYRIGHT 2012,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -43,9 +43,25 @@ namespace TRACE * * @brief Class to manage the Reserved Trace Buffer * - * This is a utility class to manage the buffer - looking for space - * for an entry, adding entries and removing entries. - * + * @details This is a utility class to manage the buffer - looking + * for space for an entry, adding entries and removing entries. + * When a system crashes, this buffer will persist the last + * few traces. When HB is IPLed again, the persisted data + * will be retrieved for inspection. + * With PHYP, the buffer will be retrieved at the same memory + * location as before the crash. With OPAL, the buffer may be + * relocated to a different location and all the pointers within + * the buffer will be invalid. If the buffer does get relocated, + * this class will correct the pointers. + * To correct the pointers, a section at the beginning of the + * persisted buffer is reserved to save the address of the buffer. + * Such that when the buffer is retrieved after a crash, if that + * data does not match the current buffer address, then we can + * conclude it has been relocated and the pointers in the buffer + * need to be updated/corrected. + * If the data at the beginning of the buffer is 0, then this is + * first time this buffer is being used and therefore no need to + * correct pointers. */ class RsvdTraceBuffer { @@ -61,7 +77,7 @@ namespace TRACE * * @param[in] i_addressToBuffer - Where the buffer begins * - * @param[in] i_addressToHead - A pointer to a ponter to the first + * @param[in] i_addressToHead - A pointer to a pointer to the first * Entry, cannot be a nullptr */ void init(uint32_t i_bufferSize, @@ -89,12 +105,12 @@ namespace TRACE * If o_data is valid and the i_size is greater than * the size of trace_buf_head_t, then as many trace * entries will be returned in the o_data buffer that - * i_size will allow. + * i_size will allow, minus size of trace_buf_head_t. * - * @param[in] o_data - if not null, the buffer area to copy + * @param[out] o_data - if not null, the buffer area to copy * trace data into * - * @param[out] i_dataSize - if not 0, the size of the buffer area, + * @param[in] i_dataSize - if not 0, the size of the buffer area, * which dictates how many trace entries' * payload (or data the entry contains) * that can be copied @@ -123,7 +139,23 @@ namespace TRACE */ uint32_t getNumberOfEntries() const; + // Private methods private: + + /** @brief Checks the buffer to see if it has been relocated and if + * so, realign the pointers within the buffer. + */ + void checkBuffer(); + + + /** @brief When and if buffer has been relocated this method will + * realign the pointers within the buffer. + * + * @param[in] i_offset - the offset the buffer has moved + * within memory + */ + void realignListPointers(intptr_t i_offset); + /** @brief This function will find a contiguous piece of memory that * is large enough in size to accommodate the space needed. * If not enough free contiguous memory exists to accommodate @@ -147,7 +179,8 @@ namespace TRACE * requested is not larger in size to the buffer size, * then an available space will eventually be returned. * - * @param[in] i_spaceNeeded - @see insertEntry::i_dataSize above + * @param[in] i_spaceNeeded - The size of the contiguous piece + * of memory caller desires * * @param[out] o_availableAddress - A pointer to the contiguous * piece of memory found that satisfies the caller's @@ -160,8 +193,8 @@ namespace TRACE char* &o_availableAddress); /** @brief Returns a contiguous piece of memory that will satisfy - * the space that is needed if large enough space can be - * had, else returns the size of the largest contiguous + * the space that is needed if a large enough space can be + * found, else return the size of the largest contiguous * piece of memory. * * @algorithm There are three cases to consider: @@ -176,7 +209,7 @@ namespace TRACE * --------------------------------------------------------- * | < - 10 bytes -> | Head | .....| Tail | <- 20 bytes -> | * --------------------------------------------------------- - * scenario 1: Contigous space desired: 15 bytes + * scenario 1: Contiguous space desired: 15 bytes * Return the 20 bytes after the Tail * scenario 2: Contiguous space desired: 10 bytes * Return the 20 bytes after the Tail @@ -223,18 +256,21 @@ namespace TRACE * --------------------------------------------------------- * | .... | Tail | < - 30 bytes -> | Head | .... * --------------------------------------------------------- - * Case 1: Contigous space desired: 25 bytes + * Case 1: Contiguous space desired: 25 bytes * Return the 30 bytes between Tail and Head. - * Case 2: Contigous space desired: 40 bytes + * Case 2: Contiguous space desired: 40 bytes * Return the 30 bytes between Tail and Head. * - * @param[in] i_spaceNeeded - @see insertEntry::i_dataSize above + * @param[in] i_spaceNeeded - The size of the contiguous piece + * of memory caller desires * - * @param[out] o_availableAddress - @see makeSpaceForEntry above + * @param[out] o_availableAddress - A pointer to the biggest + * piece of contiguous memory found. May or may + * not satisfy i_spaceNeeded. * * @return The minimum size of the space found that meets the * requested space needed; or the largest size that comes - * close to meeting the space needed + * close to meeting the space needed. * */ uint32_t getAvailableSpace(uint32_t i_spaceNeeded, @@ -256,7 +292,7 @@ namespace TRACE uint32_t getAggregateSizeOfEntries() const; /** @brief This will return as many data entries that can be - * accommodated by size + * accommodated by i_dataSize * * @param[out] o_data - the buffer area to copy trace data into * @@ -380,7 +416,6 @@ namespace TRACE * * @param[in] i_tail - a pointer to an Entry data type; * OK to be a nullptr - * */ void setListTail(Entry* i_newEntry) { @@ -448,9 +483,13 @@ namespace TRACE void clearPtrToHead() { iv_ptrToHead = nullptr; } + // Private data members + private: + uintptr_t* iv_ptrToRsvdMem; //< Pointer to Reserved Memory. Used to + // realign pointers if RsvdMem relocates + uintptr_t* iv_ptrToHead; //< Pointer to oldest Entry (time wise) char *iv_bufferBeginningBoundary; //< Pointer to beginning of buffer char *iv_bufferEndingBoundary; //< Pointer to end of buffer - uintptr_t* iv_ptrToHead; //< Pointer to oldest Entry (time wise) bool iv_isBufferValid; //< Indicates an initialized buffer // For testing purposes only diff --git a/src/usr/trace/runtime/rt_rsvdtracebufservice.C b/src/usr/trace/runtime/rt_rsvdtracebufservice.C index 3d0c1bb95..21316e6f6 100644 --- a/src/usr/trace/runtime/rt_rsvdtracebufservice.C +++ b/src/usr/trace/runtime/rt_rsvdtracebufservice.C @@ -80,10 +80,10 @@ void RsvdTraceBufService::init() // If the data is not NULL, then retrieve crashed data // I want NULL in this case, not nullptr; *l_addressToHead is an int. // If I use nullptr; compiler complains - //if (*l_addressToHead != NULL) - //{ - // retrieveDataFromLastCrash(); - //} + if (*l_addressToHead != NULL) + { + retrieveDataFromLastCrash(); + } // After gathering trace info from previous crash, clear buffer data iv_rsvdTraceBuffer.clearBuffer(); diff --git a/src/usr/trace/runtime/test/testrsvdtracebuf.H b/src/usr/trace/runtime/test/testrsvdtracebuf.H index 148df5d07..0b6374ba7 100644 --- a/src/usr/trace/runtime/test/testrsvdtracebuf.H +++ b/src/usr/trace/runtime/test/testrsvdtracebuf.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2018 */ +/* Contributors Listed Below - COPYRIGHT 2013,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -25,10 +25,8 @@ #include <cxxtest/TestSuite.H> #include <trace/runtime/rt_rsvdtracebuffer.H> // TRACE::RsvdTraceBuffer -#include <trace/runtime/rt_rsvdtracebufservice.H> // TRACE::RsvdTraceBufService -#include <trace/entry.H> // TRACE::Entry -#include <trace/compdesc.H> // TRACE::ComponentDesc -#include <util/runtime/util_rt.H> // hb_get_rt_rsvd_mem +#include <trace/entry.H> // TRACE::Entry +#include <trace/compdesc.H> // TRACE::ComponentDesc #include <stdint.h> // uint32_t #include <stdlib.h> // malloc @@ -83,7 +81,7 @@ void testRsvdTraceBuffConstructor() } TRACFCOMP(g_trac_test, EXIT_MRK"RsvdTraceBuffTestSuite:%s", __func__); -} // void testRsvdTraceBuffConstructor() +} // end void testRsvdTraceBuffConstructor // Some more simple tests - the initializer void testRsvdTraceBuffInit() @@ -108,7 +106,7 @@ void testRsvdTraceBuffInit() l_addressToHead); char* l_bufferBegin = reinterpret_cast<char*>(l_bufferAddr + - sizeof(uintptr_t)); + (2 * sizeof(uintptr_t))); char* l_bufferEnd = reinterpret_cast<char*>(l_bufferAddr + l_bufferSize - 1); @@ -155,7 +153,7 @@ void testRsvdTraceBuffInit() } TRACFCOMP(g_trac_test, EXIT_MRK"RsvdTraceBuffTestSuite:%s", __func__); -} // end void testRsvdTraceBuffInit() +} // end void testRsvdTraceBuffInit // Test where buffer is too small to accommodate any Entry size void testRsvdTraceBuffBufferToSmall() @@ -225,7 +223,7 @@ void testRsvdTraceBuffBufferToSmall() free(l_buffer); TRACFCOMP(g_trac_test, EXIT_MRK"RsvdTraceBuffTestSuite:%s", __func__); -} // end void testRsvdTraceBuffBufferToSmall() +} // end void testRsvdTraceBuffBufferToSmall // Test where buffer is just the right size to fit a single Entry void testRsvdTraceBuffOnlyAccommodateOneItem() @@ -283,7 +281,8 @@ void testRsvdTraceBuffOnlyAccommodateOneItem() TS_FAIL("%s:%s: Pointer to list is not correct", __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + uint32_t l_itemCount(0); + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -329,7 +328,8 @@ void testRsvdTraceBuffOnlyAccommodateOneItem() TS_FAIL("%s:%s: Pointer to list is not correct", __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -354,7 +354,8 @@ void testRsvdTraceBuffOnlyAccommodateOneItem() TS_FAIL("%s:%s: Pointer to list is not correct", __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -363,7 +364,7 @@ void testRsvdTraceBuffOnlyAccommodateOneItem() free(l_buffer); TRACFCOMP(g_trac_test, EXIT_MRK"RsvdTraceBuffTestSuite:%s", __func__); -} // end void testRsvdTraceBuffOnlyAccommodateOneItem() +} // end void testRsvdTraceBuffOnlyAccommodateOneItem // Test where buffer is just the right size to fit a single Entry plus size void testRsvdTraceBuffOnlyAccommodateOneItemPlusSize() @@ -378,7 +379,7 @@ void testRsvdTraceBuffOnlyAccommodateOneItemPlusSize() l_rsvd); // Adjust buffer to the area we are interested in - char* l_buffer = l_fullBuffer + sizeof(uintptr_t); + char* l_buffer = l_fullBuffer + (2 * sizeof(uintptr_t)); if (l_rsvd.getBufferSize() != l_bufferSize) { @@ -434,8 +435,8 @@ void testRsvdTraceBuffOnlyAccommodateOneItemPlusSize() __FILE__, __func__); } - - if (true != runSelfDiagnostics(l_rsvd)) + uint32_t l_itemCount(0); + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -533,7 +534,8 @@ void testRsvdTraceBuffOnlyAccommodateOneItemPlusSize() __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -603,7 +605,8 @@ void testRsvdTraceBuffOnlyAccommodateOneItemPlusSize() __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -682,7 +685,7 @@ void testRsvdTraceBuffOnlyAccommodateOneItemPlusSize() free(l_fullBuffer); TRACFCOMP(g_trac_test, EXIT_MRK"RsvdTraceBuffTestSuite:%s", __func__); -} // end void testRsvdTraceBuffOnlyAccommodateOneItemPlusSize() +} // end void testRsvdTraceBuffOnlyAccommodateOneItemPlusSize // Test where buffer is just the right size to fit two Entries void testRsvdTraceBuffOnlyAccommodateTwoItems() @@ -697,7 +700,7 @@ void testRsvdTraceBuffOnlyAccommodateTwoItems() l_rsvd); // Adjust buffer to the area we are interested in - char* l_buffer = l_fullBuffer + sizeof(uintptr_t); + char* l_buffer = l_fullBuffer + (2 * sizeof(uintptr_t)); if (l_rsvd.getBufferSize() != l_bufferSize) { @@ -741,7 +744,8 @@ void testRsvdTraceBuffOnlyAccommodateTwoItems() __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + uint32_t l_itemCount(0); + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -790,7 +794,8 @@ void testRsvdTraceBuffOnlyAccommodateTwoItems() __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -833,7 +838,8 @@ void testRsvdTraceBuffOnlyAccommodateTwoItems() __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -887,7 +893,8 @@ void testRsvdTraceBuffOnlyAccommodateTwoItems() __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -912,7 +919,7 @@ void testRsvdTraceBuffTestTheEnds() l_rsvd); // Adjust buffer to the area we are interested in - char* l_buffer = l_fullBuffer + sizeof(uintptr_t); + char* l_buffer = l_fullBuffer + (2 * sizeof(uintptr_t)); if (l_rsvd.getBufferSize() != l_bufferSize) { @@ -991,7 +998,8 @@ void testRsvdTraceBuffTestTheEnds() __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + uint32_t l_itemCount(0); + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -1028,7 +1036,8 @@ void testRsvdTraceBuffTestTheEnds() __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -1064,7 +1073,8 @@ void testRsvdTraceBuffTestTheEnds() __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -1089,16 +1099,18 @@ void testRsvdTraceBuffTestReentrant () iv_buffer = initializeRsvdBuffer(iv_bufferSize, l_rsvd); + iv_bufferBeginningBoundary = l_rsvd.iv_bufferBeginningBoundary; iv_bufferEndingBoundary = l_rsvd.iv_bufferEndingBoundary; // Adjust buffer to the area we are interested in - char* l_buffer = iv_buffer + sizeof(uintptr_t); + char* l_buffer = iv_buffer + (2 * sizeof(uintptr_t)); - if (l_rsvd.getBufferSize() != iv_bufferSize) + if (l_rsvd.getBufferSize() != (iv_bufferSize - sizeof(uintptr_t))) { - TS_FAIL("%s:%s: buffer size is not correct", - __FILE__, __func__); + TS_FAIL("%s:%s: buffer size is not correct %d %d", + __FILE__, __func__, l_rsvd.getBufferSize(), + (iv_bufferSize - sizeof(uintptr_t))); } if (true != l_rsvd.isBufferValid()) @@ -1149,7 +1161,8 @@ void testRsvdTraceBuffTestReentrant () __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + uint32_t l_itemCount(0); + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -1168,7 +1181,7 @@ void testRsvdTraceBuffTestReentrant2() TRACE::RsvdTraceBuffer l_rsvd; initializeRsvdBufferForReentrant(l_rsvd); - if (l_rsvd.getBufferSize() != iv_bufferSize) + if (l_rsvd.getBufferSize() != (iv_bufferSize - sizeof(uintptr_t))) { TS_FAIL("%s:%s: buffer size is not correct", __FILE__, __func__); @@ -1196,7 +1209,8 @@ void testRsvdTraceBuffTestReentrant2() TS_FAIL("%s:%s: buffer is not valid", __FILE__, __func__); } - if (true != runSelfDiagnostics(l_rsvd)) + uint32_t l_itemCount(0); + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) { TS_FAIL("%s:%s: self diagnostics discovered an error", __FILE__, __func__); @@ -1259,7 +1273,7 @@ void testRsvdTraceBuffTestReentrant3() TRACE::RsvdTraceBuffer l_rsvd; initializeRsvdBufferForReentrant(l_rsvd); - if (l_rsvd.getBufferSize() != iv_bufferSize) + if (l_rsvd.getBufferSize() != (iv_bufferSize - sizeof(uintptr_t))) { TS_FAIL("%s:%s: buffer size is not correct", __FILE__, __func__); @@ -1353,7 +1367,7 @@ void testRsvdTraceBuffTestReentrant4() TRACE::RsvdTraceBuffer l_rsvd; initializeRsvdBufferForReentrant(l_rsvd); - if (l_rsvd.getBufferSize() != iv_bufferSize) + if (l_rsvd.getBufferSize() != (iv_bufferSize - sizeof(uintptr_t))) { TS_FAIL("%s:%s: buffer size is not correct", __FILE__, __func__); @@ -1423,7 +1437,7 @@ void testRsvdTraceBuffTestReentrant5() TRACE::RsvdTraceBuffer l_rsvd; initializeRsvdBufferForReentrant(l_rsvd); - if (l_rsvd.getBufferSize() != iv_bufferSize) + if (l_rsvd.getBufferSize() != (iv_bufferSize - sizeof(uintptr_t))) { TS_FAIL("%s:%s: buffer size is not correct", __FILE__, __func__); @@ -1474,11 +1488,175 @@ void testRsvdTraceBuffTestReentrant5() TRACFCOMP(g_trac_test, EXIT_MRK"RsvdTraceBuffTestSuite:%s", __func__); } // end void testRsvdTraceBuffTestReentrant5 +// Test when the buffer has been relocated +// To simulate that the buffer has been relocated in memory and the pointers +// within the buffer corrected, I create a buffer and divided it into +// 3 sections. I populate the middle section with data and verify that it +// is valid. Then I copy the middle buffer data over to the top section, +// basically a memory location before the middle buffer. Zero out the middle +// section to keep myself honest, then hand that buffer over to the +// RsvdTraceBuffer class, which should detect that the buffer has been relocated +// and correct the pointers. Once the RsvdTraceBuffer class has worked it's +// magic, the buffer is tested for correctness. I repeat this process by +// moving the buffer data to the bottom buffer, basically a memory location +// after the top and repeat this test. +void testRsvdTraceBuffTestBufferRelocation() +{ + TRACFCOMP(g_trac_test, ENTER_MRK"RsvdTraceBuffTestSuite:%s", __func__); + + // Size of each buffer segment (top buffer, middle buffer, bottom buffer) + const uint32_t SEGMENT_BUFFER_SIZE = 1024; + const uint32_t NUM_SEGMENTS = 3; + // Aggregate the size of the 3 buffer segments. + uint32_t l_bufferSize = NUM_SEGMENTS * SEGMENT_BUFFER_SIZE; + // Create the buffer of all combined segments and 'zero' out + char l_buffer[l_bufferSize]; + memset(l_buffer, 0, l_bufferSize); + + // Segment the buffer into 3 sections, top, middle, bottom + char * l_niflheim = l_buffer; + char * l_midgard = &(l_buffer[1 * SEGMENT_BUFFER_SIZE]); + char * l_muspelheim = &(l_buffer[2 * SEGMENT_BUFFER_SIZE]); + + uint32_t l_itemCount(0); + uint32_t l_expectedItemCount(3); + TRACE::RsvdTraceBuffer l_rsvd; + + // Populate middle buffer with data and verify it is correct + // This is just setting up the data before simulating a relocation + { + // Get the address of buffer + uintptr_t l_bufferAddr = reinterpret_cast<uintptr_t>(l_midgard); + + // Get a pointer to where the list head needs to reside in the buffer + uintptr_t *l_addressToListHead = reinterpret_cast<uintptr_t *>(l_bufferAddr); + + + l_rsvd.init(SEGMENT_BUFFER_SIZE - sizeof(uintptr_t), // subtract list head pointer + l_bufferAddr + sizeof(uintptr_t), // 'hop' over list head pointer + l_addressToListHead); + + // populate the middle buffer (l_midgard) with data + l_rsvd.insertEntry(sizeof(TRACE::Entry) + 20); + l_rsvd.insertEntry(sizeof(TRACE::Entry) + 5); + l_rsvd.insertEntry(sizeof(TRACE::Entry) + 30); + + // Validate the buffer + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) + { + TS_FAIL("%s:%s: Entry datas in midgard are corrupt", + __FILE__, __func__); + } + + if (l_itemCount != l_expectedItemCount) + { + TS_FAIL("%s:%s: The number of items found in midgard is incorrect, " + " expected %d, but got back %d", + __FILE__, __func__, l_expectedItemCount, l_itemCount); + } + } + + // Copy data over to the top buffer and clear out the middle buffer + // Simulate a relocation of the buffer to a memory address that precedes + // the original buffer's memory location + memcpy(l_niflheim, l_midgard, SEGMENT_BUFFER_SIZE); + memset(l_midgard, 0, SEGMENT_BUFFER_SIZE); + + // Test the top buffer + { + // Get the address of buffer + uintptr_t l_bufferAddr = reinterpret_cast<uintptr_t>(l_niflheim); + + // Get a pointer to where the list head needs to reside in the buffer + uintptr_t *l_addressToListHead = reinterpret_cast<uintptr_t *>(l_bufferAddr); + + // First invalidate buffer + // We need to invalidate the buffer before using it again. Saying + // it is invalid is probably a misnomer here, it really should be + // 'buffer is not initialized'. In a real situation, HB would have + // crashed and restarted. The validity of the buffer would be false + // since that info is not persisted. The buffer gets initialized with + // buffer data, which may or may not be empty. During the + // initialization the buffer gets evaluated to see if there is crash + // data to retrieve and a buffer that may or may not need the pointers + // corrected. + l_rsvd.iv_isBufferValid = false; + l_rsvd.init(SEGMENT_BUFFER_SIZE - sizeof(uintptr_t), // subtract list head pointer + l_bufferAddr + sizeof(uintptr_t), // 'hop' over list head pointer + l_addressToListHead); + + // Validate the buffer + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) + { + TS_FAIL("%s:%s: Entry datas in niflheim are corrupt", + __FILE__, __func__); + } + + if (l_itemCount != l_expectedItemCount) + { + TS_FAIL("%s:%s: The number of items found in niflheim is incorrect, " + " expected %d, but got back %d", + __FILE__, __func__, l_expectedItemCount, l_itemCount); + + } + } + + // Copy data over to the bottom buffer and clear out the top buffer + // Simulate a relocation of the buffer to a memory address that succeeds + // the original buffer's memory location + memcpy(l_muspelheim, l_niflheim, SEGMENT_BUFFER_SIZE); + memset(l_niflheim, 0, SEGMENT_BUFFER_SIZE); + + // Test the bottom buffer + { + // Get the address of buffer + uintptr_t l_bufferAddr = reinterpret_cast<uintptr_t>(l_muspelheim); + + // Get a pointer to where the list head needs to reside in the buffer + uintptr_t *l_addressToListHead = reinterpret_cast<uintptr_t *>(l_bufferAddr); + + // First invalidate buffer + // We need to invalidate the buffer before using it again. Saying + // it is invalid is probably a misnomer here, it really should be + // 'buffer is not initialized'. In a real situation, HB would have + // crashed and restarted. The validity of the buffer would be false + // since that info is not persisted. The buffer gets initialized with + // buffer data, which may or may not be empty. During the + // initialization the buffer gets evaluated to see if there is crash + // data to retrieve and a buffer that may or may not need the pointers + // corrected. + l_rsvd.iv_isBufferValid = false; + l_rsvd.init(SEGMENT_BUFFER_SIZE - sizeof(uintptr_t), // subtract list head pointer + l_bufferAddr + sizeof(uintptr_t), // 'hop' over list head pointer + l_addressToListHead); + + // Validate the buffer + l_itemCount = 0; + if (true != runSelfDiagnostics(l_rsvd, l_itemCount)) + { + TS_FAIL("%s:%s: Entry datas in muspelheim are corrupt", + __FILE__, __func__); + } + + if (l_itemCount != l_expectedItemCount) + { + TS_FAIL("%s:%s: The number of items found in muspelheim is incorrect, " + " expected %d, but got back %d", + __FILE__, __func__, l_expectedItemCount, l_itemCount); + } + } + TRACFCOMP(g_trac_test, EXIT_MRK"RsvdTraceBuffTestSuite:%s", __func__); +} // end void testRsvdTraceBuffTestBufferRelocation + private: // Helpful methods to help in testing char* initializeRsvdBuffer(uint32_t i_bufferSize, TRACE::RsvdTraceBuffer& i_rsvd) { + i_bufferSize += sizeof(uintptr_t); + iv_bufferSize = i_bufferSize; // Create a buffer uint32_t l_realBufferSize = i_bufferSize + sizeof(uintptr_t); char *l_buffer = reinterpret_cast<char*>(malloc(l_realBufferSize)); @@ -1513,7 +1691,7 @@ void initializeRsvdBufferForReentrant(TRACE::RsvdTraceBuffer& i_rsvd) } -bool runSelfDiagnostics(TRACE::RsvdTraceBuffer& l_rsvd) +bool runSelfDiagnostics(TRACE::RsvdTraceBuffer& l_rsvd, uint32_t & o_itemCount) { bool l_everythingChecksOut = true; uintptr_t l_bufferBeginningBoundary = l_rsvd.getAddressOfPtr @@ -1521,15 +1699,15 @@ bool runSelfDiagnostics(TRACE::RsvdTraceBuffer& l_rsvd) uintptr_t l_bufferEndingBoundary = l_rsvd.getAddressOfPtr (l_rsvd.iv_bufferEndingBoundary); + o_itemCount = 0; + if (!l_rsvd.isListEmpty()) { - uint32_t l_itemCount(0); - TRACE::Entry* l_entry = l_rsvd.getListHead(); TRACE::Entry* l_head = l_entry; do { - ++l_itemCount; + ++o_itemCount; uintptr_t l_entryAddr = l_rsvd.getAddressOfPtr(l_entry); uintptr_t l_entryAddrEnd = l_rsvd.getEndingAddressOfEntry(l_entry); @@ -1539,7 +1717,7 @@ bool runSelfDiagnostics(TRACE::RsvdTraceBuffer& l_rsvd) TS_FAIL("Item [%d] at address (0x%X) precedes the " "allocated memory location at address " "(0x%X) by %d byte(s)", - l_itemCount, l_entryAddr, l_bufferBeginningBoundary, + o_itemCount, l_entryAddr, l_bufferBeginningBoundary, (l_bufferBeginningBoundary - l_entryAddr)); l_everythingChecksOut = false; } @@ -1548,7 +1726,7 @@ bool runSelfDiagnostics(TRACE::RsvdTraceBuffer& l_rsvd) TS_FAIL("Item [%d] at address (0x%X) is beyond the " "ending allocated memory location at address " "(0x%X) by %d byte(s)", - l_itemCount, l_entryAddr, l_bufferEndingBoundary, + o_itemCount, l_entryAddr, l_bufferEndingBoundary, (l_entryAddr - l_bufferEndingBoundary)); l_everythingChecksOut = false; } @@ -1557,7 +1735,7 @@ bool runSelfDiagnostics(TRACE::RsvdTraceBuffer& l_rsvd) TS_FAIL("Item [%d] at address (0x%X) overruns the " "ending allocated memory location at address " "(0x%X) by %d byte(s)", - l_itemCount, l_entryAddr, l_bufferEndingBoundary, + o_itemCount, l_entryAddr, l_bufferEndingBoundary, (l_entryAddrEnd - l_bufferEndingBoundary)); l_everythingChecksOut = false; } @@ -1570,7 +1748,7 @@ bool runSelfDiagnostics(TRACE::RsvdTraceBuffer& l_rsvd) { TS_FAIL("Item [%d] at address (0x%X) overruns the " "next item at address (0x%X) by %d byte(s)", - l_itemCount, l_entryAddr, l_entryNextAddr, + o_itemCount, l_entryAddr, l_entryNextAddr, (l_entryAddrEnd - l_entryNextAddr + 1)); l_everythingChecksOut = false; } diff --git a/src/usr/trace/service.C b/src/usr/trace/service.C index ad8a0250c..21b2269b5 100644 --- a/src/usr/trace/service.C +++ b/src/usr/trace/service.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2018 */ +/* Contributors Listed Below - COPYRIGHT 2012,2019 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -37,7 +37,6 @@ #include <util/singleton.H> #include <assert.h> #include <time.h> -#include <config.h> #include <console/consoleif.H> #include <stdio.h> #include <ctype.h> |