Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 30 additions & 31 deletions libphal/phal_sbe.C
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
#include <fapi2.H>
#include "libphal.H"
#include "log.H"
#include "phal_exception.H"
#include "utils_buffer.H"
#include "utils_pdbg.H"
#include "utils_tempfile.H"
//#include "plat/plat_target.H"
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>

#include "sbeInf/response_info.H"
#include "sbeInf/sbe_cmd_implementation.H"

#include <ekb/chips/p10/procedures/hwp/perv/p10_sbe_hreset.H>
#include <ekb/chips/p10/procedures/hwp/sbe/p10_get_sbe_msg_register.H>
#include <ekb/hwpf/fapi2/include/return_code_defs.H>
Expand Down Expand Up @@ -435,48 +440,42 @@ void getTiInfo(struct pdbg_target *proc, uint8_t **data, uint32_t *dataLen)
}
}

void getDump(struct pdbg_target *chip, const uint8_t type, const uint8_t clock,
const uint8_t faCollect, uint8_t **data, uint32_t *dataLen)
void getDump(struct pdbg_target* chip,
const uint8_t type, const uint8_t clock, const uint8_t faCollect,
uint8_t** data, uint32_t* dataLen)
{
log(level::INFO, "Enter: getDump(%d) on %s", type,
pdbg_target_path(chip));

bool isOcmb = is_ody_ocmb_chip(chip);

if (!isTgtPresent(chip)) {
log(level::ERROR, "getDump(%s) Target is not present",
pdbg_target_path(chip));
}

if (!isOcmb) {
// Validate input target is processor target.
validateProcTgt(chip);
std::vector<uint8_t> dataVec;
std::vector<sbeIntf::ResponseInfo::FFDC> ffdcVec;

// SBE halt state need recovery before dump chip-ops
sbeHaltStateRecovery(chip, false);
}
log(level::ERROR, "In get dump");

// validate SBE state
validateSBEState(chip);
fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> fapiTarget(chip);
auto rc = sbeIntf::getDump(fapiTarget, type, clock, faCollect, dataVec, ffdcVec);

// get PIB target for proc else use same target
struct pdbg_target *chipOpTarget = isOcmb ? chip : getPibTarget(chip);
if (rc != fapi2::FAPI2_RC_SUCCESS)
{
log(level::ERROR, "fapi rc not success");
*data = nullptr;
*dataLen = 0;
throw sbeError_t(exception::SBE_CMD_FAILED);
}

// call pdbg back-end function
if (sbe_dump(chipOpTarget, type, clock, faCollect, data, dataLen)) {
throw captureFFDC(chip, CO_CMD_FAILURE);
}
*dataLen = dataVec.size();
*data = static_cast<uint8_t*>(malloc(*dataLen));
if (!*data)
{
*dataLen = 0;
throw sbeError_t(exception::SBE_CMD_FAILED);
}

sbeError_t result = captureFFDC(chip, CO_CMD_SUCCESS);
std::memcpy(*data, dataVec.data(), *dataLen);

// Throw only if FFDC present
if (result.errType() != exception::SBE_FFDC_NO_DATA) {
throw result;
}
// need to handle FFDC
}

void threadStopProc(struct pdbg_target *proc)
{

validateProcTgt(proc);

log(level::INFO, "Enter: threadStopProc(%s)", pdbg_target_path(proc));
Expand Down
67 changes: 67 additions & 0 deletions libphal/sbeInf/plat/plat_sbe_fifo.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once

extern "C" {
#include <libsbefifo.h>
}

#include <stdio.h>

#include <fapi2.H>
#include <vector>
#include <cstdint>
#include <cstring>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <cassert>

namespace sbeIntf {
namespace platform {

template <fapi2::TargetType T>
void setChipOpTimeout(const fapi2::Target<T>& target, uint32_t timeoutMs)
{
struct pdbg_target *pib = openpower::phal::utils::pdbg::getPibTarget(target);

sbe_set_chipop_timeout(pib, timeoutMs);
}

template <fapi2::TargetType T>
fapi2::ReturnCode transport(const fapi2::Target<T>& target,
const std::vector<uint8_t>& request, uint32_t out_len,
std::vector<uint8_t>& response)
{

uint8_t* out = nullptr;

struct pdbg_target *pib = openpower::phal::utils::pdbg::getPibTarget(target);

int rc = sbe_operation(pib,
const_cast<uint8_t*>(request.data()),
request.size(),
&out,
&out_len);

if (rc == ETIMEDOUT)
{
return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA;
}
else if (rc != 0)
{
fprintf(stderr, "transport failed in plat: rc=0x%08X\n", rc);
return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA;
}

if (!out || out_len == 0)
{
return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA;
}

response.assign(out, out + out_len);
free(out);
return fapi2::FAPI2_RC_SUCCESS;
}

} // namespace platform
} // namespace sbeIntf

25 changes: 25 additions & 0 deletions libphal/sbeInf/response_info.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <vector>
#include <cstdint>

namespace sbeIntf {

struct ResponseInfo
{
struct FFDC
{
uint8_t slid = 0;
uint8_t severity = 0;
uint32_t chipId = 0;
std::vector<uint8_t> rawData;
};

std::vector<uint8_t> payload;
std::vector<FFDC> ffdcList;
uint16_t primaryStatus = 0;
uint16_t secondaryStatus = 0;
};

}

165 changes: 165 additions & 0 deletions libphal/sbeInf/sbe_cmd_implementation.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#pragma once

#include <stdio.h>
#include <fapi2.H>
#include <vector>
#include <cstdint>
#include <cstring>
#include "sbe_cmd_protocol.H"
#include "plat/plat_sbe_fifo.H"

namespace sbeIntf {

inline std::vector<uint8_t> toByteVector(const std::vector<uint32_t>& words)
{
std::vector<uint8_t> bytes(words.size() * sizeof(uint32_t));
std::memcpy(bytes.data(), words.data(), bytes.size());
return bytes;
}


inline ResponseInfo decodeResponse(const std::vector<uint8_t>& rawBytes)
{
ResponseInfo out;
const size_t wordSize = sizeof(uint32_t);
const size_t wordCount = rawBytes.size() / wordSize;
const uint32_t* words = reinterpret_cast<const uint32_t*>(rawBytes.data());

if (wordCount < 3)
{
return out;
}

uint32_t trailerOffset = ntohl(words[wordCount - 1]);
size_t headerPos = wordCount - trailerOffset;

if (headerPos + 1 >= wordCount)
{
return out;
}

out.primaryStatus = ntohl(words[headerPos + 1]) >> 16;
out.secondaryStatus = ntohl(words[headerPos + 1]) & 0xFFFF;

size_t payloadSize = headerPos * wordSize;
out.payload.assign(rawBytes.begin(), rawBytes.begin() + payloadSize);

size_t ffdcStart = (headerPos + 2) * wordSize;
if (ffdcStart + 8 <= rawBytes.size())
{
size_t offset = ffdcStart;
while (offset + 8 <= rawBytes.size())
{
const uint8_t* p = &rawBytes[offset];
uint16_t magic = ntohs(*(uint16_t*)p);

if (magic != 0xFBAD && magic != 0xFFDC)
break;

ResponseInfo::FFDC entry;
entry.slid = ntohs(*(uint16_t*)(p + 4));
entry.severity = *(p + 6);
entry.chipId = *(p + 7);

uint16_t wordLen = ntohs(*(uint16_t*)(p + 2));
size_t byteLen = wordLen * wordSize;

if (offset + byteLen > rawBytes.size())
break;

entry.rawData.assign(p, p + byteLen);
out.ffdcList.push_back(std::move(entry));
offset += byteLen;
}
}

return out;
}


template <fapi2::TargetType T>
fapi2::ReturnCode executeChipOp(const fapi2::Target<T>& target,
const std::vector<uint32_t>& cmd_words,
std::vector<uint8_t>& data,
std::vector<ResponseInfo::FFDC>& ffdc)
{
std::vector<uint8_t> request = toByteVector(cmd_words);

uint32_t cmd = ntohl(cmd_words[1]);
uint32_t timeoutMs = cmd::getRecommendedTimeoutMs(cmd);
uint32_t out_len = cmd::getRecommendedSize(cmd);

platform::setChipOpTimeout(target, timeoutMs);

std::vector<uint8_t> response;
auto rc = platform::transport(target, request, out_len, response);
if (rc != fapi2::FAPI2_RC_SUCCESS)
{
return rc;
}

auto decoded = decodeResponse(response);
data = std::move(decoded.payload);
ffdc = std::move(decoded.ffdcList);
fprintf(stderr, "SBE response status: primary=0x%08X secondary=0x%08X, payload=%zu bytes, FFDC=%zu\n",
decoded.primaryStatus, decoded.secondaryStatus,
decoded.payload.size(), decoded.ffdcList.size());

return (decoded.primaryStatus != 0 || decoded.secondaryStatus != 0)
? fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA
: fapi2::FAPI2_RC_SUCCESS;
}

template <fapi2::TargetType T>
fapi2::ReturnCode captureFfdc(const fapi2::Target<T>& target,
std::vector<uint8_t>& discard,
std::vector<ResponseInfo::FFDC>& outFfdc)
{
std::vector<uint8_t> response;
auto encoded = cmd::encodeGetFfdc();
uint32_t cmd = ntohl(encoded[1]);
uint32_t out_len = cmd::getRecommendedSize(cmd);
auto rc = platform::transport(target, toByteVector(encoded), out_len, response);
if (rc != fapi2::FAPI2_RC_SUCCESS) {
return rc;
}

auto decoded = decodeResponse(response);
if (!decoded.ffdcList.empty()) {
outFfdc.insert(outFfdc.end(),
std::make_move_iterator(decoded.ffdcList.begin()),
std::make_move_iterator(decoded.ffdcList.end()));
return fapi2::FAPI2_RC_SUCCESS;
}

return fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA;
}

template <fapi2::TargetType T>
void mergeExtraFfdc(const fapi2::Target<T>& target,
std::vector<ResponseInfo::FFDC>& ffdc)
{
std::vector<ResponseInfo::FFDC> extraFfdc;
std::vector<uint8_t> discard;
auto ffdcRc = captureFfdc(target, discard, extraFfdc);
if (ffdcRc != fapi2::FAPI2_RC_SUCCESS && !extraFfdc.empty()) {
ffdc.insert(ffdc.end(),
std::make_move_iterator(extraFfdc.begin()),
std::make_move_iterator(extraFfdc.end()));
}
}

template <fapi2::TargetType T>
fapi2::ReturnCode getDump(const fapi2::Target<T>& target,
uint8_t type, uint8_t clock, uint8_t fa,
std::vector<uint8_t>& data,
std::vector<ResponseInfo::FFDC>& ffdc)
{
auto cmd_words = cmd::encodeGetDump(type, clock, fa);
auto rc = executeChipOp(target, cmd_words, data, ffdc);
mergeExtraFfdc(target, ffdc);
return rc;
}

}

Loading