diff options
Diffstat (limited to 'src/sbefw/core/sbecmdringaccess.C')
-rw-r--r-- | src/sbefw/core/sbecmdringaccess.C | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/src/sbefw/core/sbecmdringaccess.C b/src/sbefw/core/sbecmdringaccess.C new file mode 100644 index 00000000..1db28734 --- /dev/null +++ b/src/sbefw/core/sbecmdringaccess.C @@ -0,0 +1,361 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/core/sbecmdringaccess.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* */ +/* */ +/* 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 */ +/* + * @file: ppe/sbe/sbefw/sbecmdringaccess.C + * + * @brief This file contains the SBE Ring Access chipOps + * + */ + +#include "sbecmdringaccess.H" +#include "sbefifo.H" +#include "sbe_sp_intf.H" +#include "sbetrace.H" +#include "sbeHostMsg.H" +#include "sbeHostUtils.H" +#include "sbeFifoMsgUtils.H" +#include "sbeutil.H" +#include "sbefapiutil.H" +#include "fapi2.H" +#include "plat_hw_access.H" +#include "sbeglobals.H" + +using namespace fapi2; + +static const uint32_t SIZE_OF_LENGTH_INWORDS = 1; +static const uint32_t NUM_WORDS_PER_GRANULE = 2; +static const uint32_t GETRING_GRANULE_SIZE_IN_BITS = 64; + + +uint32_t sbePutRingFromImagePSU (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbePutRingFromImagePSU " + SBE_ENTER(SBE_FUNC); + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t l_fapiRc = FAPI2_RC_SUCCESS; + sbePSUPutRingCMD_t l_cmd = {0}; + do + { + // Fetch Ring ID, Ring mode and pervasive chiplet id from the message + // and also send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1 + l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1, + (sizeof(l_cmd)/sizeof(uint64_t)), + (uint64_t*)&l_cmd, + true); + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_ERROR(SBE_FUNC "Failed to extract SBE_HOST_PSU_MBOX_REG1 and " + "SBE_HOST_PSU_MBOX_REG2"); + break; + } + + // Construct a Target from Chiplet ID and Target Type + fapi2::plat_target_handle_t l_tgtHndl; + if(!sbeGetFapiTargetHandle(l_cmd.TargetType, l_cmd.ChipletID, + l_tgtHndl)) + { + SBE_ERROR(SBE_FUNC "Invalid target type [0x%04x]", + (uint16_t)l_cmd.TargetType); + SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INVALID_DATA, + SBE_SEC_INVALID_TARGET_TYPE_PASSED); + break; + } + fapi2::Target<TARGET_TYPE_ALL> l_Tgt(l_tgtHndl); + + // Initialize with HEADER CHECK mode + uint16_t l_ringMode = sbeToFapiRingMode(l_cmd.RingMode); + + l_fapiRc = (uint32_t)putRing(l_Tgt, (RingID)l_cmd.RingID, + (RingMode)l_ringMode); + if(l_fapiRc != FAPI2_RC_SUCCESS) + { + SBE_ERROR(SBE_FUNC "putRing HWP failure - " + "MSG - Target Type [0x%04x] Ring ID [0x%04x]" + " Ring Mode [0x%04x] Chiplet ID [0x%04x]", + l_cmd.TargetType, + l_cmd.RingID, + l_cmd.RingMode, + l_cmd.ChipletID); + break; + } + }while(0); // End of do-while + + // Send the response + sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, l_rc); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeGetRing(uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeGetRing " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbeGetRingAccessMsgHdr_t l_reqMsg; + sbeRespGenHdr_t respHdr; + respHdr.init(); + sbeResponseFfdc_t l_ffdc; + ReturnCode l_fapiRc; + uint32_t l_len = 0; + + //Note-Read operation flow is SHIFT and then READ. + // First time , the shift count will be 0.. because of the way it + // works. if we shift 64bits in the very first iteration then we + // loose first 64 bit. But still we should update l_bitSentCnt + // because we are sending back this data + uint32_t l_bitSentCnt = 64; + const uint32_t LONG_ROTATE_ADDRESS = 0x0003E000; + + do + { + // Get the ring access header + l_len = sizeof(sbeGetRingAccessMsgHdr_t)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len, (uint32_t *)&l_reqMsg); // EOT fetch + + // If FIFO access failure + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc); + + SBE_INFO(SBE_FUNC "Ring Address 0x%08X User Ring Mode 0x%04X " + "Length in Bits 0x%08X", + (uint32_t)l_reqMsg.ringAddr, + (uint32_t)l_reqMsg.ringMode, + (uint32_t)l_reqMsg.ringLenInBits); + + uint16_t l_ringMode = sbeToFapiRingMode(l_reqMsg.ringMode); + + // Call getRing_setup - loads the scan region data for the given ring + // address and updates the check word data + l_fapiRc = fapi2::getRing_setup(l_reqMsg.ringAddr, + (fapi2::RingMode)l_ringMode); + if( l_fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" getRing_setup failed. RingAddress:0x%08X " + "RingMode:0x%04x", l_reqMsg.ringAddr, l_ringMode); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + break; + } + // Calculate the iteration length + uint32_t l_loopCnt = + (l_reqMsg.ringLenInBits / GETRING_GRANULE_SIZE_IN_BITS); + // Check for modulus - remainder + uint8_t l_mod = (l_reqMsg.ringLenInBits % GETRING_GRANULE_SIZE_IN_BITS); + if(l_mod) + { + ++l_loopCnt; + } + + // fix for the alignment issue + uint32_t l_buf[NUM_WORDS_PER_GRANULE]__attribute__ ((aligned (8))) ={0}; + uint32_t l_bitShift = 0; + l_len = NUM_WORDS_PER_GRANULE; + plat_target_handle_t l_hndl; + uint32_t l_chipletId = (uint32_t)(l_reqMsg.ringAddr) & 0xFF000000; + uint32_t l_scomAddress = 0; + + // Fetch the ring data in bits, each iteration will give you 64bits + for(uint32_t l_cnt=0; l_cnt < l_loopCnt; l_cnt++) + { + + l_scomAddress = LONG_ROTATE_ADDRESS | l_chipletId; + l_scomAddress |= l_bitShift; + l_fapiRc = getscom_abs_wrap (&l_hndl, + l_scomAddress, + (uint64_t*)&l_buf); + + if( l_fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" getRing_granule_data failed. " + "RingAddress:0x%08X RingMode:0x%04x", + l_reqMsg.ringAddr, l_ringMode); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + break; + } + // if the length of ring is not divisible by 64 then mod value + // should be considered which will match with the length in bits + // that passed + if((l_cnt == (l_loopCnt -1)) && (l_mod)) + { + l_bitShift = l_mod; + } + // Send it to DS Fifo + // If this is the last iteration in the loop, let the full 64bit + // go, even for 1bit of remaining length. The length passed to + // the user will take care of actual number of bits. + l_rc = sbeDownFifoEnq_mult (l_len, (uint32_t *)&l_buf); + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc); + l_bitSentCnt = l_bitSentCnt + l_bitShift; + l_bitShift = GETRING_GRANULE_SIZE_IN_BITS; + } + if ( (l_fapiRc == FAPI2_RC_SUCCESS) && + (l_rc == SBE_SEC_OPERATION_SUCCESSFUL) ) + { + if (!l_mod) + { + l_mod = GETRING_GRANULE_SIZE_IN_BITS; + } + //Here we need to shift with the mod value to enter into the + //starting position of the ring.But the data is already read in the + //above for loop.. so here we ignore the data + l_scomAddress = LONG_ROTATE_ADDRESS | l_chipletId; + l_scomAddress |= l_mod; + l_fapiRc = getscom_abs_wrap (&l_hndl, + l_scomAddress, + (uint64_t*)&l_buf); + + if( l_fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" getRing_granule_data failed. " + "RingAddress:0x%08X RingMode:0x%04x", + l_reqMsg.ringAddr, l_ringMode); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + break; + } + + // Call getRing_verifyAndcleanup - verify the check word data is + // matching or not and will clean up the scan region data + l_fapiRc = getRing_verifyAndcleanup((uint32_t)(l_reqMsg.ringAddr), + (fapi2::RingMode)l_ringMode); + if( l_fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" getRing_verifyAndcleanup failed. " + "RingAddress:0x%08X RingMode:0x%04x", + l_reqMsg.ringAddr, l_ringMode); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + } + } + }while(false); + + // Now build and enqueue response into downstream FIFO + // If there was a FIFO error, will skip sending the response, + // instead give the control back to the command processor thread + if ( SBE_SEC_OPERATION_SUCCESSFUL == l_rc ) + { + l_len = SIZE_OF_LENGTH_INWORDS; + l_rc = sbeDownFifoEnq_mult (l_len, &(l_bitSentCnt)); + if(SBE_SEC_OPERATION_SUCCESSFUL == l_rc) + { + l_rc = sbeDsSendRespHdr( respHdr, &l_ffdc); + } + } + SBE_EXIT(SBE_FUNC); + return l_rc; +#undef SBE_FUNC +} + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbePutRing(uint8_t *i_pArg) +{ +#define SBE_FUNC " sbePutRing " + SBE_ENTER(SBE_FUNC); + + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbePutRingMsg_t reqMsg; + sbeRespGenHdr_t respHdr; + respHdr.init(); + sbeResponseFfdc_t ffdc; + ReturnCode fapiRc; + sbePutRingMsgHdr_t hdr; + uint32_t len = 0; + + do + { + // Get the length of payload + // Length is not part of chipop. So take length from total length + len = SBE_GLOBAL->sbeFifoCmdHdr.len - + sizeof(SBE_GLOBAL->sbeFifoCmdHdr)/sizeof(uint32_t); + uint32_t rs4FifoEntries = len - + sizeof(sbePutRingMsgHdr_t)/sizeof(uint32_t); + + if( rs4FifoEntries > (SBE_PUT_RING_RS4_MAX_DOUBLE_WORDS * 2) ) + { + SBE_ERROR(SBE_FUNC" RS4 palyload size is wrong." + "size(entries):0x%08x", rs4FifoEntries); + respHdr.setStatus( SBE_PRI_INVALID_DATA, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + // flush the fifo + rc = sbeUpFifoDeq_mult(len, NULL,true, true); + break; + } + + len = sizeof(sbePutRingMsgHdr_t)/sizeof(uint32_t); + rc = sbeUpFifoDeq_mult (len, (uint32_t *)&hdr, false); + // If FIFO access failure + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc); + + len = rs4FifoEntries; + rc = sbeUpFifoDeq_mult (len, (uint32_t *)&reqMsg); + // If FIFO access failure + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc); + + uint16_t ringMode = sbeToFapiRingMode(hdr.ringMode); + bool i_applyOverride = false; + + if (hdr.ringMode & SBE_RING_MODE_APPLY_OVERRIDE) + { + i_applyOverride = true; + } + + + + Target<TARGET_TYPE_PROC_CHIP> proc = plat_getChipTarget(); + // No need to pass length as platform api takes length from payload. + fapiRc = rs4DecompressionSvc(proc, (uint8_t *)reqMsg.rs4Payload, + i_applyOverride, (fapi2::RingMode)ringMode); + if( fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" rs4DecompressionSvc failed." + "RingMode:0x%04x", ringMode); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + ffdc.setRc(fapiRc); + break; + } + }while(false); + + // Now build and enqueue response into downstream FIFO + // If there was a FIFO error, will skip sending the response, + // instead give the control back to the command processor thread + if ( SBE_SEC_OPERATION_SUCCESSFUL == rc ) + { + rc = sbeDsSendRespHdr( respHdr, &ffdc); + } + SBE_EXIT(SBE_FUNC); + return rc; +#undef SBE_FUNC +} + |