From f2d94b5f809410300fe10dc9d0786790018463a0 Mon Sep 17 00:00:00 2001 From: Shakeeb Date: Sat, 27 Aug 2016 10:50:49 -0500 Subject: SBE code restructure: sbe -> src rename Change-Id: I6e4378d0e71a00ed2b239658d43f180df2a9b748 RTC:159709 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/28875 Tested-by: Jenkins Server Tested-by: FSP CI Jenkins Reviewed-by: RAJA DAS Reviewed-by: Sachin Gupta --- src/sbefw/Makefile | 56 +++ src/sbefw/assert.h | 49 ++ src/sbefw/pk_app_cfg.h | 144 ++++++ src/sbefw/plugins/sbeUserDataParser.C | 292 ++++++++++++ src/sbefw/pool.C | 65 +++ src/sbefw/pool.H | 58 +++ src/sbefw/sbeFFDC.C | 141 ++++++ src/sbefw/sbeFFDC.H | 125 +++++ src/sbefw/sbeFFDCType.H | 100 ++++ src/sbefw/sbeFifoMsgUtils.C | 375 +++++++++++++++ src/sbefw/sbeFifoMsgUtils.H | 192 ++++++++ src/sbefw/sbeHostMsg.H | 132 ++++++ src/sbefw/sbeHostUtils.C | 226 +++++++++ src/sbefw/sbeHostUtils.H | 244 ++++++++++ src/sbefw/sbeSpMsg.H | 634 ++++++++++++++++++++++++++ src/sbefw/sbeXipUtils.H | 63 +++ src/sbefw/sbe_host_intf.H | 89 ++++ src/sbefw/sbe_sp_intf.H | 408 +++++++++++++++++ src/sbefw/sbecmdcntlinst.C | 203 +++++++++ src/sbefw/sbecmdcntlinst.H | 45 ++ src/sbefw/sbecmdcntrldmt.C | 302 +++++++++++++ src/sbefw/sbecmdcntrldmt.H | 59 +++ src/sbefw/sbecmdgeneric.C | 118 +++++ src/sbefw/sbecmdgeneric.H | 46 ++ src/sbefw/sbecmdiplcontrol.C | 830 ++++++++++++++++++++++++++++++++++ src/sbefw/sbecmdiplcontrol.H | 117 +++++ src/sbefw/sbecmdmemaccess.C | 778 +++++++++++++++++++++++++++++++ src/sbefw/sbecmdmemaccess.H | 54 +++ src/sbefw/sbecmdparser.C | 483 ++++++++++++++++++++ src/sbefw/sbecmdparser.H | 119 +++++ src/sbefw/sbecmdprocessor.C | 376 +++++++++++++++ src/sbefw/sbecmdreceiver.C | 325 +++++++++++++ src/sbefw/sbecmdregaccess.C | 274 +++++++++++ src/sbefw/sbecmdregaccess.H | 56 +++ src/sbefw/sbecmdringaccess.C | 305 +++++++++++++ src/sbefw/sbecmdringaccess.H | 63 +++ src/sbefw/sbecmdscomaccess.C | 495 ++++++++++++++++++++ src/sbefw/sbecmdscomaccess.H | 93 ++++ src/sbefw/sbecmdsram.C | 337 ++++++++++++++ src/sbefw/sbecmdsram.H | 64 +++ src/sbefw/sbeerrorcodes.H | 49 ++ src/sbefw/sbeevents.H | 96 ++++ src/sbefw/sbeexeintf.H | 256 +++++++++++ src/sbefw/sbefifo.H | 227 ++++++++++ src/sbefw/sbefwfiles.mk | 48 ++ src/sbefw/sbeirq.C | 195 ++++++++ src/sbefw/sbeirq.H | 109 +++++ src/sbefw/sbemain.C | 352 ++++++++++++++ src/sbefw/sberegaccess.C | 331 ++++++++++++++ src/sbefw/sberegaccess.H | 266 +++++++++++ src/sbefw/sbescom.C | 198 ++++++++ src/sbefw/sbescom.H | 38 ++ src/sbefw/sbestates.H | 67 +++ src/sbefw/sbetrace.H | 75 +++ src/sbefw/sbeutil.H | 81 ++++ src/sbefw/vector | 397 ++++++++++++++++ 56 files changed, 11720 insertions(+) create mode 100644 src/sbefw/Makefile create mode 100644 src/sbefw/assert.h create mode 100644 src/sbefw/pk_app_cfg.h create mode 100644 src/sbefw/plugins/sbeUserDataParser.C create mode 100644 src/sbefw/pool.C create mode 100644 src/sbefw/pool.H create mode 100644 src/sbefw/sbeFFDC.C create mode 100644 src/sbefw/sbeFFDC.H create mode 100644 src/sbefw/sbeFFDCType.H create mode 100644 src/sbefw/sbeFifoMsgUtils.C create mode 100644 src/sbefw/sbeFifoMsgUtils.H create mode 100644 src/sbefw/sbeHostMsg.H create mode 100644 src/sbefw/sbeHostUtils.C create mode 100644 src/sbefw/sbeHostUtils.H create mode 100644 src/sbefw/sbeSpMsg.H create mode 100644 src/sbefw/sbeXipUtils.H create mode 100644 src/sbefw/sbe_host_intf.H create mode 100644 src/sbefw/sbe_sp_intf.H create mode 100644 src/sbefw/sbecmdcntlinst.C create mode 100644 src/sbefw/sbecmdcntlinst.H create mode 100644 src/sbefw/sbecmdcntrldmt.C create mode 100644 src/sbefw/sbecmdcntrldmt.H create mode 100644 src/sbefw/sbecmdgeneric.C create mode 100644 src/sbefw/sbecmdgeneric.H create mode 100644 src/sbefw/sbecmdiplcontrol.C create mode 100644 src/sbefw/sbecmdiplcontrol.H create mode 100644 src/sbefw/sbecmdmemaccess.C create mode 100644 src/sbefw/sbecmdmemaccess.H create mode 100644 src/sbefw/sbecmdparser.C create mode 100644 src/sbefw/sbecmdparser.H create mode 100644 src/sbefw/sbecmdprocessor.C create mode 100644 src/sbefw/sbecmdreceiver.C create mode 100644 src/sbefw/sbecmdregaccess.C create mode 100644 src/sbefw/sbecmdregaccess.H create mode 100644 src/sbefw/sbecmdringaccess.C create mode 100644 src/sbefw/sbecmdringaccess.H create mode 100644 src/sbefw/sbecmdscomaccess.C create mode 100644 src/sbefw/sbecmdscomaccess.H create mode 100644 src/sbefw/sbecmdsram.C create mode 100644 src/sbefw/sbecmdsram.H create mode 100644 src/sbefw/sbeerrorcodes.H create mode 100644 src/sbefw/sbeevents.H create mode 100644 src/sbefw/sbeexeintf.H create mode 100644 src/sbefw/sbefifo.H create mode 100644 src/sbefw/sbefwfiles.mk create mode 100644 src/sbefw/sbeirq.C create mode 100644 src/sbefw/sbeirq.H create mode 100644 src/sbefw/sbemain.C create mode 100644 src/sbefw/sberegaccess.C create mode 100644 src/sbefw/sberegaccess.H create mode 100644 src/sbefw/sbescom.C create mode 100644 src/sbefw/sbescom.H create mode 100644 src/sbefw/sbestates.H create mode 100644 src/sbefw/sbetrace.H create mode 100644 src/sbefw/sbeutil.H create mode 100644 src/sbefw/vector (limited to 'src/sbefw') diff --git a/src/sbefw/Makefile b/src/sbefw/Makefile new file mode 100644 index 00000000..f25f44f5 --- /dev/null +++ b/src/sbefw/Makefile @@ -0,0 +1,56 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/sbefw/Makefile $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 +#export P2P_ENABLE = 1 + +export SUB_OBJDIR = /sbefw + +include img_defs.mk +include sbefwfiles.mk + +OBJS := $(addprefix $(OBJDIR)/, $(SBEFW_OBJECTS)) + +libsbefw.a: $(OBJS) + $(AR) crs $(OBJDIR)/libsbefw.a $(OBJDIR)/*.o + +.PHONY: clean sbefw +sbefw: $(OBJS) + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + + +#clean the kernel directory first, then the application level clean +clean: + rm -fr $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif + + + + + diff --git a/src/sbefw/assert.h b/src/sbefw/assert.h new file mode 100644 index 00000000..4a5be085 --- /dev/null +++ b/src/sbefw/assert.h @@ -0,0 +1,49 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/assert.h $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 assert.h + * + * @brief This file contains the assert macro for SBE + */ +#ifndef SBE_ASSERT_H +#define SBE_ASSERT_H +#include "sbetrace.H" +#include "sbeutil.H" + +//@TODO via RTC 129166 +//inject exception to halt SBE. Also see if we can use some +//PK kernel API. +#ifndef NDEBUG +#define assert(expr) \ + if( !(expr )) \ + { \ + SBE_ERROR("assertion failed: "#expr); \ + PK_PANIC(SBE::PANIC_ASSERT); \ + } \ + +#else +#define assert(expr) +#endif //NDEBUG + +#endif // SBE_ASSERT_H diff --git a/src/sbefw/pk_app_cfg.h b/src/sbefw/pk_app_cfg.h new file mode 100644 index 00000000..d2fbfceb --- /dev/null +++ b/src/sbefw/pk_app_cfg.h @@ -0,0 +1,144 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/pk_app_cfg.h $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/pk_app_cfg.h + * + * @brief Application specific overrides go here. + * + */ + +#ifndef __PK_APP_CFG_H__ +#define __PK_APP_CFG_H__ + +#include "sbeirq.H" + +/* + * @brief Static configuration data for external interrupts: + * IRQ#, TYPE, POLARITY, ENABLE + * + */ +#define APPCFG_EXT_IRQS_CONFIG \ + SBE_IRQ_START0 STD_IRQ_TYPE_EDGE STD_IRQ_POLARITY_RISING STD_IRQ_MASKED \ + SBE_IRQ_START1 STD_IRQ_TYPE_EDGE STD_IRQ_POLARITY_RISING STD_IRQ_MASKED \ + SBE_IRQ_INTR0 STD_IRQ_TYPE_LEVEL STD_IRQ_POLARITY_RISING STD_IRQ_MASKED \ + SBE_IRQ_INTR1 STD_IRQ_TYPE_LEVEL STD_IRQ_POLARITY_RISING STD_IRQ_MASKED \ + SBE_IRQ_DRTM_REQ STD_IRQ_TYPE_LEVEL STD_IRQ_POLARITY_RISING STD_IRQ_MASKED \ + SBE_IRQ_SBEFIFO_RESET STD_IRQ_TYPE_LEVEL STD_IRQ_POLARITY_RISING STD_IRQ_MASKED \ + SBE_IRQ_SBEFIFO_DATA STD_IRQ_TYPE_LEVEL STD_IRQ_POLARITY_RISING STD_IRQ_MASKED \ + SBE_IRQ_HOST_PSU_INTR STD_IRQ_TYPE_LEVEL STD_IRQ_POLARITY_RISING STD_IRQ_MASKED \ + + +/* + * @brief This 64 bit mask specifies which of the interrupts are not to be used. + * + */ +#define APPCFG_IRQ_INVALID_MASK \ +(\ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_8) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_9) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_10) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_11) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_12) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_13) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_14) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_15) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_16) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_17) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_18) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_19) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_20) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_21) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_22) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_23) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_24) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_25) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_26) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_27) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_28) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_29) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_30) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_31) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_32) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_33) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_34) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_35) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_36) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_37) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_38) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_39) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_40) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_41) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_42) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_43) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_44) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_45) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_46) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_47) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_48) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_49) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_50) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_51) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_52) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_53) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_54) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_55) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_56) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_57) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_58) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_59) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_60) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_61) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_62) | \ + STD_IRQ_MASK64(SBE_IRQ_RESERVED_63)) + + +/* + * @brief Override the default behavior of the PK API error handling. + * Force PK to send the return code back to the application, + * instead of a kernel panic. + * + */ +#ifndef PK_ERROR_PANIC +#define PK_ERROR_PANIC 0 +#endif + +/* + * @brief Override the default behavior of idle timer trace. + * As SBE trace buffer is small, we do not want idle timer traces. + * + */ +#define PK_TRACE_TIMER_OUTPUT 0 + +#ifdef PPE42_MACHINE_CHECK_HANDLER +#undef PPE42_MACHINE_CHECK_HANDLER +#endif +#define PPE42_MACHINE_CHECK_HANDLER SBE_MACHINE_CHECK_HANDLER + +// Set the trace buffer size +#ifdef PK_TRACE_SZ +#undef PK_TRACE_SZ +#endif +#define PK_TRACE_SZ 4*1024 + +#endif /*__PK_APP_CFG_H__*/ diff --git a/src/sbefw/plugins/sbeUserDataParser.C b/src/sbefw/plugins/sbeUserDataParser.C new file mode 100644 index 00000000..9ad2f48e --- /dev/null +++ b/src/sbefw/plugins/sbeUserDataParser.C @@ -0,0 +1,292 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/plugins/sbeUserDataParser.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ +#include +#include + +#include +#include +#include + +#include +#include + +#include "sbeFFDCType.H" + +#define SBE_TEMP_DUMP_FILE "/tmp/trace_dump.bin" +#define SBE_TRACE_BIN "/tmp/sbe_trace.bin" +#define PPE2FSP_TOOL "ppe2fsp" +#define P9_XIP_TOOL "p9_xip_tool" +#define SBE_TRACE_CMD "fsp-trace -s" +#define SBE_TRACE_HEADLINE "SBE Traces" +#define SBE_ATTR_DUMP_HEADLINE "SBE Attributes Dump" +#define P9_XIP_ATTR_CMD "-ifs attrdump" +#define SBE_STRING_FILE "sbeStringFile" +#define SBE_SEEPROM_BIN "sbe_seeprom.bin" + +#define SBE_PARSER_MAX_LOCAL_BUFFER 8192 + +#define SBE_PARSER_PRINT_DELIMITER {std::cout << \ +"*****************************************************************************"\ +<< std::endl;} +#define SBE_PARSER_PRINT_HEADING(x) { SBE_PARSER_PRINT_DELIMITER \ +std::cout << \ +" "x<< std::endl;\ +SBE_PARSER_PRINT_DELIMITER } + +std::string findSbeFile(const char *name) +{ +#ifdef CONTEXT_x86_nfp + //TODO via RTC:157433 + std::string tmp = getenv("bb"); + tmp += "obj/x86.nfp/sbei/sbfw/img/"; + std::string file = tmp + name; + + struct stat l_stat; + if(stat(file.c_str(), &l_stat) < 0) + { + //Can't find the file + } + + return file; +#endif +#ifdef CONTEXT_ppc + std::string tmp = getenv("PATH"); + tmp += ":/nfs:/maint"; + + char *path = strdup(tmp.c_str()); + char *dir = NULL; + + std::string file; + + struct stat l_stat; + + for(dir = strtok( path, ":" ); dir; dir = strtok(NULL, ":")) + { + file = file + dir + "/" + name; + + if(stat(file.c_str(), &l_stat) < 0) + { + // String file not found, go to next one + file.clear(); + } + else + { + // update where trexStringFile is + break; + } + } + + free(path); + path = NULL; //sm05c + + return file; +#endif +} + +void sbeParserSysCall(const char *cmd) +{ + FILE *stream; + char buffer[256]; + + stream = popen(cmd, "r" ); + if(stream) + { + while(!feof(stream)) + { + if(fgets(buffer, 256, stream) != NULL) + { + std::cout << buffer; + } + } + } + else + { + std::cout << "command failed :[" << cmd << "]" << std::endl; + std::cout << "errno [" << errno << "]" << std::endl; + } +} + +int parseSbeFFDC(ErrlUsrParser & i_parser, const void * i_pBuffer, + const uint32_t i_buflen) +{ + int l_rc = 0; + uint32_t fapiRc = 0; + sbeFFDCDataHeader_t l_pData = {0}; + char l_buffer[SBE_PARSER_MAX_LOCAL_BUFFER] = {0}; + char *l_pBuffer = (char*)i_pBuffer; + uint32_t l_buflen = i_buflen; + + do + { + if(i_pBuffer == NULL) + { + l_rc = -1; + break; + } + //seek l_mem to the binary blob of FFDC package + UtilMem l_mem(const_cast(i_pBuffer),i_buflen); + + // The data is a buffer of SBE FFDC data + i_parser.PrintHeading("SBE FFDC Parser"); + + if(l_buflen < sizeof(fapiRc)) + { + i_parser.PrintHexDump(l_pBuffer, l_buflen); + break; + } + l_buflen -= sizeof(fapiRc); + l_pBuffer += sizeof(fapiRc); + l_mem >> fapiRc; + i_parser.PrintNumber("FAPI RC ", "0x%08X", fapiRc); + + if(l_buflen < sizeof(l_pData)) + { + i_parser.PrintHexDump(l_pBuffer, l_buflen); + break; + } + l_buflen -= sizeof(l_pData); + l_pBuffer += sizeof(l_pData); + l_mem >> l_pData; + + i_parser.PrintNumber("Primary Status ", "0x%04X", + (uint16_t)l_pData.primaryStatus); + i_parser.PrintNumber("Secondary Status ", "0x%04X", + (uint16_t)l_pData.secondaryStatus); + + //loop through the number of fields configured + uint32_t l_dumpFields = l_pData.dumpFields.get(); + while(l_dumpFields && !l_rc) + { + if(l_dumpFields & 0x0001) + { + if(l_buflen < sizeof(uint32_t)) + { + //Complete this loop and let the tools print as much data + //as possible but break from next loop + l_rc = -1; + } + sbeFFDCUserDataIdentifier_t l_ffdcUserDataId = {0}; + l_buflen -= sizeof(uint32_t); //l_ffdcUserDataId + l_pBuffer += sizeof(uint32_t); //l_ffdcUserDataId + + l_mem >> l_ffdcUserDataId; + + // TODO via RTC:158462 continue even for attribute dump + // Need to extend p9_xip_tool for partial attr dump handling + if((l_buflen < l_ffdcUserDataId.fieldLen) && + (l_ffdcUserDataId.fieldId != SBE_FFDC_TRACE_DUMP)) + { + i_parser.PrintHexDump(l_pBuffer, l_buflen); + break; + } + + l_buflen -= l_ffdcUserDataId.fieldLen; + l_pBuffer += l_ffdcUserDataId.fieldLen; + + l_mem.read(l_buffer, l_ffdcUserDataId.fieldLen); + std::ostringstream l_strFile; + //Generate temp dump file name + l_strFile << SBE_TEMP_DUMP_FILE; + + //Write dump into the temporary file + UtilFile l_fileObj(l_strFile.str().c_str()); + errlHndl_t l_errlHndl = l_fileObj.open("w"); + if ( l_errlHndl ) + { + std::cerr << "Error opening " + << l_strFile.str() << std::endl; + l_errlHndl->commit(HWSV_COMP_ID, ERRL_ACTION_REPORT); + delete l_errlHndl; + l_errlHndl = NULL; + i_parser.PrintHexDump(l_buffer, l_ffdcUserDataId.fieldLen); + return -1; + } + else + { + l_fileObj.write( l_buffer, l_ffdcUserDataId.fieldLen); + l_fileObj.Close(); + } + + //Specific handling + if(l_ffdcUserDataId.fieldId == SBE_FFDC_ATTR_DUMP) + { + SBE_PARSER_PRINT_HEADING(SBE_ATTR_DUMP_HEADLINE) + //command + std::ostringstream l_strCmd1; + // p9_xip_tool + // -ifs attrdump 2>&1 + l_strCmd1 << findSbeFile(P9_XIP_TOOL) + << " " + << findSbeFile(SBE_SEEPROM_BIN) + << " " + << P9_XIP_ATTR_CMD + << " " + << l_strFile.str().c_str() + << " " + << "2>&1"; + + //Call out the command + sbeParserSysCall( l_strCmd1.str().c_str() ); + } + else if(l_ffdcUserDataId.fieldId == SBE_FFDC_TRACE_DUMP) + { + SBE_PARSER_PRINT_HEADING(SBE_TRACE_HEADLINE) + //command + std::ostringstream l_strCmd1, l_strCmd2; + // ppe2fsp 2>&1 + l_strCmd1 << findSbeFile(PPE2FSP_TOOL) + << " " + << l_strFile.str().c_str() + << " " + << SBE_TRACE_BIN + << " " + << "2>&1"; + + // fsp-trace -s 2>&1 + l_strCmd2 << SBE_TRACE_CMD + << " " + << findSbeFile(SBE_STRING_FILE) + << " " + << SBE_TRACE_BIN + << " " + << "2>&1"; + + //Call out the commands + sbeParserSysCall( l_strCmd1.str().c_str() ); + sbeParserSysCall( l_strCmd2.str().c_str() ); + } + + //Delete the temp file + l_fileObj.Remove(); + } + l_dumpFields >>= 1; + if(l_rc != 0) + { + break; + } + } + } while(false); + + return l_rc; +} diff --git a/src/sbefw/pool.C b/src/sbefw/pool.C new file mode 100644 index 00000000..6695135a --- /dev/null +++ b/src/sbefw/pool.C @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/pool.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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 */ +#include +#include +#include +#include +#include "assert.h" + +namespace SBEVECTORPOOL +{ + +vectorMemPool_t g_pool[G_POOLSIZE]; + +vectorMemPool_t * allocMem() +{ + vectorMemPool_t *pool = NULL; + for( size_t idx = 0; idx < G_POOLSIZE; idx++ ) + { + if( 0 == g_pool[idx].refCount ) + { + pool = g_pool + idx; + g_pool[idx].refCount++; + break; + } + } + SBE_DEBUG(" Giving pool 0x%08X", pool); + return pool; +} + +void releaseMem( vectorMemPool_t * i_pool ) +{ + do + { + if ( NULL == i_pool ) break; + + // Assert here. This pool was not supposed to be in use. + assert( 0 != i_pool->refCount ) + SBE_DEBUG(" Releasing pool 0x%08X", i_pool); + i_pool->refCount--; + SBE_DEBUG(" In releaseMem() RefCount:%u", i_pool->refCount); + }while(0); +} + +} // namesspace SBEVECTORPOOL diff --git a/src/sbefw/pool.H b/src/sbefw/pool.H new file mode 100644 index 00000000..3968852c --- /dev/null +++ b/src/sbefw/pool.H @@ -0,0 +1,58 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/pool.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ + +#ifndef SBE_VECTOR_POOL_H +#define SBE_VECTOR_POOL_H + +namespace SBEVECTORPOOL +{ + +// Size of a block for a vector +static const size_t G_BLOCKSIZE = 512; + +//Pool size +static const size_t G_POOLSIZE = 4; + +typedef struct +{ + size_t refCount; + uint8_t data[G_BLOCKSIZE] __attribute__ ((aligned (8))); +}vectorMemPool_t; + +/** + * @brief Returns memory pool block. + * + * @return Memory block if available, NULL otherwise. + */ +vectorMemPool_t * allocMem(); + +/** + * @brief Release memory pool block. + * + * @param[in] i_pool pool pointer. + */ +void releaseMem( vectorMemPool_t * i_pool ); + +} // namespace SBEVECTORPOOL +#endif //SBE_VECTOR_POOL_H diff --git a/src/sbefw/sbeFFDC.C b/src/sbefw/sbeFFDC.C new file mode 100644 index 00000000..88bee00d --- /dev/null +++ b/src/sbefw/sbeFFDC.C @@ -0,0 +1,141 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeFFDC.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ +#include "sbefifo.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "sbeFifoMsgUtils.H" +#include "sberegaccess.H" +#include "sbeFFDC.H" + +/* + * @brief sendOverFIFO - method to pack and send SBE internal FFDC + * only if isSendInternalFFDCSet() is true + * over FIFO interface + * @param[in] i_primStatus - Primary status of Chip op + * @param[in] i_secStatus - Secondary status of Chip op + * @param[in] i_fieldsConfig - bitmap indicating the field + * to be sent in FFDC + * + * @param[out] o_bytesSent -number of bytes sent + * + * @return - SBE secondary RC + */ +uint32_t SbeFFDCPackage::sendOverFIFO(uint32_t i_primStatus, + uint32_t i_secStatus, + uint32_t i_fieldsConfig, + uint32_t &o_bytesSent) +{ + #define SBE_FUNC "sbeSendFFDCPackageFIFO " + SBE_ENTER(SBE_FUNC); + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t length = 0; + + do + { + //reset sent bytes + o_bytesSent = 0; + + //check if SBE internal FFDC should be generated + if(SbeRegAccess::theSbeRegAccess().isSendInternalFFDCSet() == false) + { + SBE_INFO(SBE_FUNC" isSendInternalFFDCSet()=false, " + "not generating SBE InternalFFDC"); + rc = SBE_SEC_OPERATION_SUCCESSFUL; + break; + } + + // update the primary and secondary status + iv_sbeFFDCDataHeader.primaryStatus = i_primStatus; + iv_sbeFFDCDataHeader.secondaryStatus = i_secStatus; + //Update the user data header with dump fields configuration + iv_sbeFFDCDataHeader.dumpFields.set(i_fieldsConfig); + iv_sbeFFDCHeader.lenInWords = (sizeof(sbeResponseFfdc_t) + + sizeof(sbeFFDCDataHeader_t)) + /sizeof(uint32_t); + //Update the length in ffdc package header base on required fields + for(auto &sbeFFDCUserData:sbeFFDCUserDataArray) + { + if(sbeFFDCUserData.userDataId.fieldId & i_fieldsConfig) + { + iv_sbeFFDCHeader.lenInWords += + (sbeFFDCUserData.userDataId.fieldLen + + sizeof(sbeFFDCUserDataIdentifier_t)) + /sizeof(uint32_t); + } + } + + //Send FFDC package header + length = sizeof(iv_sbeFFDCHeader) / sizeof(uint32_t); + rc = sbeDownFifoEnq_mult(length, + (uint32_t *)(&(iv_sbeFFDCHeader))); + if( rc!= SBE_SEC_OPERATION_SUCCESSFUL) + { + break; + } + o_bytesSent += length; + + //Send FFDC user data header + length = sizeof(iv_sbeFFDCDataHeader) / sizeof(uint32_t); + rc = sbeDownFifoEnq_mult(length, + (uint32_t *)(&(iv_sbeFFDCDataHeader))); + if( rc!= SBE_SEC_OPERATION_SUCCESSFUL) + { + break; + } + o_bytesSent += length; + + //Send FFDC user data blobs + for(auto &sbeFFDCUserData:sbeFFDCUserDataArray) + { + if(sbeFFDCUserData.userDataId.fieldId & i_fieldsConfig) + { + //Send User data identifer and length + length = sizeof(sbeFFDCUserDataIdentifier_t) / sizeof(uint32_t); + rc = sbeDownFifoEnq_mult(length, + (uint32_t*)&(sbeFFDCUserData.userDataId)); + if( rc!= SBE_SEC_OPERATION_SUCCESSFUL) + { + break; + } + o_bytesSent += length; + + //Send User data + length = sbeFFDCUserData.userDataId.fieldLen / sizeof(uint32_t); + rc = sbeDownFifoEnq_mult(length, + (uint32_t*)sbeFFDCUserData.userDataPtr); + if( rc!= SBE_SEC_OPERATION_SUCCESSFUL) + { + break; + } + o_bytesSent += length; + } + } + + SBE_INFO(SBE_FUNC "Number of words sent [%d]", o_bytesSent); + } while(false); + + SBE_EXIT(SBE_FUNC); + return rc; + #undef SBE_FUNC +} diff --git a/src/sbefw/sbeFFDC.H b/src/sbefw/sbeFFDC.H new file mode 100644 index 00000000..514b9caf --- /dev/null +++ b/src/sbefw/sbeFFDC.H @@ -0,0 +1,125 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeFFDC.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ +#ifndef __SBE_FFDC_H +#define __SBE_FFDC_H + +#include "fapi2.H" +#include "plat_attributes.H" +#include "pk_trace.h" +#include "sbeFFDCType.H" +#include "sbeSpMsg.H" + +//PIBMEM attribute dump +extern G_sbe_attrs_t G_sbe_attrs; + +//Configuration of user data blobs present in SBE FFDC +//Data is sent in the order defined here +//Definition - Identifier +// length of the blob +// pointer to the data +const sbeFFDCUserData_t sbeFFDCUserDataArray[] = + {{{SBE_FFDC_TRACE_DUMP, + sizeof(PkTraceBuffer)}, + (const void *)&g_pk_trace_buf, + }, + {{SBE_FFDC_ATTR_DUMP, + sizeof(G_sbe_attrs_t)}, + (const void *)&G_sbe_attrs, + }, + }; + +//SBE internal FFDC package class +class SbeFFDCPackage +{ +private: + //Disable copy constructor + SbeFFDCPackage(SbeFFDCPackage const &) = delete; + //Disable assignment operator + SbeFFDCPackage& operator=(SbeFFDCPackage const &) = delete; + + sbeResponseFfdc_t iv_sbeFFDCHeader; + //FFDC user data header + sbeFFDCDataHeader_t iv_sbeFFDCDataHeader; + +public: + /*ctor + * + */ + SbeFFDCPackage() + { + //Making sure data is indeed aligned + static_assert((sizeof(G_sbe_attrs_t) % 4) == 0, + "G_sbe_attrs not 4byte aligned"); + static_assert((sizeof(PkTraceBuffer) % 4) == 0, + "g_pk_trace_buf not 4byte aligned"); + + iv_sbeFFDCHeader.magicBytes = 0xFFDC; + iv_sbeFFDCHeader.fapiRc = fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA; + + iv_sbeFFDCDataHeader.primaryStatus = SBE_PRI_OPERATION_SUCCESSFUL; + iv_sbeFFDCDataHeader.secondaryStatus = SBE_SEC_OPERATION_SUCCESSFUL; + + //length and dumpFields will be filled up depending on the fields + //to be sent in send APIs + iv_sbeFFDCDataHeader.dumpFields = {0}; + } + /* + * @brief sendOverFIFO - method to pack and send SBE internal FFDC + * only if isSendInternalFFDCSet() is true + * over FIFO interface + * @param[in] i_primStatus - Primary status of Chip op + * @param[in] i_secStatus - Secondary status of Chip op + * @param[in] i_fieldsConfig - bitmap indicating the field + * to be sent in FFDC + * + * @param[out] o_bytesSent -number of bytes sent + * + * @return - SBE secondary RC + */ + uint32_t sendOverFIFO(uint32_t i_primStatus, + uint32_t i_secStatus, + uint32_t i_fieldsConfig, + uint32_t &o_bytesSent); + + /* TODO via RTC:150786 + * @brief sendOverHOST - method to pack and send SBE internal FFDC + * only if isSendInternalFFDCSet() is true + * over HOST interface + * + * @param[in] i_primStatus - Primary status of Chip op + * @param[in] i_secStatus - Secondary status of Chip op + * @param[in] i_fieldsConfig - bitmap indicating the field + * to be sent in FFDC + * + * @param[out] o_bytesSent - number of bytes sent + * + * @return - SBE secondary RC + */ + //uint32_t sendOverHOST(uint32_t i_primStatus, + // uint32_t i_secStatus, + // uint32_t i_fieldsConfig, + // uint32_t &o_bytesSent) {}; +}; + +#endif //__SBE_FFDC_H diff --git a/src/sbefw/sbeFFDCType.H b/src/sbefw/sbeFFDCType.H new file mode 100644 index 00000000..f4ef95ad --- /dev/null +++ b/src/sbefw/sbeFFDCType.H @@ -0,0 +1,100 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeFFDCType.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ +#ifndef __SBE_FFDC_TYPE_H +#define __SBE_FFDC_TYPE_H + +//Bit mapped identifiers +#define SBE_FFDC_ATTR_DUMP 0x0001 +#define SBE_FFDC_TRACE_DUMP 0x0002 +#define SBE_FFDC_ALL_DUMP 0xFFFF + +/* Structure indicating the contents of FFDC package + * value 'true' - field present;value 'false' - field not present + * bit_0 - attribute dump + * bit_1 - trace buffer dump + * bit 2-31 - reserved + */ +typedef struct +{ + uint32_t attrField:1; + uint32_t traceField:1; + uint32_t reserved:30; + /* @breif - set dump fields + * + * @param[in] - uint32_t value to be updated + */ + void set(uint32_t val) + { + if(val & SBE_FFDC_ATTR_DUMP) + { + attrField = true; + } + if(val & SBE_FFDC_TRACE_DUMP) + { + traceField = true; + } + } + /* @brief - get dump fields as uint32_t + * + * @return - uint32_t value + */ + uint32_t get() + { + uint32_t l_val = 0; + if(attrField) + { + l_val |= SBE_FFDC_ATTR_DUMP; + } + if(traceField) + { + l_val |= SBE_FFDC_TRACE_DUMP; + } + return l_val; + } +} sbeFFDCDumpFields_t; + +//Sturcture indicating the type of ffdc user data blob +//and its length in bytes +typedef struct +{ + uint32_t fieldId:16; + uint32_t fieldLen:16; +} sbeFFDCUserDataIdentifier_t; + +//Structure of ffdc user data blob +typedef struct +{ + sbeFFDCUserDataIdentifier_t userDataId; + const void *userDataPtr; +} sbeFFDCUserData_t; + +//keep it packed to 4byte boundary to avoid packing bytes +typedef struct +{ + uint32_t primaryStatus:16;//Chip Op Primary status + uint32_t secondaryStatus:16;//Chip Op Secondary status + sbeFFDCDumpFields_t dumpFields;//bitmapped dumpFields +} sbeFFDCDataHeader_t; + +#endif //__SBE_FFDC_TYPE_H diff --git a/src/sbefw/sbeFifoMsgUtils.C b/src/sbefw/sbeFifoMsgUtils.C new file mode 100644 index 00000000..99cf2709 --- /dev/null +++ b/src/sbefw/sbeFifoMsgUtils.C @@ -0,0 +1,375 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeFifoMsgUtils.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbeFifoMsgUtils.C + * + * @brief This file contains the SBE FIFO Access Common Utility Functions + * + */ + +#include "sbefifo.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "sbeFifoMsgUtils.H" +#include "sbeerrorcodes.H" +#include "assert.h" +#include "sbeFFDC.H" + +// If we can not perform FIFO operation ( FIFO FULL while writing +// or EMPTY while reading ) we will sleep for FIFO_WAIT_SLEEP_TIME +// ms so that FIFO can be ready. +static const uint32_t FIFO_WAIT_SLEEP_TIME = 1; +// Write this data to send EOT to DS FIFO. The register to send EOT +// is 32 bit only. But our scom operations are 64 bit. So set a bit +// in higher word to trigger EOT. +static const uint64_t DOWNSTREAM_EOT_DATA = 0x100000000ull; + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeUpFifoDeq_mult (uint32_t &io_len, + uint32_t *o_pData, + const bool i_isEotExpected, + const bool i_flush) +{ + #define SBE_FUNC " sbeUpFifoDeq_mult " + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t l_len = 0; + + // If Caller didn't request flush operation + // and passed a non-zero valid length, we + // would expect a valid buffer + if ((!i_flush) && (io_len > 0)) + { + assert ( NULL != o_pData) + } + + do + { + sbeFifoEntry_t l_data = {0}; + + // Read Double word from the Upstream FIFO; + // The DW data represents the first 32 bits of data word entry + // followed by the status bits. + + // Bit 0-31 : Data + // Bit 32 : Data valid flag + // Bit 33 : EOT flag + // Bit 34-63 : Status (2-31) + // Valid : EOT + // 1 : 0 -> data=message + // 0 : 1 -> data=dummy_data of EOT operation + // 0 : 0 -> data=dummy_data + // 1 : 1 -> Not used + + l_rc = sbeUpFifoDeq ( reinterpret_cast(&l_data) ); + + if (l_rc) + { + // Error while dequeueing from upstream FIFO + SBE_ERROR(SBE_FUNC"sbeUpFifoDeq failed," + "l_rc=[0x%08X]", l_rc); + // @TODO RTC via : 132295 + // RC refactoring - reserve 3 bits in SBE RC for PCBPIB + l_rc = SBE_SEC_FIFO_ACCESS_FAILURE; + break; + } + + SBE_DEBUG(SBE_FUNC"sbeUpFifoDeq, " + "l_data.fifo_data=[0x%08X],", + l_data.fifo_data); + + // If FIFO reset is requested + if(l_data.statusOrReserved.req_upfifo_reset) + { + // @TODO via RTC : 126147 + // Review reset loop flow in here. + // Received a FIFO reset request + l_rc = SBE_FIFO_RESET_RECEIVED; + break; + } + + // if EOT flag is set, clear EOT and + // set the RC accordingly + if (l_data.statusOrReserved.eot_flag) + { + l_rc = sbeUpFifoAckEot(); + if (l_rc) + { + // Error while ack'ing EOT in upstream FIFO + SBE_ERROR(SBE_FUNC"sbeUpFifoAckEot failed," + "l_rc=[0x%08X]", l_rc); + + // Collect FFDC and save off the l_rc + l_rc = SBE_SEC_FIFO_ACCESS_FAILURE; + break; + } + + // Successfully Ack'ed the EOT in upstream FIFO + if ( ((!i_isEotExpected) || (l_len != io_len)) + && (!i_flush) ) + { + if (l_len < io_len) + { + // Unexpected EOT, got insufficient data + l_rc = SBE_SEC_UNEXPECTED_EOT_INSUFFICIENT_DATA ; + } + else + { + // Unexpected EOT, got excess data + l_rc = SBE_SEC_UNEXPECTED_EOT_EXCESS_DATA ; + } + } + break; + } + + // if Upstream FIFO is empty, + if (l_data.statusOrReserved.fifo_empty) + { + pk_sleep(PK_MILLISECONDS(FIFO_WAIT_SLEEP_TIME)); + continue; + } + + if ((!i_flush) && (l_len < io_len)) + { + o_pData[l_len] = l_data.fifo_data; + } + + ++l_len; + + } while(i_flush || i_isEotExpected || (l_len < io_len)); + + // Return the length of entries dequeued. + io_len = l_len; + return l_rc; + + #undef SBE_FUNC +} + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeDownFifoEnq_mult (uint32_t &io_len, + const uint32_t *i_pData) +{ + #define SBE_FUNC " sbeDownFifoEnq_mult " + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t l_len = 0; + + do + { + sbeDownFifoStatusReg_t l_status = {0}; + + // Read the down stream FIFO status + l_rc = sbeDownFifoGetStatus (reinterpret_cast(&l_status)); + if (l_rc) + { + // Error while reading downstream FIFO status + SBE_ERROR(SBE_FUNC"sbeDownFifoGetStatus failed, " + "l_rc=[0x%08X]", l_rc); + l_rc = SBE_SEC_FIFO_ACCESS_FAILURE; + break; + } + + // Check if there was a FIFO reset request from SP + if (l_status.downfifo_status.req_upfifo_reset) + { + // @TODO via RTC : 126147 + // Review reset loop flow in here. + // Received an upstream FIFO reset request + SBE_ERROR(SBE_FUNC"Received reset request"); + l_rc = SBE_FIFO_RESET_RECEIVED; + break; + } + + // Check if downstream FIFO is full + if (l_status.downfifo_status.fifo_full) + { + // Downstream FIFO is full + pk_sleep(PK_MILLISECONDS(FIFO_WAIT_SLEEP_TIME)); + continue; + } + + // PIB write data format: + // Bit 0 - 31 : Data + // Bit 32 - 63 : Unused + + sbeFifoEntry_t l_data = {0}; + + l_data.fifo_data = *(i_pData+l_len); + + SBE_DEBUG(SBE_FUNC"Downstream fifo data entry[0x%08X]", + l_data.fifo_data); + + // Write the data into the downstream FIFO + uint64_t * tp = reinterpret_cast(&l_data); + l_rc = sbeDownFifoEnq ( *tp ); + if (l_rc) + { + SBE_ERROR(SBE_FUNC"sbeDownFifoEnq failed, " + "l_rc[0x%08X]", l_rc); + // @TODO RTC via : 132295 + // RC refactoring - reserve 3 bits in SBE RC for PCBPIB + l_rc = SBE_SEC_FIFO_ACCESS_FAILURE; + break; + } + + ++l_len; + + } while(l_len(&l_status)); + if (l_rc) + { + // Error while reading downstream FIFO status + SBE_ERROR(SBE_FUNC"sbeDownFifoGetStatus failed, " + "l_rc=[0x%08X]", l_rc); + l_rc = SBE_SEC_FIFO_ACCESS_FAILURE; + break; + } + + // Check if downstream FIFO is full + if (l_status.downfifo_status.fifo_full) + { + pk_sleep(PK_MILLISECONDS(FIFO_WAIT_SLEEP_TIME)); + continue; + } + l_rc = putscom_abs(SBE_DOWNSTREAM_FIFO_SIGNAL_EOT, DOWNSTREAM_EOT_DATA); + break; + } while(1); + + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + + +uint32_t sbeDsSendRespHdr(const sbeRespGenHdr_t &i_hdr, + const sbeResponseFfdc_t &i_ffdc ) +{ + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + do + { + uint32_t distance = 1; //initialise by 1 for entry count itself. + uint32_t len = sizeof( i_hdr )/sizeof(uint32_t); + // sbeDownFifoEnq_mult. + rc = sbeDownFifoEnq_mult ( len, ( uint32_t *) &i_hdr); + if (rc) + { + break; + } + distance += len; + + // If no ffdc , exit; + if( i_ffdc.getRc() ) + { + len = sizeof(i_ffdc)/sizeof(uint32_t); + rc = sbeDownFifoEnq_mult ( len, ( uint32_t *) &i_ffdc); + if (rc) + { + break; + } + distance += len; + } + + // If there is a SBE internal failure + if((i_hdr.primaryStatus != SBE_PRI_OPERATION_SUCCESSFUL) ||\ + (i_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL)) + { + //Add FFDC data as well. + //Generate all the fields of FFDC package + SbeFFDCPackage sbeFfdc; + rc = sbeFfdc.sendOverFIFO(i_hdr.primaryStatus, + i_hdr.secondaryStatus, + SBE_FFDC_ALL_DUMP, + len); + if (rc) + { + break; + } + distance += len; + } + + len = sizeof(distance)/sizeof(uint32_t); + rc = sbeDownFifoEnq_mult ( len, &distance); + if (rc) + { + break; + } + + }while(0); + return rc; +} diff --git a/src/sbefw/sbeFifoMsgUtils.H b/src/sbefw/sbeFifoMsgUtils.H new file mode 100644 index 00000000..60492964 --- /dev/null +++ b/src/sbefw/sbeFifoMsgUtils.H @@ -0,0 +1,192 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeFifoMsgUtils.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbeFifoMsgUtils.H + * + * @brief This file contains the SBE FIFO Access Common Utility Functions + * + */ + +#ifndef __SBEFW_SBEFIFOMSGUTILS_H +#define __SBEFW_SBEFIFOMSGUTILS_H + +#include +#include "sbeexeintf.H" + + +/**********************************************************************/ +// SBE Utilities +/**********************************************************************/ + +/** + * @brief sbeUpFifoDeq_mult : Dequeue multiple entries from upstream FIFO + * + * @param[in/out] io_len + * On input: Non-zero number of entries (excluding EOT) to dequeue. + * Ignored when i_flush == true. + * On output: Number of entries dequeued (excluding EOT). + * @param[out] o_pData Entries dequeued into the buffer + * @param[in] i_isEotExpected true / false + * true - Default case. + * Caller expects an EOT entry after io_len entries are + * dequeued. Accordingly, this function will attempt to dequeue + * the EOT entry after io_len entries are dequeued. + * false - Caller doesn't expect an EOT after io_len entries are + * dequeued. Accordingly, this function will not attempt to + * dequeue the EOT entry after io_len entries are dequeued. + * @param[in] i_flush true / false + * true - caller requested FIFO flush + * Usually caller marks this flag as true to handle error scenario. + * All entries written in the US fifo (until an EOT is encountered), + * would be dequeued and discarded (not processed). Note that io_len + * and i_isEotExpected inputs are ignored in this case. + * However, flag i_isEotExpected is always interpreted as true in + * case. + * false - Default good path. + * US Fifo entries will be dequeued and processed per inputs io_len + * and i_isEotExpected. + * + * @return Return Code SUCCESS or a secondary response code + * SBE_SEC_OPERATION_SUCCESSFUL + * SBE_SEC_FIFO_ACCESS_FAILURE + * SBE_SEC_UNEXPECTED_EOT_INSUFFICIENT_DATA + * SBE_SEC_UNEXPECTED_EOT_EXCESS_DATA + * SBE_FIFO_RESET_RECEIVED + * + */ +extern uint32_t sbeUpFifoDeq_mult (uint32_t &io_len, + uint32_t *o_pData, + const bool i_isEotExpected = true, + const bool i_flush = false); + + +/** + * @brief sbeDownFifoEnq_mult : Enqueue into downstream FIFO + * + * @param[in/out] io_len number of entries to enqueue as input, + * number of entries enqueued as output + * @param[in] i_pData buffer containting data to be enqueued + * + * @return Rc SUCCESS or a secondary response code + * SBE_SEC_OPERATION_SUCCESSFUL + * SBE_SEC_FIFO_ACCESS_FAILURE + * SBE_FIFO_RESET_RECEIVED + * + */ +extern uint32_t sbeDownFifoEnq_mult (uint32_t &io_len, + const uint32_t *i_pData) ; + + +/** + * @brief sbeBuildRespHeaderMagicCodeCmdClass + * Builds the header word containing the magic code, + * the command class and the opcode + * + * @return Returns the header word in the response header + * containing the magic code, command class and opcode + * + */ +extern inline uint32_t sbeBuildRespHeaderMagicCodeCmdClass (void) +{ + return ( (0xC0DE0000) | + (uint32_t)(g_sbeFifoCmdHdr.cmdClass << 8) | + (uint32_t)(g_sbeFifoCmdHdr.command)); +} + +/** + * @brief sbeBuildRespHeaderStatusWordGlobal + * Builds the status header word from global variables + * + * @return Returns the status word in the response header + * + */ +extern inline uint32_t sbeBuildRespHeaderStatusWordGlobal (void) +{ + return ( (((uint32_t)g_sbeCmdRespHdr.prim_status)<<16) | + (g_sbeCmdRespHdr.sec_status) ); +} + +/** + * @brief sbeBuildRespHeaderStatusWordLocal + * Builds the status header word from passed in parameters + * + * @param[in] const uint16_t i_primStatus Primary Response Status Code + * @param[in] const uint16_t i_secStatus Secondary Response Status Code + * + * @return Returns the status word in the response header + * + */ +extern inline uint32_t sbeBuildRespHeaderStatusWordLocal ( + const uint16_t i_primStatus, + const uint16_t i_secStatus) +{ + return ( (((uint32_t)i_primStatus)<<16) | (i_secStatus) ); +} + +/** + * @brief sbeBuildMinRespHdr : Builds minimum response header + * + * @desc This builds the buffer with the following status words + * - Magic Bytes, Command Class, Command opcode + * - Primary Status Code, Secondary Status Code + * - PCB / PIB Status Code [optional] + * - Distance to Status Header + * @param[in/out] uint32_t *io_pBuf Buffer to be filled in + * @param[in/out] uint32_t &io_curIndex Current Index into the buffer + * @param[in] const uint16_t i_primStatus Primary Response Status Code + * @param[in] const uint16_t i_secStatus Secondary Response Status Code + * @param[in] const uint32_t i_pcbpibStatus PCB-PIB Response Status Code + * @param[in] const uint32_t i_startIndex Starting Index into the buffer + */ + +void sbeBuildMinRespHdr ( uint32_t *io_pBuf, + uint32_t &io_curIndex, + const uint16_t i_primStatus, + const uint16_t i_secStatus, + const uint32_t i_pcbpibStatus, + const uint32_t i_startIndex = 0 ); + +/** + * @brief sbeDownFifoSignalEot : Signal EOT in Downstream FIFO + * + * @return Rc from the underlying scom utility + * + * @note This is a blocking call. If FIFO is full, it will wait + * in loop ( sleep ) till the time there is some space in + * FIFO. + */ +uint32_t sbeDownFifoSignalEot (void); + +/** + * @brief sbeDsSendRespHdr : Send response header to DS FIFO + * - This also sends the FFDC if exist. + * + * @param[in] i_hdr Response Header + * @param[in] i_ffdc FFDC object + * + * @return Rc from the underlying scom utility + */ +uint32_t sbeDsSendRespHdr(const sbeRespGenHdr_t &i_hdr, + const sbeResponseFfdc_t &i_ffdc ); +#endif // __SBEFW_SBEFIFOMSGUTILS_H diff --git a/src/sbefw/sbeHostMsg.H b/src/sbefw/sbeHostMsg.H new file mode 100644 index 00000000..3467d59c --- /dev/null +++ b/src/sbefw/sbeHostMsg.H @@ -0,0 +1,132 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeHostMsg.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbeHostMsg.H + * + * @brief This file contains the message structures for SBE Host + * communication. + * + */ + +#ifndef __SBEFW_SBEHOST_MSG_H +#define __SBEFW_SBEHOST_MSG_H + +#include +#include "sbe_host_intf.H" +#include "sbe_sp_intf.H" + +/*****************************************************************/ +/* SBE->PSU request structures */ +/*****************************************************************/ + +/** + * @brief structure for Host->SBE command request format denoting + * mininum header (as of now, contained in mbx 0) + */ +typedef struct +{ + // mbxReg0 + uint64_t res:16; + uint64_t flags:16; + uint64_t seqID:16; + uint64_t cmdClass:8; + uint64_t command:8; + + /** + * @brief initialize the fields contained in PSU Mbx0 + * + */ + void init() + { + res = 0; + flags = 0; + seqID = 0; + cmdClass = SBE_PSU_CMD_CLASS_UNKNOWN; + command = SBE_PSU_CMD_UNKNOWN; + } +} sbePsu2SbeCmdReqHdr_t; + +extern sbePsu2SbeCmdReqHdr_t g_sbePsu2SbeCmdReqHdr; + + +/*****************************************************************/ +/* SBE->PSU response structures */ +/*****************************************************************/ + +/** + * @brief SBE->Host Generic response structure + * + */ +typedef struct +{ + uint64_t mbxReg4; + uint64_t mbxReg5; + uint64_t mbxReg6; + uint64_t mbxReg7; +} sbeSbe2PsuGenericResp_t ; + +/** + * @brief Structure for SBE->Host response header contained in + * mbx4 register + * + */ +typedef struct +{ + // mbxReg 4 + uint64_t primStatus:16; + uint64_t secStatus:16; + uint64_t seqID:16; + uint64_t cmdClass:8; + uint64_t command:8; + + /** + * @brief set the primary and secondary status + * + * @param[in] i_prim Primary status + * @param[in] i_sec Secondary status + * + */ + void setStatus(const uint16_t i_prim, const uint16_t i_sec) + { + primStatus = i_prim; + secStatus = i_sec; + } + + /** + * @brief initialize the response fields contained in PSU Mbx3 + * + */ + void init() + { + primStatus = SBE_PRI_OPERATION_SUCCESSFUL; + secStatus = SBE_SEC_OPERATION_SUCCESSFUL; + seqID = g_sbePsu2SbeCmdReqHdr.seqID; + cmdClass = g_sbePsu2SbeCmdReqHdr.cmdClass; + command = g_sbePsu2SbeCmdReqHdr.command; + } +} sbeSbe2PsuRespHdr_t; + +extern sbeSbe2PsuRespHdr_t g_sbeSbe2PsuRespHdr; + +#endif // __SBEFW_SBEHOST_MSG_H diff --git a/src/sbefw/sbeHostUtils.C b/src/sbefw/sbeHostUtils.C new file mode 100644 index 00000000..3e4605d0 --- /dev/null +++ b/src/sbefw/sbeHostUtils.C @@ -0,0 +1,226 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeHostUtils.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbeHostUtils.C + * + * @brief This file contains the PSU Access Utility Functions + * + */ + +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "sbeHostUtils.H" +#include "sbeHostMsg.H" +#include "sbe_host_intf.H" +#include "sbeerrorcodes.H" +#include "assert.h" +#include "fapi2.H" + + +/////////////////////////////////////////////////////////////////// +// PSU->SBE register access utilities +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +uint32_t sbeReadPsu2SbeMbxReg (uint32_t i_addr, + const uint8_t i_count, + uint64_t *o_pData, + bool i_isFinalRead) +{ + #define SBE_FUNC " sbeReadPsu2SbeMbxReg " + SBE_DEBUG(SBE_FUNC"i_count[0x%02X], i_addr=[0x%08X]", i_count, i_addr); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint8_t l_count = 0; + + assert((i_count >0 ) && (NULL != o_pData)) + assert( (SBE_HOST_PSU_MBOX_REG0 <= i_addr) && + (SBE_HOST_PSU_MBOX_REG3 >= (i_addr + i_count - 1)) ) + + while (l_count < i_count) + { + l_rc = getscom_abs ( i_addr, + reinterpret_cast(&o_pData[l_count]) ); + + if (l_rc) + { + // Error while reading from PSU->SBE mbx register + SBE_ERROR(SBE_FUNC"getscom_abs failed," + "l_rc=[0x%08X], i_addr=[0x%08X]", + l_rc, i_addr); + break; + } + + SBE_DEBUG(SBE_FUNC"l_data=[0x%08X%08X]", + SBE::higher32BWord(o_pData[l_count]), + SBE::lower32BWord(o_pData[l_count])); + ++l_count; + ++i_addr; + } + + // Set the Ack bit in SBE->PSU DB register + // if the message requires ack and if its a final read operation + if ((i_isFinalRead) && (SBE_SEC_OPERATION_SUCCESSFUL == l_rc)) + { + l_rc = sbeAcknowledgeHost(); + if (l_rc) + { + SBE_ERROR(SBE_FUNC " Failed to Sent Ack to Host over " + "SBE_SBE2PSU_DOORBELL_SET_BIT1"); + } + } + return l_rc; + + #undef SBE_FUNC +} + +/////////////////////////////////////////////////////////////////// +// SBE->PSU register access utilities +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +uint32_t sbeIntrHostUponRespWaiting () +{ + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + // Interrupt the host by setting bit0 in SBE->PSU DB register + // if the caller requested for it. + if (g_sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_RESP_REQUIRED) + { + l_rc = sbeSetSbe2PsuDbBitX(SBE_SBE2PSU_DOORBELL_SET_BIT0); + } + return l_rc; +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +uint32_t sbeAcknowledgeHost () +{ + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + // Set the Ack bit in SBE->PSU DB register + // if the caller requested for it. + if (g_sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_ACK_REQUIRED) + { + l_rc = sbeSetSbe2PsuDbBitX(SBE_SBE2PSU_DOORBELL_SET_BIT1); + } + return l_rc; +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +uint32_t sbeWriteSbe2PsuMbxReg (uint32_t i_addr, + const uint64_t *i_pData, + const uint8_t i_count, + bool i_setBit0ToIntrHB) +{ + #define SBE_FUNC " sbeWriteSbe2PsuMbxReg " + SBE_DEBUG(SBE_FUNC"i_count[0x%02X], i_addr=[0x%08X]", i_count, i_addr); + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint8_t l_count = 0; + + assert( (i_count >0 ) && (NULL != i_pData) ) + assert( (SBE_HOST_PSU_MBOX_REG4 <= i_addr) && + (SBE_HOST_PSU_MBOX_REG7 >= (i_addr + i_count - 1)) ) + + if( g_sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_RESP_REQUIRED ) + { + while (l_count < i_count) + { + SBE_DEBUG(SBE_FUNC"l_data=[0x%08X%08X]", + SBE::higher32BWord(*(i_pData+l_count)), + SBE::lower32BWord(*(i_pData+l_count))); + + l_rc = putscom_abs ( i_addr, *(i_pData+l_count) ); + if (l_rc) + { + // Error while reading from PSU->SBE mbx register + SBE_ERROR(SBE_FUNC"putscom_abs failed," + "l_rc=[0x%08X], i_addr=[0x%08X]", + l_rc, i_addr); + break; + } + + ++l_count; + ++i_addr; + } + + if( (i_setBit0ToIntrHB) && (SBE_SEC_OPERATION_SUCCESSFUL == l_rc) ) + { + // indicate the Host via Bit SBE_SBE2PSU_DOORBELL_SET_BIT0 + l_rc = sbeSetSbe2PsuDbBitX(SBE_SBE2PSU_DOORBELL_SET_BIT0); + if(l_rc) + { + SBE_ERROR(SBE_FUNC " Failed to Sent Ack to Host over " + "SBE_SBE2PSU_DOORBELL_SET_BIT0"); + } + } + } + return l_rc; + + #undef SBE_FUNC +} + +/* @brief - Send PSU Chip Op response + * + * @param[in] - i_sbe2PsuRespHdr - Response header + * @param[in] - i_fapiRc - fapi rc of the relevant hwp call + * @param[in/out] - io_rc - rc status of the PSU access utility + * + * @return - void + */ +void sbePSUSendResponse(sbeSbe2PsuRespHdr_t &i_sbe2PsuRespHdr, + uint32_t &i_fapiRc, + uint32_t &io_rc) +{ +#define SBE_FUNC "sbePSUSendResponse" + do + { + // Making sure the PSU access utility is functional + if(io_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + break; + } + // TODO via RTC:151555 Generate FFDC + if(i_fapiRc != fapi2::FAPI2_RC_SUCCESS) + { + i_sbe2PsuRespHdr.setStatus(SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + } + + // Send the response header + io_rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4, + (uint64_t*)(&i_sbe2PsuRespHdr), + (sizeof(i_sbe2PsuRespHdr)/sizeof(uint64_t)), + true); + if(SBE_SEC_OPERATION_SUCCESSFUL != io_rc) + { + SBE_ERROR(SBE_FUNC" Failed to write to " + "SBE_HOST_PSU_MBOX_REG4"); + } + } while(0); +#undef SBE_FUNC +} diff --git a/src/sbefw/sbeHostUtils.H b/src/sbefw/sbeHostUtils.H new file mode 100644 index 00000000..efca6bf4 --- /dev/null +++ b/src/sbefw/sbeHostUtils.H @@ -0,0 +1,244 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeHostUtils.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbeHostUtils.H + * + * @brief This file contains basic SBE PSU hardware specific + * definitions and operations. + * + */ + +#ifndef __SBEFW_SBEHOSTUTILS_H +#define __SBEFW_SBEHOSTUTILS_H + +#include +#include "ppe42_scom.h" +#include "sbeHostMsg.H" + +/** + * @brief SBE PSU Access register addresses + * + */ +const uint32_t SBE_HOST_PSU_BASE = 0x000D0050; + +const uint32_t SBE_HOST_PSU_MBOX_REG0 = SBE_HOST_PSU_BASE + 0x0000; +const uint32_t SBE_HOST_PSU_MBOX_REG1 = SBE_HOST_PSU_BASE + 0x0001; +const uint32_t SBE_HOST_PSU_MBOX_REG2 = SBE_HOST_PSU_BASE + 0x0002; +const uint32_t SBE_HOST_PSU_MBOX_REG3 = SBE_HOST_PSU_BASE + 0x0003; +const uint32_t SBE_HOST_PSU_MBOX_REG4 = SBE_HOST_PSU_BASE + 0x0004; +const uint32_t SBE_HOST_PSU_MBOX_REG5 = SBE_HOST_PSU_BASE + 0x0005; +const uint32_t SBE_HOST_PSU_MBOX_REG6 = SBE_HOST_PSU_BASE + 0x0006; +const uint32_t SBE_HOST_PSU_MBOX_REG7 = SBE_HOST_PSU_BASE + 0x0007; + + +const uint32_t SBE_PSU2SBE_DOORBELL_REG_RW = 0x000D0060; +const uint32_t SBE_PSU2SBE_DOORBELL_REG_AND = 0x000D0061; +const uint32_t SBE_PSU2SBE_DOORBELL_REG_OR = 0x000D0062; +const uint32_t SBE_PSU2HOST_DOORBELL_REG_RW = 0x000D0063; +const uint32_t SBE_PSU2HOST_DOORBELL_REG_AND = 0x000D0064; +const uint32_t SBE_PSU2HOST_DOORBELL_REG_OR = 0x000D0065; + + +/** + * @brief SBE PSU door bell register Bit definitions + */ +typedef enum +{ + // Bit 0 AND flag for PSU->SBE Doorbell Register; + // When this is set by the host firmware, it would trigger an + // interrupt to the SBE about a waiting message in the Host/SBE + // Mailbox Registers. SBE is responsible for clearing this + // bit upon being interrupted. + SBE_PSU2SBE_DOORBELL_CLEAR_BIT0 = 0x7FFFFFFFFFFFFFFFull, +} sbe_psu2sbeDoorbellReg_UpdateFlags; + +typedef enum +{ + // Bit 0 OR flag for SBE->PSU Doorbell Register; + // When this is set by SBE, it would trigger an interrupt to host + // firmware about a waiting response in the Host/SBE Mailbox Registers 4-7 + SBE_SBE2PSU_DOORBELL_SET_BIT0 = 0x8000000000000000ull, + + // Bit 1 OR flag for SBE->PSU Doorbell Register; + // When this is set by SBE, it would trigger an interrupt to host + // firmware indicating that the message in Host/SBE mailbox registers 0-3 + // has been read by SBE and is being processed + SBE_SBE2PSU_DOORBELL_SET_BIT1 = 0x4000000000000000ull, + + // Bit 2 OR flag for SBE->PSU Doorbell Register; + // When this is set by SBE, it would trigger an interrupt to host + // firmware to trigger Stop15 exit on thread 0 on the master core. + // This would be used to trigger hostboot in istep 16 + SBE_SBE2PSU_DOORBELL_SET_BIT2 = 0x2000000000000000ull, +} sbe_sbe2psuDoorbellReg_UpdateFlags; + + +/*****************************************************************/ +/** PSU->SBE register access utilities **/ +/*****************************************************************/ + +/** + * @brief sbeClearPsu2SbeDbBitX : Clear given bit in PSU->SBE DB register + * + * @param[in] 64-Bit Scom Data indicating bit position to be cleared + * + * @return RC from the underlying scom utility + * + */ +inline uint32_t sbeClearPsu2SbeDbBitX (const uint64_t i_bit) +{ + return putscom_abs (SBE_PSU2SBE_DOORBELL_REG_AND, i_bit) ; +} + + +/** + * @brief sbeReadPsu2SbeDbReg : Read PSU->SBE DB register + * + * @param[out] 64-Bit Data read from PSU->SBE DB register + * + * @return RC from the underlying scom utility + * + */ +inline uint32_t sbeReadPsu2SbeDbReg (uint64_t *o_data) +{ + return getscom_abs (SBE_PSU2SBE_DOORBELL_REG_RW, o_data) ; +} + + +/** + * @brief sbeReadPsu2SbeMbxReg : Read from PSU->SBE MBX register(s) + * + * @param[in] i_addr + * Starting Mbx Register Address + * @param[in] i_count + * Number of Mbx registers to be read. + * @param[in] i_isFinalRead + * Indicates if its a final read operation for this chip op and + * internally handle the ack + * By default it is false. + * @param[out] o_pData + * Contents of the Mbx registers read into the buffer + * @return Return Code + * SUCCESS or TBD + */ +uint32_t sbeReadPsu2SbeMbxReg (uint32_t i_addr, + const uint8_t i_count, + uint64_t *o_pData, + bool i_isFinalRead = false); + +/*****************************************************************/ +/** SBE->PSU register access utilities **/ +/*****************************************************************/ + +/** + * @brief sbeSetSbe2PsuDbBitX : Set Bit-X in SBE->PSU DB register + * + * @param[in] 64-Bit Scom Data indicating bit position + * + * @return RC from the underlying scom utility + * + */ +inline uint32_t sbeSetSbe2PsuDbBitX (const uint64_t i_bit) +{ + return putscom_abs (SBE_PSU2HOST_DOORBELL_REG_OR, i_bit) ; +} + +/** + * @brief sbeClearSbe2PsuDbBitX : Clear Bit-X in SBE->PSU DB register + * + * @param[in] 64-Bit Scom Data indicating bit position + * + * @return RC from the underlying scom utility + * + */ +inline uint32_t sbeClearSbe2PsuDbBitX (const uint64_t i_bit) +{ + return putscom_abs (SBE_PSU2HOST_DOORBELL_REG_AND, i_bit) ; +} + +/** + * @brief sbeReadSbe2PsuDbReg : Read SBE->PSU DB register + * + * @param[out] 64-Bit Data read from SBE->PSU DB register + * + * @return RC from the underlying scom utility + * + */ +inline uint32_t sbeReadSbe2PsuDbReg (uint64_t *o_data) +{ + return getscom_abs (SBE_PSU2HOST_DOORBELL_REG_RW, o_data) ; +} + +/** + * @brief sbeAcknowledgeHost : Acknowldge by setting bit 1 in + * SBE->PSU DB register if the host had requested for an ack + * + * @return RC from the underlying scom utility + * + */ +uint32_t sbeAcknowledgeHost(); + +/** + * @brief sbeIntrHostUponRespWaiting : Interrupt Host by + * setting bit 0 in SBE->PSU DB register if the host had + * requested for response + * + * @return RC from the underlying scom utility + * + */ +uint32_t sbeIntrHostUponRespWaiting(); + + +/** + * @brief sbeWriteSbe2PsuMbxReg : Write to SBE->PSU MBX register(s) + * + * @param[in] i_addr + * Starting Mbx Register Address + * @param[in] i_pData + * Contains the data to be written into given Mbx registers + * @param[in] i_count + * Number of Mbx registers to be written. + * @param[in] i_setBit0ToIntrHB + * Indicates whether to write Bit0 to interrupt the Host, + * By default it is false. + * @return Return Code + * SUCCESS or TBD + */ +uint32_t sbeWriteSbe2PsuMbxReg (uint32_t i_addr, + const uint64_t *i_pData, + const uint8_t i_count, + bool i_setBit0ToIntrHB = false); + +/* @brief - Send PSU Chip Op response + * + * @param[in] - i_sbe2PsuRespHdr - Response header + * @param[in] - i_fapiRc - fapi rc of the relevant hwp call + * @param[in/out] - io_rc - rc status of the PSU access utility + * + * @return - void + */ +void sbePSUSendResponse(sbeSbe2PsuRespHdr_t &i_sbe2PsuRespHdr, + uint32_t &i_fapiRc, + uint32_t &io_rc); +#endif // __SBEFW_SBEHOSTUTILS_H diff --git a/src/sbefw/sbeSpMsg.H b/src/sbefw/sbeSpMsg.H new file mode 100644 index 00000000..c1b972bf --- /dev/null +++ b/src/sbefw/sbeSpMsg.H @@ -0,0 +1,634 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeSpMsg.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbeSpMsg.H + * + * @brief This file contains the message structures for FIFO + * communication. + * + */ + +#ifndef __SBEFW_SBESP_MSG_H +#define __SBEFW_SBESP_MSG_H + +#include "sbe_sp_intf.H" + +// @NOTE Make sure all FIFO structures are 32 bit alligned ( the largest +// member should be atleast 4 byte). It is required as in sbe fifo +// operation we are casting these structures to uint32_t pointer. It can +// cause alignment issue if largest member of structure is not atleast +// 32 bit. We can use bit fields to optimize memory requirements. +// These are two coding guidleines we will follow for this file +// 1. All data members less than 32 bits will be bit fields +// 2. All data members more than 32 buts will be divided into small +// members of 32 bit each. This is required as compiler pads structure +// to largest data member and we do not want extra padding for data +// members gretater than 32 bits ( e.g. uint64_t ) +/** + * @brief Command Request Header + */ +typedef struct +{ + uint32_t len; + uint32_t reserved:16; + uint32_t cmdClass:8; + uint32_t command:8; +}sbeFifoCmdReqBuf_t; + +extern sbeFifoCmdReqBuf_t g_sbeFifoCmdHdr; + +/** + * @brief structure for generic header for fifo response. + * + */ +typedef struct +{ + uint32_t magicCode:16; + uint32_t cmdClass:8; + uint32_t command:8; + uint32_t primaryStatus:16; + uint32_t secondaryStatus:16; + + /** + * @brief set the primary and secondary status + * + * @param[in] i_prim Primary status + * @param[in] i_sec Secondary status + * + * @return + */ + void setStatus( const uint16_t i_prim, const uint16_t i_sec) + { + primaryStatus = i_prim; + secondaryStatus = i_sec; + } + + /** + * @brief set initial values for response header + * + * @note We did not set this in constructor as based on use case + * it is possible that g_sbeFifoCmdHdr does not have proper + * values at time of object creation. + * + */ + void init() + { + magicCode = 0xC0DE; + cmdClass = g_sbeFifoCmdHdr.cmdClass; + command = g_sbeFifoCmdHdr.command; + primaryStatus = SBE_PRI_OPERATION_SUCCESSFUL; + secondaryStatus = SBE_SEC_OPERATION_SUCCESSFUL; + } + +}sbeRespGenHdr_t; + +/** + * @brief structure for generic Resp header with Len for fifo response. + * + */ +typedef struct +{ + uint32_t respLen; + sbeRespGenHdr_t respHdr; + + /** + * @brief set response length + * + * @param[in] i_len Length + * + * @return + */ + void setLength( const uint32_t i_len ) + { + respLen = i_len; + } + + /** + * @brief set initial values for response header + * + * @note We did not set this in constructor as based on use case + * it is possible that g_sbeCmdHdr does not have proper + * values at time of object creation. + * + */ + void init() + { + respHdr.init(); + } +}sbeRespGenHdrWithLen_t; + + +/** + * @brief structure for ffdc header for fifo response. + * + */ +typedef struct sbeResponseFfdc +{ + uint32_t magicBytes:16; + uint32_t lenInWords:16; // length in word( 4 byte ) + uint32_t fapiRc; + + /** + * @brief set rc + * + * @param[in] i_rc FAPI RC + * + * @return + */ + void setRc(const uint32_t i_rc) + { + fapiRc = i_rc; + } + + /** + * @brief return fapiRc + * + * @return fapiRc + */ + uint32_t getRc() const + { + return fapiRc; + } + + /** + * @brief constructor + * + * @param[in] i_rc FAPI RC + * + * @return + */ + sbeResponseFfdc() + { + magicBytes = 0xFFDC; + //TODO via 129076. + //Need to change value for length once FFDC design is final. + lenInWords = ( sizeof(uint32_t ) // For magicBytes + lenInWords + + sizeof(fapiRc)) + / sizeof(uint32_t); + fapiRc = 0; + } +}sbeResponseFfdc_t; + +/** + * @brief structure for execute istep chipop (0xA101) contents. + * + */ +typedef struct +{ + uint32_t reserved1:8; + uint32_t major:8; + uint32_t reserved2:8; + uint32_t minor:8; +}sbeIstepReqMsg_t; + + +/** + * @brief structure for GetScom Chipop (0xA201) contents. + * + */ +typedef struct +{ + uint32_t hiAddr; + uint32_t lowAddr; +}sbeGetScomReqMsg_t; + +/** + * @brief structure for PutScom Chipop (0xA202) contents. + * + */ +typedef struct +{ + uint32_t hiAddr; + uint32_t lowAddr; + uint32_t hiInputData; + uint32_t lowInputData; + + /** + * @brief return 64-bit Scom data + * + * @return 64-bit Scom data + */ + uint64_t getScomData() + { + uint64_t data = ((uint64_t)hiInputData << 32) | lowInputData; + return data; + } +}sbePutScomReqMsg_t; + +/** + * @brief structure for Modify_Scom Chipop (0xA203) contents. + * + */ +typedef struct +{ + uint32_t reserved:24; + uint32_t opMode:8; + uint32_t hiAddr; + uint32_t lowAddr; + uint32_t hiInputData; + uint32_t lowInputData; + + /** + * @brief return 64-bit modifying data + * + * @return 64-bit modifying data + */ + uint64_t getModifyingData() + { + uint64_t data = ((uint64_t)hiInputData << 32) | lowInputData; + return data; + } +}sbeModifyScomReqMsg_t; + +/** + * @brief structure for PutScom_UnderMask Chipop (0xA204) contents. + * + */ +typedef struct +{ + uint32_t hiAddr; + uint32_t lowAddr; + uint32_t hiInputData; + uint32_t lowInputData; + uint32_t hiMaskData; + uint32_t lowMaskData; + + /** + * @brief return 64-bit input data + * + * @return 64-bit input data + */ + uint64_t getInputData() + { + uint64_t data = ((uint64_t)hiInputData << 32) | lowInputData; + return data; + } + + /** + * @brief return 64-bit input mask + * + * @return 64-bit input mask + */ + uint64_t getInputMask() + { + uint64_t data = ((uint64_t)hiMaskData << 32) | lowMaskData; + return data; + } + + /** + * @brief Determines 64-bit Scom data + * + * @param[in/out] io_scomData 64-bit scom data + */ + void getScomData(uint64_t &io_scomData) + { + uint64_t l_inputMask = getInputMask(); + uint64_t l_inputData = getInputData(); + io_scomData = (io_scomData & (~l_inputMask)) + | (l_inputData & l_inputMask); + } +}sbePutScomUnderMaskReqMsg_t; + +/** + * @brief Structure for SBE Memory Access ChipOps (0xA401/A402) + * + */ +typedef struct +{ + uint32_t coreChipletId:8; //Pervasive Core Chiplet Id for PBA + uint32_t eccByte:8; //Ecc Override Byte from user + uint32_t flags:16; //Operational Flags -refer enum sbeMemoryAccessFlags + uint32_t addrHi; //Higher 32-Bit Memory Address + uint32_t addrLo; //Lower 32-Bit Memory Address + uint32_t len; //Length of Data in Bytes + + /** + * @brief Calculates 64-bit PBA ADU Address + * + * @return Return 64-bit PBA ADU address + */ + uint64_t getAddr() const + { + return (((uint64_t)addrHi << 32) | addrLo); + } + + /** + * @brief Determines if ECC Override bit is set + * + * @return Returns True if ECC Override bit is set + * False if ECC Override bit is not set + */ + bool isEccOverrideFlagSet() const + { + return ((flags & SBE_MEM_ACCESS_FLAGS_ECC_OVERRIDE) ? true : false); + } + + /** + * @brief Determines if ECC required bit is set + * + * @return Returns True if ECC required flag is set + * False if ECC required flag is not set + */ + bool isEccFlagSet() const + { + return ((flags & SBE_MEM_ACCESS_FLAGS_ECC_REQUIRED) ? true : false); + } + + /** + * @brief Determines if Itag required bit is set + * + * @return Returns True if Itag required flag is set + * False if Itag required flag is not set + */ + bool isItagFlagSet() const + { + return ((flags & SBE_MEM_ACCESS_FLAGS_ITAG) ? true : false); + } + + /** + * @brief Determines if Cache Inhibited mode is set + * + * @return Returns True if Cache Inhibited Mode flag is set + * False if Cache Inhibited Mode flag is not set + */ + bool isCacheInhibitModeFlagSet() const + { + return ((flags & SBE_MEM_ACCESS_FLAGS_CACHE_INHIBIT) ? true : false); + } + + /** + * @brief Determines if PBA flag is set + * + * @return Returns True if PBA Flag is set + * False if PBA flag is not set + */ + bool isPbaFlagSet() + { + return ((flags & SBE_MEM_ACCESS_FLAGS_TARGET_PBA) ? true : false); + } + + /** + * @brief Determines if Auto Increment Mode is set + * + * @return Returns True if Auto Increment mode is set + * False if Auto Increment is not set + */ + bool isAutoIncrModeSet() const + { + return ((flags & SBE_MEM_ACCESS_FLAGS_AUTO_INCR_ON) ? true : false); + } + + /** + * @brief Determines if Fast Mode is set + * + * @return Returns True if Fast mode is set + * False if Fast mode is not set + */ + uint32_t isFastModeSet() const + { + return ((flags & SBE_MEM_ACCESS_FLAGS_FAST_MODE_ON) ? true : false); + } + + /** + * @brief Determines if LCO Mode is set + * + * @return Returns True if LCO mode is set + * False if LCO mode is not set + */ + uint32_t isPbaLcoModeSet() const + { + return ((flags & SBE_MEM_ACCESS_FLAGS_LCO_ENABLED) ? true : false); + } + + /** + * @brief Calculates Data length in alignment with PBA/ADU Cacheline + * (128B/8B respectively) + * + * @return Returns Data length in alignment with PBA/ADU Cacheline + */ + uint64_t getDataLenCacheAlign() const + { + uint64_t l_len = (len / 8); + if(flags & SBE_MEM_ACCESS_FLAGS_TARGET_PBA) + { + l_len = (l_len / 16); + } + return l_len; + } + +}sbeMemAccessReqMsgHdr_t; + +/** + * @brief Structure for SBE OCC Get/Put Sram Access ChipOps (0xA403/A404) + */ +typedef struct +{ + uint32_t reserved:24; // Not used + sbeSramAccessMode mode:8; // Channel select 0-3 + uint32_t addr; // 32-Bit Memory Address + uint32_t len; // Length of Data in Bytes +}sbeOccSramAccessReqMsgHdr_t; + +// Maximum number of capabilities +static const uint32_t SBE_MAX_CAPABILITIES = 18; + +/** + * @brief structure for SBE Get Capabilities chipop (0xA802) contents. + * + */ +typedef struct sbeCapabilityRespMsg +{ + uint32_t verMajor:16; + uint32_t verMinor:16; + uint32_t fwCommitId; + uint32_t capability[SBE_MAX_CAPABILITIES]; + // ctor. constructor will initialise all values. + sbeCapabilityRespMsg(); +}sbeCapabilityRespMsg_t; + +// TODO via RTC 128658 +// We may be able to replace this structure by sbeRespGenHdr_t + +/** + * @brief Command response structure to hold the primary and secondary + * status values. This will be utilized when a command class + * validation or state machine check fails. + * + */ +typedef struct +{ + uint32_t prim_status:16 ; // Primary Response Status + uint32_t sec_status:16 ; // Secondary Response Status + + /** + * @brief initialize the response status + **/ + void init() + { + prim_status = SBE_PRI_OPERATION_SUCCESSFUL; + sec_status = SBE_SEC_OPERATION_SUCCESSFUL; + } + + /** + * @brief set the primary and secondary status + * + * @param[in] i_prim Primary status + * @param[in] i_sec Secondary status + * + **/ + void setStatus(const uint16_t i_prim, const uint16_t i_sec) + { + prim_status = i_prim; + sec_status = i_sec; + } +} sbeCmdRespHdr_t; + +extern sbeCmdRespHdr_t g_sbeCmdRespHdr; + +/** + * @brief structure for Control Instruction Chipop (0xA701) contents. + * + */ +typedef struct +{ + uint32_t reserved:12; + sbeErrorMode mode:4; + sbeCoreChipletId coreChipletId:8; + sbeThreadNum threadNum:4; + sbeThreadOps threadOps:4; + + /** + * @brief Validate input arguments + * + * @return bool, true if the validation is success, else false for + * validation failure + */ + bool validateInputArgs() + { + bool l_validatePassFlag = true; + // Validate Thread Command / Thread Num / Error Mode + if((threadOps > THREAD_SRESET_INS) || + (mode > IGNORE_HW_ERRORS) || + !((threadNum <= SMT4_THREAD3) || (threadNum == SMT4_THREAD_ALL))) + { + SBE_ERROR(SBE_FUNC "Invalid Parameter by User, ThreadOps[%d] " + "mode[%d] ThreadNum[%d]", threadOps, mode, threadNum); + l_validatePassFlag = false; + } + return l_validatePassFlag; + } + + /** + * @brief Process the input to find out core/thread ids to iterate + * over HWP for the internal business logic + * + * @param[out] o_core, Core Id to start with in the iteration + * @param[out] o_coreCntMax, Core Max count to iterate, start from o_core + * @param[out] o_threadCnt, Thread Num to start with in the iteration + * @param[out] o_threadCntMax, Thread Max Num to iterate, start from + * o_threadCnt + * + * @return void + */ + void processInputDataToIterate(uint8_t & o_core, uint8_t & o_coreCntMax, + uint8_t & o_threadCnt, uint8_t & o_threadCntMax) + { + //Default Init + o_threadCnt = SMT4_THREAD0; + o_threadCntMax = SMT4_THREAD_MAX; + + o_core = SMT4_CORE0_ID; + o_coreCntMax = SMT4_CORE_ID_MAX; + + if( SMT4_ALL_CORES != coreChipletId ) + { + o_core = coreChipletId; + o_coreCntMax = coreChipletId; + } + if( SMT4_THREAD_ALL != threadNum ) + { + o_threadCnt = threadNum; + o_threadCntMax = threadNum; + } + } +}sbeCntlInstRegMsgHdr_t; + +/** + * @brief Get Ring access message header + */ +typedef struct +{ + uint32_t ringAddr; + uint32_t ringLenInBits; + uint32_t reserved:16; + uint32_t ringMode:16; +}sbeGetRingAccessMsgHdr_t; + +/** + * @brief Reg access message header + */ +typedef struct +{ + uint32_t reserved:8; + uint32_t coreChiplet:8; + uint32_t threadNr:4; + uint32_t regType:4; + uint32_t numRegs:8; + + /** + * @brief checks if it is valid request. + * + * @return true if valid request, false otherwise + */ + bool isValidRequest() const + { + return (( SBE_REG_ACCESS_FPR >= regType ) + &&( SBE_MAX_REG_ACCESS_REGS >= numRegs ) + &&( SMT4_THREAD3 >= threadNr ) + &&( SMT4_CORE0_ID <= coreChiplet ) + &&( SMT4_CORE_ID_MAX >= coreChiplet )) ? true:false; + } +}sbeRegAccessMsgHdr_t; + +/** + * @brief reg scom package + */ +typedef struct +{ + uint32_t regNr; + uint32_t hiData; + uint32_t lowData; + + /** + * @brief data for a register. + * + * @return data. + */ + uint64_t getData() const + { + return (((uint64_t)hiData << 32 ) | lowData ); + } +}sbeRegAccessPackage_t; + +#endif // __SBEFW_SBESP_MSG_H diff --git a/src/sbefw/sbeXipUtils.H b/src/sbefw/sbeXipUtils.H new file mode 100644 index 00000000..b9ce992e --- /dev/null +++ b/src/sbefw/sbeXipUtils.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeXipUtils.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ +#ifndef SBE_XIP_UTILS_H +#define SBE_XIP_UTILS_H + +#include "p9_xip_image.h" +#include "ppe42_scom.h" // for PPE_STVD +#include "sbe_link.H" // for SBE_BASE_ORIGIN, SBE_SEEPROM_BASE_ORIGIN + +// Unconditional jump to a memory location +#define JUMP_TO_ADDR(VAL ) \ +{ \ +asm volatile ( \ + "mtlr %0 \n\t" \ + : \ + : "r" (VAL)); \ +asm volatile ( \ + "blr \n\t" \ + : \ + );\ +} + +// PIBMEM start address +const uint32_t g_pibMemAddr = SBE_BASE_ORIGIN; +// SEEPROM start address +const uint32_t g_headerAddr = SBE_SEEPROM_BASE_ORIGIN; +// IVPR register address +const uint32_t g_ivprLoc = 0xC0000160; + +// Get XIP image header +inline P9XipHeader * getXipHdr() +{ + P9XipHeader *hdr = (P9XipHeader *)( g_headerAddr ); + return hdr; +} + +// Get Section start addess +inline uint8_t * getSectionAddr( P9XipSection * i_section ) +{ + return ( (uint8_t *)( g_headerAddr + i_section->iv_offset)); +} +#endif // SBE_XIP_UTILS_H diff --git a/src/sbefw/sbe_host_intf.H b/src/sbefw/sbe_host_intf.H new file mode 100644 index 00000000..24658f16 --- /dev/null +++ b/src/sbefw/sbe_host_intf.H @@ -0,0 +1,89 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbe_host_intf.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbe_host_intf.H + * + * @brief This file contains the Host-SBE interface protocol common details + */ + +#ifndef __SBEFW_SBE_HOST_INTF_H +#define __SBEFW_SBE_HOST_INTF_H + +#include + +/** + * $Version: Conforms to HOST-SBE Interface Spec v0.5a + */ + +/* + * Constants for SBE FW major and minor number + */ +static const uint16_t SBE_SBEFW_HOST_MAJOR_VERSION = 1; +static const uint16_t SBE_SBEFW_HOST_MINOR_VERSION = 0; + +/** + * @brief enums for SBE-Host interface command class + */ +enum sbePsuCommandClass + { + SBE_PSU_CMD_CLASS_UNKNOWN = 0, + SBE_PSU_CMD_CLASS_CORE_STATE = 0xD1, + SBE_PSU_CMD_CLASS_RING_ACCESS = 0xD3, + }; + +/** + * @brief enums for SBE-Host interface core state control commands + */ +enum sbePsuCoreStateControlCommands +{ + SBE_PSU_CMD_CONTROL_DEADMAN = 0x01, + SBE_PSU_CMD_UNKNOWN = 0xFF, +}; + +/** + * @brief enums for SBE-Host interface ring access messages + */ +enum sbePsuRingAccessMessages +{ + SBE_PSU_MSG_PUT_RING_FROM_IMAGE = 0x01, + SBE_PSU_MSG_UNKNOWN = 0xFF, +}; + +/** + * @brief enums denoting control flags + * + */ +enum sbePsuControlFlags +{ + SBE_PSU_FLAGS_RESP_REQUIRED = 0x0100, + SBE_PSU_FLAGS_ACK_REQUIRED = 0x0200, +}; + +enum sbePsuDmtCmdFlags +{ + SBE_PSU_FLAGS_START_DMT = 0x0001, + SBE_PSU_FLAGS_STOP_DMT = 0x0002, +}; + +#endif // __SBEFW_SBE_HOST_INTF_H diff --git a/src/sbefw/sbe_sp_intf.H b/src/sbefw/sbe_sp_intf.H new file mode 100644 index 00000000..0734343d --- /dev/null +++ b/src/sbefw/sbe_sp_intf.H @@ -0,0 +1,408 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbe_sp_intf.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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 sbe_sp_intf.H + * + * @brief This file contains the SP - SBE interface protocol common details + */ + +#ifndef __SBEFW_SBE_SP_INTF_H +#define __SBEFW_SBE_SP_INTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * $Version: Conforms to SP-SBE Interface Spec v0.8e + */ + +/* + * Constants for SBE FW major and minor number + */ +static const uint16_t SBE_FW_MAJOR_VERSION = 1; +static const uint16_t SBE_FW_MINOR_VERSION = 1; + +/** + * @brief enums for SBE command classes + * +*/ +enum sbeCommandClass +{ + SBE_CMD_CLASS_UNKNOWN = 0, + SBE_CMD_CLASS_IPL_CONTROL = 0xA1, + SBE_CMD_CLASS_SCOM_ACCESS = 0xA2, + SBE_CMD_CLASS_RING_ACCESS = 0xA3, + SBE_CMD_CLASS_MEMORY_ACCESS = 0xA4, + SBE_CMD_CLASS_REGISTER_ACCESS = 0xA5, + SBE_CMD_CLASS_ARRAY_ACCESS = 0xA6, + SBE_CMD_CLASS_INSTRUCTION_CONTROL = 0xA7, + SBE_CMD_CLASS_GENERIC_MESSAGE = 0xA8, + SBE_CMD_CLASS_MPIPL_COMMANDS = 0xA9, +}; + +/** + * @brief enums for SBE Istep Control command class + * +*/ +enum sbeIplControlCommands +{ + SBE_CMD_EXECUTE_ISTEP = 0x01, /* Execute istep */ + SBE_CMD_CONTINUE_BOOT = 0x02, /* Continue SBE Boot */ +}; + +/** + * @brief enums for SCOM Access Messages + * +*/ +enum sbeScomAccessCommands +{ + SBE_CMD_GETSCOM = 0x01, /* Get SCOM */ + SBE_CMD_PUTSCOM = 0x02, /* Put SCOM */ + SBE_CMD_MODIFYSCOM = 0x03, /* Modify SCOM */ + SBE_CMD_PUTSCOM_MASK = 0x04, /* Put SCOM under mask */ + SBE_CMD_MULTISCOM = 0x05, /* Execute Multi SCOM */ +}; + +/** + * @brief enum for modify mode + * +*/ +enum sbeChipOpModifyMode +{ + SBE_MODIFY_MODE_OR = 0x01, + SBE_MODIFY_MODE_AND = 0x02, + SBE_MODIFY_MODE_XOR = 0x03, +}; + +/** + * @brief enums for Ring Access Messages + * +*/ +enum sbeRingAccessCommands +{ + SBE_CMD_GETRING = 0x01, /* Get Ring */ + SBE_CMD_PUTRING = 0x02, /* Put Ring */ +}; + +/** + * @brief enums for Memory Access Messages + * +*/ +enum sbeMemoryAccesCommands +{ + SBE_CMD_GETMEM = 0x01, /* Get Memory (Proc/PBA) */ + SBE_CMD_PUTMEM = 0x02, /* Put Memory (Proc/PBA) */ + SBE_CMD_GETSRAM_OCC = 0x03, /* Get Memory (OCC SRAM) */ + SBE_CMD_PUTSRAM_OCC = 0x04, /* Put Memory (OCC SRAM) */ +}; + +/** + * @brief enums for GPR/SPR/FPR Access Messages + * +*/ +enum sbeRegisterAccessCommands +{ + SBE_CMD_GETREG = 0x01, /* Get Register (GPR,SPR,FPR) */ + SBE_CMD_PUTREG = 0x02, /* Put Register (GPR,SPR,FPR) */ +}; + +/** + * @brief enums for Trace Array Access Messages + * +*/ +enum sbeArrayAccessCommands +{ + SBE_CMD_GET_FAST_ARRAY = 0x01, /* Get Fast Array */ + SBE_CMD_GET_TRACE_ARRAY = 0x02, /* Get Trace Array */ + SBE_CMD_CONTROL_TRACE_ARRAY = 0x03, /* Control Trace Array */ +}; + +/** + * @brief enums for Instruction Control Messages + * +*/ +enum sbeInstructionControlCommands +{ + SBE_CMD_CONTROL_INSTRUCTIONS = 0x01, /* Control Instructions */ +}; + +/** + * @brief enums for Generic Messages + * +*/ +enum sbeGenericMessageCommands +{ + SBE_CMD_GET_SBE_FFDC = 0x01, /* Get FFDC */ + SBE_CMD_GET_SBE_CAPABILITIES = 0x02, /* GET SBE capabilities */ + SBE_CMD_GET_FREQ_SUPPORTED = 0x03, /* Get Supported frequencies */ + SBE_CMD_ABORT = 0x05, /* Sbe Abort */ +}; + +enum sbeMpIplCommands +{ + SBE_CMD_MPIPL_ENTER = 0x01, /* Enter MPIPL */ + SBE_CMD_MPIPL_CONTINUE = 0x02, /* Continue MPIPL */ +}; + +/** + * @brief enums for primary SBE response + * +*/ +enum sbePrimResponse +{ + SBE_PRI_OPERATION_SUCCESSFUL = 0x00, + SBE_PRI_INVALID_COMMAND = 0x01, + SBE_PRI_INVALID_DATA = 0x02, + SBE_PRI_SEQUENCE_ERROR = 0x03, + SBE_PRI_INTERNAL_ERROR = 0x04, + SBE_PRI_GENERIC_EXECUTION_FAILURE = 0xFE, +}; + +/** + * @brief enums for secondary SBE response + * @TODO via RTC: 129763 + * Discuss on SBE_SEC_INVALID_TARGET_ID_PASSED + * +*/ +enum sbeSecondaryResponse +{ + SBE_SEC_OPERATION_SUCCESSFUL = 0x00, + SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED = 0x01, + SBE_SEC_COMMAND_NOT_SUPPORTED = 0x02, + SBE_SEC_INVALID_ADDRESS_PASSED = 0x03, + SBE_SEC_INVALID_TARGET_TYPE_PASSED = 0x04, + SBE_SEC_INVALID_TARGET_ID_PASSED = 0x05, + SBE_SEC_SPECIFIED_TARGET_NOT_PRESENT = 0x06, + SBE_SEC_SPECIFIED_TARGET_NOT_FUNCTIONAL = 0x07, + SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE = 0x08, + SBE_SEC_FUNCTIONALITY_NOT_SUPPORTED = 0x09, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION = 0x0A, + SBE_SEC_SECURITY_VALIDATION_FAILED = 0x0B, + SBE_SEC_OS_FAILURE = 0x0C, + SBE_SEC_FIFO_ACCESS_FAILURE = 0x0D, + SBE_SEC_UNEXPECTED_EOT_INSUFFICIENT_DATA = 0x0E, + SBE_SEC_UNEXPECTED_EOT_EXCESS_DATA = 0x0F, + SBE_SEC_HW_OP_TIMEOUT = 0x10, + SBE_SEC_PCB_PIB_ERR = 0x11, +}; + +/** + * @brief enums for SBE command timeout values + * +*/ +enum sbeCmdRespTimeout +{ + SBE_CMD_TIMEOUT_SHORT_IN_MSEC = 100, + SBE_CMD_TIMEOUT_LONG_IN_MSEC = 30000, +}; + +/** + * @brief enums for PCB-PIB Generic Error codes + * +*/ +enum sbePCBPIBErrorRC +{ + SBE_PCB_PIB_ERROR_NONE = 0x00, + SBE_PCB_PIB_ERROR_RESOURCE_OCCUPIED = 0x01, + SBE_PCB_PIB_ERROR_CHIPLET_OFFLINE = 0x02, + SBE_PCB_PIB_ERROR_PARTIAL_GOOD = 0x03, + SBE_PCB_PIB_ERROR_ADDRESS_ERROR = 0x04, + SBE_PCB_PIB_ERROR_CLOCK_ERROR = 0x05, + SBE_PCB_PIB_ERROR_PACKET_ERROR = 0x06, + SBE_PCB_PIB_ERROR_TIMEOUT = 0x07, +}; + +/** + * @brief capabilities index values. + * Get Capability response will return 18 capabilities. This + * enum tells the index for each capability. Currently each generic + * functionality( scom, IPL ) etc span across two capabilities. + */ +enum +{ + GENERIC_CAPABILTITY_START_IDX = 0, + IPL_CAPABILITY_START_IDX = GENERIC_CAPABILTITY_START_IDX + 2, + SCOM_CAPABILITY_START_IDX = GENERIC_CAPABILTITY_START_IDX + 4, + RING_CAPABILITY_START_IDX = GENERIC_CAPABILTITY_START_IDX + 6, + MEMORY_CAPABILITY_START_IDX = GENERIC_CAPABILTITY_START_IDX + 8, + REGISTER_CAPABILITY_START_IDX = GENERIC_CAPABILTITY_START_IDX + 10, + ARRAY_CAPABILITY_START_IDX = GENERIC_CAPABILTITY_START_IDX + 12, + INSTRUCTION_CTRL_CAPABILITY_START_IDX = GENERIC_CAPABILTITY_START_IDX + 14, + GENERIC_CHIPOP_CAPABILITY_START_IDX = GENERIC_CAPABILTITY_START_IDX + 16, +}; +/** + * @brief capabilities enum values. + * + */ +enum +{ + HWP_FFDC_COLLECTION_SUPPPORTED = 0x00000001, + SBE_FFDC_COLLECTION_SUPPPORTED = 0x00000002, + ADDRESS_BLACKLISTING_SUPPPORTED = 0x00000004, + FIFO_RESET_SUPPPORTED = 0x00000008, + EXECUTE_ISTEP_SUPPPORTED = 0xA1000001, + IS_SBE_DONE_SUPPPORTED = 0xA1000002, + GET_SCOM_SUPPPORTED = 0xA2000001, + PUT_SCOM_SUPPPORTED = 0xA2000002, + MODIFY_SCOM_SUPPPORTED = 0xA2000004, + PUT_SCOM_UNDER_MASK_SUPPPORTED = 0xA2000008, + MULTI_SCOM_SUPPPORTED = 0xA2000010, + GET_RING_SUPPPORTED = 0xA3000001, + PUT_RING_SUPPPORTED = 0xA3000002, + GET_MEMORY_SUPPPORTED = 0xA4000001, + PUT_MEMORY_SUPPPORTED = 0xA4000002, + GET_SRAM_OCC_SUPPPORTED = 0xA4000004, + PUT_SRAM_OCC_SUPPPORTED = 0xA4000008, + GET_SRAM_CME_SUPPPORTED = 0xA4000010, + PUT_SRAM_CME_SUPPPORTED = 0xA4000011, + GET_REGISTER_SUPPPORTED = 0xA5000001, + PUT_REGISTER_SUPPPORTED = 0xA5000002, + READ_FAST_ARRAY_SUPPPORTED = 0xA6000001, + READ_TRACE_ARRAY_SUPPPORTED = 0xA6000002, + COLLECT_TRACE_ARRAY_SUPPPORTED = 0xA6000004, + CONTROL_INSTRUCTIONS_SUPPPORTED = 0xA7000001, + GET_SBE_FFDC_SUPPPORTED = 0xA8000001, + GET_SBE_CAPABILITIES_SUPPPORTED = 0xA8000002, + GET_SBE_FREQUENCIES_SUPPPORTED = 0xA8000004, + GET_SBE_STATE_SUPPPORTED = 0xA8000008, +}; + +/** + * * @brief enums for SBE Memory Access command flags + * + */ +enum sbeMemoryAccessFlags +{ + SBE_MEM_ACCESS_FLAGS_TARGET_PROC = 0x0001, //required in ADU + SBE_MEM_ACCESS_FLAGS_TARGET_PBA = 0x0002, //required in PBA + SBE_MEM_ACCESS_FLAGS_AUTO_INCR_ON = 0x0004, + SBE_MEM_ACCESS_FLAGS_ECC_REQUIRED = 0x0008, //required only in ADU-GET + SBE_MEM_ACCESS_FLAGS_ECC_OVERRIDE = 0x0008, //required only in ADU-PUT + SBE_MEM_ACCESS_FLAGS_ITAG = 0x0010, //ITAG Mode in ADU + SBE_MEM_ACCESS_FLAGS_FAST_MODE_ON = 0x0020, + SBE_MEM_ACCESS_FLAGS_LCO_ENABLED = 0x0040, //required only in PBA-PUT + SBE_MEM_ACCESS_FLAGS_CACHE_INHIBIT = 0x0080, //required in I/O oper ADU +}; + +/** + * @brief enum for various modes for Sram Access + */ +enum sbeSramAccessMode +{ + NORMAL_MODE = 0x1, + DEBUG_MODE = 0x2, + CIRCULAR_MODE = 0x3, +}; +/* + * Constants for maximum number of register supported in reg access chipop. + */ +static const uint32_t SBE_MAX_REG_ACCESS_REGS = 64; + +/** + * @brief Error Mode enum + */ +enum sbeErrorMode +{ + EXIT_ON_FIRST_ERROR = 0x0, // Bail out on first error + IGNORE_HW_ERRORS = 0x01, // Attempt best case +}; + +/** + * @brief Core Chiplet Id Enum + */ +enum sbeCoreChipletId +{ + SMT4_CORE0_ID = 0x20, + SMT4_CORE_ID_MAX = 0x38, + SMT4_ALL_CORES = 0xFF, +}; + +/** + * @brief Thread Num Enum + */ +enum sbeThreadNum +{ + SMT4_THREAD0 = 0x0, + SMT4_THREAD1 = 0x1, + SMT4_THREAD2 = 0x2, + SMT4_THREAD3 = 0x3, + SMT4_THREAD_MAX = 0x4, + SMT4_THREAD_ALL = 0xF, +}; + +/** + * @brief Thread Operation Enum + */ +enum sbeThreadOps +{ + THREAD_START_INS = 0x0, + THREAD_STOP_INS = 0x1, + THREAD_STEP_INS = 0x2, + THREAD_SRESET_INS = 0x3, +}; + +/** + * @brief enums for Reg access register type + * + */ +enum sbeRegAccesRegType +{ + SBE_REG_ACCESS_GPR = 0x00, + SBE_REG_ACCESS_SPR = 0x01, + SBE_REG_ACCESS_FPR = 0x02, +}; + +/* + * @brief enums for target types used in ring access chip op +*/ +typedef enum +{ + TARGET_PROC_CHIP = 0x0000, + TARGET_EX = 0x0001, + TARGET_PERV = 0x0002, + TARGET_MCS = 0x0003, +} sbeRingTargetTypes_t; + +/* + * @brief enums for access modes used in ring access chip op + */ +typedef enum +{ + SBE_RING_MODE_NO_HEADER_CHECK = 0x0001, ///< Don't check header + SBE_RING_MODE_SET_PULSE_NO_OPCG_COND = 0x0002, ///< Set pulse with + /// no OPCG conditioning + SBE_RING_MODE_SET_PULSE_NSL = 0x0004, ///< Set pulse with NSL + /// pulse + SBE_RING_MODE_SET_PULSE_SL = 0x0008, ///< Set pulse with SL + /// pulse + SBE_RING_MODE_SET_PULSE_ALL = 0x0010, ///< Set pulse with pulse + /// to all hold types +} sbeRingAccessModes_t; + +#ifdef __cplusplus +} +#endif + +#endif /* __SBEFW_SBE_SP_INTF_H */ diff --git a/src/sbefw/sbecmdcntlinst.C b/src/sbefw/sbecmdcntlinst.C new file mode 100644 index 00000000..faed1e5b --- /dev/null +++ b/src/sbefw/sbecmdcntlinst.C @@ -0,0 +1,203 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdcntlinst.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbecmdcntlinst.C + * + * @brief This file contains the SBE Control Instruction chipOps + * + */ + +#include "sbecmdcntlinst.H" +#include "sbefifo.H" +#include "sbe_sp_intf.H" +#include "sbetrace.H" +#include "sbeFifoMsgUtils.H" + +#include "fapi2.H" +#include "p9_thread_control.H" + +using namespace fapi2; + +// This is used to find out the array index in g_control_reg_map in +// p9_thread_control.C +static const uint8_t SINGLE_THREAD_BIT_MASK = 0x08; +// TODO via RTC 152424 +// Currently all proecdures in core directory are in seeprom. +// So we have to use function pointer to force a long call. +p9_thread_control_FP_t threadCntlhwp = &p9_thread_control; + +/* @brief Map User Thread Command to Hwp ThreadCommands Enum */ +ThreadCommands getThreadCommand(const sbeCntlInstRegMsgHdr_t & i_req) +{ + ThreadCommands l_cmd = PTC_CMD_START; + switch(i_req.threadOps) + { + case THREAD_START_INS: l_cmd = PTC_CMD_START; break; + case THREAD_STOP_INS: l_cmd = PTC_CMD_STOP; break; + case THREAD_STEP_INS: l_cmd = PTC_CMD_STEP; break; + case THREAD_SRESET_INS: l_cmd = PTC_CMD_SRESET; break; + } + return l_cmd; +} + +/* @brief Map User Mode Command to Hwp Warn Check flag */ +inline bool getWarnCheckFlag(const sbeCntlInstRegMsgHdr_t & i_req) +{ + bool l_warnCheck = false; + if( EXIT_ON_FIRST_ERROR != i_req.mode ) + { + l_warnCheck = true; + } + return l_warnCheck; +} + +/////////////////////////////////////////////////////////////////////// +// @brief sbeCntlInst Sbe control instructions function +// +// @return RC from the underlying FIFO utility +/////////////////////////////////////////////////////////////////////// +uint32_t sbeCntlInst(uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeCntlInst " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + ReturnCode l_fapiRc = FAPI2_RC_SUCCESS; + sbeRespGenHdr_t l_respHdr; + l_respHdr.init(); + sbeResponseFfdc_t l_ffdc; + + // Create the req struct for Control Instructions Chip-op + sbeCntlInstRegMsgHdr_t l_req = {0}; + + do + { + // Get the Req Struct Data sbeCntlInstRegMsgHdr_t from upstream Fifo + uint32_t l_len2dequeue = sizeof(l_req) / sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, (uint32_t *)&l_req, true); + + // If FIFO failure + if ( SBE_SEC_OPERATION_SUCCESSFUL != l_rc ) + { + // Let command processor routine to handle the RC. + break; + } + + SBE_INFO("mode[0x%04X] coreChipletId[0x%08X] threadNum[0x%04X] " + "threadOps[0x%04X] ", l_req.mode, l_req.coreChipletId, + l_req.threadNum, l_req.threadOps); + + // Validate Input Args + if( false == l_req.validateInputArgs()) + { + SBE_ERROR(SBE_FUNC "ValidateAndMapInputArgs failed"); + l_respHdr.setStatus( SBE_PRI_INVALID_DATA, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION ); + break; + } + + // Fetch HWP mapped values + bool l_warnCheck = getWarnCheckFlag(l_req); + ThreadCommands l_cmd = getThreadCommand(l_req); + + // Default assignment not required since it is assigned below + uint8_t l_core, l_coreCntMax; + uint8_t l_threadCnt, l_threadCntMax; + + l_req.processInputDataToIterate(l_core, l_coreCntMax, + l_threadCnt, l_threadCntMax); + fapi2::buffer l_data64; + uint64_t l_state; + do + { + fapi2::Target + l_coreTgt(plat_getTargetHandleByChipletNumber + (l_core)); + if(!l_coreTgt.isFunctional()) + { + continue; + } + + uint8_t l_thread = l_threadCnt; + do + { + // Call the Procedure + l_fapiRc = threadCntlhwp( + l_coreTgt, + (SINGLE_THREAD_BIT_MASK >> l_thread), + l_cmd, l_warnCheck, + l_data64, l_state); + + if(l_fapiRc != FAPI2_RC_SUCCESS) + { + SBE_ERROR(SBE_FUNC "Failed for Core[%d] Thread [%d] " + "Cmd[%d] Mode[%d]", l_core, l_thread, l_req.threadOps, + l_req.mode); + if(IGNORE_HW_ERRORS == l_req.mode) + { + // No need to delete the l_fapiRc handle,it will get + // over-written + SBE_INFO(SBE_FUNC "Continuing in case of HW Errors" + " As user has passed to ignore errors."); + continue; + } + else + { + SBE_ERROR(SBE_FUNC "Breaking out, since User has " + "Selected the mode to exit on first error."); + l_respHdr.setStatus(SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + break; + } + } + }while(++l_thread < l_threadCntMax); + + // If FapiRc from the inner loop (thread loop), just break here + if ( l_fapiRc ) + { + break; // From core while loop + } + }while(++l_core < l_coreCntMax); + + }while(0); + + // Create the Response to caller + do + { + // 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) + { + break; + } + + l_rc = sbeDsSendRespHdr(l_respHdr, l_ffdc); + }while(0); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + diff --git a/src/sbefw/sbecmdcntlinst.H b/src/sbefw/sbecmdcntlinst.H new file mode 100644 index 00000000..39e84135 --- /dev/null +++ b/src/sbefw/sbecmdcntlinst.H @@ -0,0 +1,45 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdcntlinst.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbecmdcntlinst.H + * + * @brief This file contains the Interfaces for Control Instructions chip-ops + * + */ + +#ifndef __SBEFW_SBECMDCNTLINST_H +#define __SBEFW_SBECMDCNTLINST_H + +#include + +/** + * @brief sbeCntlInst : Implements SBE Control instructions ChipOp + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeCntlInst (uint8_t *i_pArg); + +#endif /* __SBEFW_SBECMDCNTLINST_H */ diff --git a/src/sbefw/sbecmdcntrldmt.C b/src/sbefw/sbecmdcntrldmt.C new file mode 100644 index 00000000..a4cf8c97 --- /dev/null +++ b/src/sbefw/sbecmdcntrldmt.C @@ -0,0 +1,302 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdcntrldmt.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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: sbe/sbefw/sbecmdcntrldmt.C + * + * @brief This file contains the Core State Control Messages + * + */ + +#include "sbecmdcntrldmt.H" +#include "sbetrace.H" +#include "sbe_build_info.H" +#include "sbeHostMsg.H" +#include "sbeHostUtils.H" +#include "sberegaccess.H" +#include "sbestates.H" +#include "sbe_sp_intf.H" +#include "fapi2.H" +#include "p9_sbe_check_master_stop15.H" +#include "p9_perv_scom_addresses.H" +#include "p9_block_wakeup_intr.H" + +using namespace fapi2; + +// Using Function pointer to force long call +p9_sbe_check_master_stop15_FP_t p9_sbe_check_master_stop15_hwp = + &p9_sbe_check_master_stop15; + +//////////////////////////////////////////////////////////////////// +//Static initialization of the Dmt Pk timer +PkTimer g_sbe_pk_dmt_timer; +// Global Flag to indicate Dmt Timer Expiry +bool g_SbeDmtTimerExpired = false; + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// +void sbeDmtPkExpiryCallback(void *) +{ + #define SBE_FUNC "sbeDmtPkExpiryCallback" + SBE_INFO(SBE_FUNC" DMT Callback Timer has expired..Checkstop the system "); + g_SbeDmtTimerExpired = true; + + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_DUMP_FAILURE_EVENT); + + // check stop the system + uint32_t l_status = SBE_PCB_PIB_ERROR_NONE; + l_status = putscom_abs (PERV_N3_LOCAL_FIR_OR, N3_FIR_CORE_CHECKSTOP_BIT); + if(SBE_PCB_PIB_ERROR_NONE != l_status) + { + // Scom failed + SBE_ERROR(SBE_FUNC "PutScom failed for REG PERV_N3_LOCAL_FIR"); + // TODO - Store the response in Async Response + // RTC:149074 + } + #undef SBE_FUNC +} + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// +uint32_t sbeStartCntlDmt() +{ + #define SBE_FUNC "sbeStartCntlDmt" + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + int l_pkRc = 0; + ReturnCode l_fapiRc = FAPI2_RC_SUCCESS; + g_SbeDmtTimerExpired = false; + + do + { + // Fetch the Timer Value and Start a Pk Timer + uint64_t l_timerVal = 0; + l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1, + (sizeof(l_timerVal)/sizeof(uint64_t)), + &l_timerVal); + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_ERROR(SBE_FUNC" Failed to extract SBE_HOST_PSU_MBOX_REG1"); + break; + } + + // Attach Callback + PkTimerCallback l_callback = &sbeDmtPkExpiryCallback; + + // Create Timer with the above value + l_pkRc = pk_timer_create(&g_sbe_pk_dmt_timer, l_callback, NULL); + if(l_pkRc) + { + SBE_ERROR(SBE_FUNC" Pk Timer Create failed, RC=[%d]", l_pkRc); + l_rc = SBE_SEC_OS_FAILURE; + break; + } + + // Schedule the timer + l_pkRc = pk_timer_schedule(&g_sbe_pk_dmt_timer, + PK_MILLISECONDS((uint32_t)l_timerVal)); + if(l_pkRc) + { + SBE_ERROR(SBE_FUNC" Pk Timer Schedule failed, RC=[%d]", l_pkRc); + l_rc = SBE_SEC_OS_FAILURE; + break; + } + + l_rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4, + (uint64_t*)(&g_sbeSbe2PsuRespHdr), + (sizeof(g_sbeSbe2PsuRespHdr)/sizeof(uint64_t)), + true); + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_ERROR(SBE_FUNC" Failed to write to " + "SBE_HOST_PSU_MBOX_REG4"); + break; + } + // Set DMT State + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_DMT_ENTER_EVENT); + + // Fetch the master core + Target l_procTgt = plat_getChipTarget(); + + // Fetch the MASTER_CORE attribute + uint8_t l_coreId = 0; + FAPI_ATTR_GET(fapi2::ATTR_MASTER_CORE,l_procTgt,l_coreId); + + // Construct the Master Core Target + fapi2::Target l_coreTgt( + (uint64_t)l_coreId); + + // Call Hwp p9_sbe_check_master_stop15 and loop + // Go around a loop till you get FAPI2_RC_SUCCESS + do + { + l_fapiRc = p9_sbe_check_master_stop15_hwp(l_coreTgt); + //Conversion is required here, since ReturnCode doesn't support + //comparision '!=' or '==' + //TODO RTC:149021 + uint32_t l_rcFapi = l_fapiRc; + if( (l_rcFapi != fapi2::RC_CHECK_MASTER_STOP15_PENDING) && + (l_rcFapi != FAPI2_RC_SUCCESS)) + { + SBE_ERROR(SBE_FUNC" p9_sbe_check_master_stop15 " + "returned failure"); + // Async Response to be stored + // RTC:149074 + break; + } + + // Only for Pending and Success case + if(RC_CHECK_MASTER_STOP15_PENDING != l_rcFapi) // Success + { + l_fapiRc = p9_block_wakeup_intr(l_coreTgt, + p9pmblockwkup::CLEAR ); + if( l_fapiRc ) + { + SBE_ERROR(SBE_FUNC" p9_block_wakeup_intr failed "); + // TODO via RTC 149074 + // Async Response to be stored. + // Also checkstop the system. + break; + } + // indicate the Host via Bit SBE_SBE2PSU_DOORBELL_SET_BIT2 + // that Stop15 exit + l_rc = sbeSetSbe2PsuDbBitX(SBE_SBE2PSU_DOORBELL_SET_BIT2); + if(l_rc) + { + SBE_ERROR(SBE_FUNC " Failed to Write " + "SBE_SBE2PSU_DOORBELL_SET_BIT2"); + } + break; // Breakout from do..while() + } + // Stop 15 Pending Case + pk_sleep(PK_MILLISECONDS(SBE_DMT_SLEEP_INTERVAL)); + + }while(false == g_SbeDmtTimerExpired); // Inner Loop + + }while(0); // Outer loop + + return l_rc; + #undef SBE_FUNC +} + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// +uint32_t sbeStopCntlDmt() +{ + #define SBE_FUNC "sbeStopCntlDmt" + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + int l_pkRc = 0; + + do + { + // Stop the Pk Timer - There is no call to check if the timer is + // still alive, if i call cancel on already expired timer, it + // returns error code. + if(false == g_SbeDmtTimerExpired) + { + SBE_INFO(SBE_FUNC " DmTimer hasn't expired yet.. stop it"); + l_pkRc = pk_timer_cancel(&g_sbe_pk_dmt_timer); + if(l_pkRc) + { + // Check again if the failure is because of the timer already + // expired, in that case don't need to send any error response + // to hostboot + if(false == g_SbeDmtTimerExpired) + { + SBE_ERROR(SBE_FUNC " Pk Timer Cancel failed, RC=[%d]", + l_pkRc); + l_rc = SBE_SEC_OS_FAILURE; + } + break; + } + } + + l_rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4, + (uint64_t*)(&g_sbeSbe2PsuRespHdr), + (sizeof(g_sbeSbe2PsuRespHdr)/sizeof(uint64_t)), + true); + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_ERROR(SBE_FUNC" Failed to write to SBE_HOST_PSU_MBOX_REG4"); + break; + } + // Set Runtime State + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_DMT_COMP_EVENT); + }while(0); + + return l_rc; + #undef SBE_FUNC +} + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// +uint32_t sbeControlDeadmanTimer (uint8_t *i_pArg) +{ + #define SBE_FUNC "sbeControlDeadmanTimer" + SBE_ENTER(SBE_FUNC); + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + do + { + // Send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1 + // This util method will check internally on the mbox0 register if ACK + // is requested. + l_rc = sbeAcknowledgeHost(); + if(l_rc) + { + SBE_ERROR(SBE_FUNC " Failed to Sent Ack to Host over " + "SBE_SBE2PSU_DOORBELL_SET_BIT1"); + break; + } + + if(g_sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_START_DMT) + { + l_rc = sbeStartCntlDmt(); + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_ERROR(SBE_FUNC " Failed sbeStartCntlDmt"); + break; + } + } + else if(g_sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_STOP_DMT) + { + l_rc = sbeStopCntlDmt(); + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_ERROR(SBE_FUNC " Failed sbeStopCntlDmt"); + break; + } + } + else + { + SBE_ERROR(SBE_FUNC" Not a valid command "); + l_rc = SBE_SEC_COMMAND_NOT_SUPPORTED; + } + }while(0); // End of do-while + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} diff --git a/src/sbefw/sbecmdcntrldmt.H b/src/sbefw/sbecmdcntrldmt.H new file mode 100644 index 00000000..4f133947 --- /dev/null +++ b/src/sbefw/sbecmdcntrldmt.H @@ -0,0 +1,59 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdcntrldmt.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbecmdcntrldmt.H + * + * @brief This file contains the Core State Control Messages API header + * + */ + +#ifndef __SBEFW_SBECMDCNTRLDMT_H +#define __SBEFW_SBECMDCNTRLDMT_H + +#include + +// Define for the Sleep interval between continuous HWP calls +// for DMT functionality in Millisecond +static const uint8_t SBE_DMT_SLEEP_INTERVAL = 1; + +// Bit-32 used to checkstop the system +static const uint64_t N3_FIR_CORE_CHECKSTOP_BIT = 32; + +/** + * @brief Callback for Timer Expiry for DMT + * + * @return void + */ +void sbeDmtPkExpiryCallback(void *arg); + +/** + * @brief Control Deadman Timer command (0xD101) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return RC from the PSU access utility + */ +uint32_t sbeControlDeadmanTimer(uint8_t *i_pArg); + +#endif // __SBEFW_SBECMDCNTRLDMT_H diff --git a/src/sbefw/sbecmdgeneric.C b/src/sbefw/sbecmdgeneric.C new file mode 100644 index 00000000..e883993a --- /dev/null +++ b/src/sbefw/sbecmdgeneric.C @@ -0,0 +1,118 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdgeneric.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbecmdgeneric.C + * + * @brief This file contains the SBE generic Commands + * + */ + +#include "sbecmdgeneric.H" +#include "sbefifo.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "sbe_build_info.H" +#include "sbeFifoMsgUtils.H" + +// Forward declaration +sbeCapabilityRespMsg::sbeCapabilityRespMsg() +{ + verMajor= SBE_FW_MAJOR_VERSION; + verMinor = SBE_FW_MINOR_VERSION; + fwCommitId = SBE_COMMIT_ID; + // We can remove this for llop once all capabilities + // are supported + for(uint32_t idx = 0; idx < SBE_MAX_CAPABILITIES; idx++ ) + { + capability[idx] = 0; + } + capability[IPL_CAPABILITY_START_IDX] = + EXECUTE_ISTEP_SUPPPORTED; + + capability[SCOM_CAPABILITY_START_IDX] = + GET_SCOM_SUPPPORTED | + PUT_SCOM_SUPPPORTED | + MODIFY_SCOM_SUPPPORTED | + PUT_SCOM_UNDER_MASK_SUPPPORTED ; + + capability[GENERIC_CHIPOP_CAPABILITY_START_IDX] = + GET_SBE_CAPABILITIES_SUPPPORTED; + + capability[MEMORY_CAPABILITY_START_IDX] = + GET_MEMORY_SUPPPORTED | + PUT_MEMORY_SUPPPORTED | + GET_SRAM_OCC_SUPPPORTED | + PUT_SRAM_OCC_SUPPPORTED; + + capability[INSTRUCTION_CTRL_CAPABILITY_START_IDX] = + CONTROL_INSTRUCTIONS_SUPPPORTED; + capability[REGISTER_CAPABILITY_START_IDX] = + GET_REGISTER_SUPPPORTED | + PUT_REGISTER_SUPPPORTED ; + + capability[RING_CAPABILITY_START_IDX] = + GET_RING_SUPPPORTED; +} +// Functions +//---------------------------------------------------------------------------- +uint32_t sbeGetCapabilities (uint8_t *i_pArg) +{ + #define SBE_FUNC "sbeGetCapabilities " + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t len = 0; + sbeRespGenHdr_t respHdr; + respHdr.init(); + sbeCapabilityRespMsg_t capMsg; + sbeResponseFfdc_t l_ffdc; + + do + { + // Dequeue the EOT entry as no more data is expected. + rc = sbeUpFifoDeq_mult (len, NULL); + // @TODO via RTC : 130575 + // Optimize both the RC handling and + // FIFO operation infrastructure. + if ( rc != SBE_SEC_OPERATION_SUCCESSFUL ) + { + // Let command processor routine to handle the RC + break; + } + + len = sizeof(capMsg)/sizeof(uint32_t); + rc = sbeDownFifoEnq_mult ( len, ( uint32_t *) &capMsg); + if (rc) + { + break; + } + + rc = sbeDsSendRespHdr(respHdr, l_ffdc); + }while(0); + + if( rc ) + { + SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc); + } + return rc; + #undef SBE_FUNC +} diff --git a/src/sbefw/sbecmdgeneric.H b/src/sbefw/sbecmdgeneric.H new file mode 100644 index 00000000..3fa174ad --- /dev/null +++ b/src/sbefw/sbecmdgeneric.H @@ -0,0 +1,46 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdgeneric.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbecmdgeneric.H + * + * @brief This file contains the SBE Generic command details + * + */ + +#ifndef __SBEFW_SBECMDGENERIC_H +#define __SBEFW_SBECMDGENERIC_H + +#include + + +/** + * @brief SBE Generic capabilities (0xA802) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetCapabilities(uint8_t *i_pArg); + +#endif // __SBEFW_SBECMDGENERIC_H diff --git a/src/sbefw/sbecmdiplcontrol.C b/src/sbefw/sbecmdiplcontrol.C new file mode 100644 index 00000000..0819a864 --- /dev/null +++ b/src/sbefw/sbecmdiplcontrol.C @@ -0,0 +1,830 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdiplcontrol.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbecmdiplcontrol.C + * + * @brief This file contains the SBE istep chipOps + * + */ + +#include "sbecmdiplcontrol.H" +#include "sbefifo.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "sbeFifoMsgUtils.H" +#include "assert.h" +#include "sberegaccess.H" +#include "sbestates.H" + +#include "fapi2.H" +// Pervasive HWP Header Files ( istep 2) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Pervasive HWP Header Files ( istep 3) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// Cache HWP header file +#include +#include +#include +#include +// Core HWP header file +#include + +// istep 5 hwp header files +#include "p9_sbe_instruct_start.H" +#include "p9_sbe_load_bootloader.H" + +#include "sbeXipUtils.H" // For getting hbbl offset +// Forward declaration +using namespace fapi2; +ReturnCode sbeExecuteIstep (uint8_t i_major, uint8_t i_minor); +bool validateIstep (uint8_t i_major, uint8_t i_minor); + +//typedefs +typedef ReturnCode (*sbeIstepHwpProc_t) + (const Target & i_target); + +typedef ReturnCode (*sbeIstepHwpEq_t) + (const Target & i_target); + +typedef ReturnCode (*sbeIstepHwpCore_t) + (const Target & i_target); + +typedef union +{ + sbeIstepHwpProc_t procHwp; + sbeIstepHwpEq_t eqHwp; + sbeIstepHwpCore_t coreHwp; +}sbeIstepHwp_t; +// Wrapper function for HWP IPl functions +typedef ReturnCode (*sbeIstep_t)( sbeIstepHwp_t ); + +// Wrapper function which will call HWP. +ReturnCode istepWithProc( sbeIstepHwp_t i_hwp ); +ReturnCode istepAttrSetup( sbeIstepHwp_t i_hwp ); +ReturnCode istepNoOp( sbeIstepHwp_t i_hwp ); +ReturnCode istepWithEq( sbeIstepHwp_t i_hwp); +ReturnCode istepWithCore( sbeIstepHwp_t i_hwp); +ReturnCode istepSelectEx( sbeIstepHwp_t i_hwp); +ReturnCode istepLoadBootLoader( sbeIstepHwp_t i_hwp); +ReturnCode istepCheckSbeMaster( sbeIstepHwp_t i_hwp); +ReturnCode istepStartInstruction( sbeIstepHwp_t i_hwp); +ReturnCode istepWithCoreConditional( sbeIstepHwp_t i_hwp); +ReturnCode istepWithEqConditional( sbeIstepHwp_t i_hwp); + +// Using function pointer to force long call. +p9_sbe_select_ex_FP_t p9_sbe_select_ex_hwp = &p9_sbe_select_ex; + +//structure for mapping SBE wrapper and HWP functions +typedef struct +{ + sbeIstep_t istepWrapper; + sbeIstepHwp_t istepHwp; +}istepMap_t; + +// Major isteps which are supported +typedef enum +{ + SBE_ISTEP2 = 2, + SBE_ISTEP_FIRST = SBE_ISTEP2, + SBE_ISTEP3 = 3, + SBE_ISTEP_LAST_SLAVE = SBE_ISTEP3, + SBE_ISTEP4 = 4, + SBE_ISTEP5 = 5, + SBE_ISTEP_LAST_MASTER = SBE_ISTEP5, +}sbe_supported_steps_t; + +// constants +const uint32_t ISTEP2_MAX_SUBSTEPS = 17; +const uint32_t ISTEP3_MAX_SUBSTEPS = 22; +const uint32_t ISTEP4_MAX_SUBSTEPS = 34; +const uint32_t ISTEP5_MAX_SUBSTEPS = 2; +static const uint8_t ISTEP_MINOR_START = 1; +static const uint8_t SLAVE_LAST_MINOR_ISTEP = 20; +static const uint8_t ISTEP2_MINOR_START = 2; +static const uint32_t SBE_ROLE_MASK = 0x00000002; + +// Globals +// TODO: via RTC 123602 This global needs to move to a class that will store the +// SBE FFDC. +fapi2::ReturnCode g_iplFailRc = FAPI2_RC_SUCCESS; + +sbeRole g_sbeRole = SBE_ROLE_MASTER; + +// File static data + +static istepMap_t g_istep2PtrTbl[ ISTEP2_MAX_SUBSTEPS ] = + { + { NULL, NULL }, + { &istepAttrSetup, { .procHwp = &p9_sbe_attr_setup }}, + { &istepWithProc, { .procHwp = &p9_sbe_tp_chiplet_init1 }}, + { &istepWithProc, { .procHwp = &p9_sbe_tp_gptr_time_initf }}, + { &istepNoOp, NULL }, // DFT only + { &istepWithProc, { .procHwp = &p9_sbe_npll_initf }}, + { &istepWithProc, { .procHwp = &p9_sbe_npll_setup }}, + { &istepWithProc, { .procHwp = &p9_sbe_tp_switch_gears }}, + { &istepWithProc, { .procHwp = &p9_sbe_clock_test2 }}, + { &istepWithProc, { .procHwp = &p9_sbe_tp_chiplet_reset }}, + { &istepWithProc, { .procHwp = &p9_sbe_tp_repr_initf }}, + { &istepWithProc, { .procHwp = &p9_sbe_tp_chiplet_init2 }}, + { &istepNoOp, NULL }, // DFT only + { &istepWithProc, { .procHwp = &p9_sbe_tp_arrayinit }}, + { &istepWithProc, { .procHwp = &p9_sbe_tp_initf }}, + { &istepNoOp, NULL }, // DFT only + { &istepWithProc, { .procHwp = &p9_sbe_tp_chiplet_init3 }}, + }; + +static istepMap_t g_istep3PtrTbl[ ISTEP3_MAX_SUBSTEPS ] = + { + { &istepWithProc, { .procHwp = &p9_sbe_chiplet_reset }}, + { &istepWithProc, { .procHwp = &p9_sbe_gptr_time_initf }}, + { &istepWithProc, { .procHwp = &p9_sbe_chiplet_pll_initf }}, + { &istepWithProc, { .procHwp = &p9_sbe_chiplet_pll_setup }}, + { &istepWithProc, { .procHwp = &p9_sbe_repr_initf }}, + { &istepWithProc, { .procHwp = &p9_sbe_chiplet_init }}, + { &istepNoOp, NULL }, // DFT only + { &istepWithProc, { .procHwp = &p9_sbe_arrayinit }}, + { &istepNoOp, NULL }, // DFT only + { &istepWithProc, { .procHwp = &p9_sbe_tp_enable_ridi }}, + { &istepWithProc, { .procHwp = &p9_sbe_setup_boot_freq }}, + { &istepWithProc, { .procHwp = &p9_sbe_nest_initf }}, + { &istepWithProc, { .procHwp = &p9_sbe_nest_startclocks }}, + { &istepWithProc, { .procHwp = &p9_sbe_nest_enable_ridi }}, + { &istepWithProc, { .procHwp = &p9_sbe_io_initf }}, + { &istepWithProc, { .procHwp = &p9_sbe_startclock_chiplets }}, + { &istepWithProc, { .procHwp = &p9_sbe_scominit }}, + { &istepWithProc, { .procHwp = &p9_sbe_lpc_init }}, + { &istepWithProc, { .procHwp = &p9_sbe_fabricinit }}, + { &istepCheckSbeMaster, NULL }, + { &istepWithProc, { .procHwp = &p9_sbe_mcs_setup }}, + { &istepSelectEx, NULL }, + }; +static istepMap_t g_istep4PtrTbl[ ISTEP4_MAX_SUBSTEPS ] = + { + { &istepWithEq, { .eqHwp = &p9_hcd_cache_poweron} }, + { &istepWithEq, { .eqHwp = &p9_hcd_cache_chiplet_reset } }, + { &istepWithEq, { .eqHwp = &p9_hcd_cache_chiplet_l3_dcc_setup }}, + { &istepWithEq, { .eqHwp = &p9_hcd_cache_gptr_time_initf }}, + { &istepWithEq, { .eqHwp = &p9_hcd_cache_dpll_initf }}, + { &istepWithEq, { .eqHwp = &p9_hcd_cache_dpll_setup }}, + { &istepWithEq, { .eqHwp = &p9_hcd_cache_dcc_skewadjust_setup }}, + { &istepWithEq, { .eqHwp = &p9_hcd_cache_chiplet_init }}, + { &istepWithEq, { .eqHwp = &p9_hcd_cache_repair_initf }}, + { &istepWithEq, { .eqHwp = &p9_hcd_cache_arrayinit }}, + { &istepNoOp, NULL }, // DFT Only + { &istepNoOp, NULL }, // DFT Only + { &istepWithEq, { .eqHwp = &p9_hcd_cache_initf }}, + { &istepWithEqConditional, { .eqHwp = &p9_hcd_cache_startclocks }}, + { &istepWithEqConditional, { .eqHwp = &p9_hcd_cache_scominit }}, + { &istepWithEqConditional, { .eqHwp = &p9_hcd_cache_scomcust }}, + { &istepNoOp, NULL }, // Runtime only + { &istepNoOp, NULL }, // Runtime only + { &istepNoOp, NULL }, // stub for SBE + { &istepNoOp, NULL }, // stub for SBE + { &istepWithCore, { .coreHwp = &p9_hcd_core_poweron }}, + { &istepWithCore, { .coreHwp = &p9_hcd_core_chiplet_reset }}, + { &istepWithCore, { .coreHwp = &p9_hcd_core_gptr_time_initf }}, + { &istepWithCore, { .coreHwp = &p9_hcd_core_chiplet_init }}, + { &istepWithCore, { .coreHwp = &p9_hcd_core_repair_initf }}, + { &istepWithCore, { .coreHwp = &p9_hcd_core_arrayinit }}, + { &istepNoOp, NULL }, // DFT Only + { &istepNoOp, NULL }, // DFT Only + { &istepWithCore, { .coreHwp = &p9_hcd_core_initf }}, + { &istepWithCoreConditional, + { .coreHwp = &p9_hcd_core_startclocks }}, + { &istepWithCoreConditional, { .coreHwp = &p9_hcd_core_scominit }}, + { &istepWithCoreConditional, { .coreHwp = &p9_hcd_core_scomcust }}, + { &istepNoOp, NULL }, + { &istepNoOp, NULL }, + }; + +// TODO via RTC 135345 +// Add the support for istep 5 HWP +static istepMap_t g_istep5PtrTbl[ ISTEP5_MAX_SUBSTEPS ] + { + { &istepLoadBootLoader, NULL }, + { &istepStartInstruction, { .coreHwp = &p9_sbe_instruct_start }}, + }; + +// Functions +//---------------------------------------------------------------------------- +uint32_t sbeHandleIstep (uint8_t *i_pArg) +{ + #define SBE_FUNC "sbeHandleIstep " + SBE_ENTER(SBE_FUNC); + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + ReturnCode fapiRc = FAPI2_RC_SUCCESS; + uint32_t len = 0; + sbeIstepReqMsg_t req; + sbeRespGenHdr_t respHdr; + respHdr.init(); + sbeResponseFfdc_t ffdc; + + // NOTE: In this function we will have two loops + // First loop will deque data and prepare the response + // Second response will enque the data on DS FIFO + //loop 1 + do + { + len = sizeof( req )/sizeof(uint32_t); + rc = sbeUpFifoDeq_mult ( len, (uint32_t *)&req); + if (rc != SBE_SEC_OPERATION_SUCCESSFUL) //FIFO access issue + { + SBE_ERROR(SBE_FUNC"FIFO dequeue failed, rc[0x%X]", rc); + break; + } + + if( false == validateIstep( req.major, req.minor ) ) + { + SBE_ERROR(SBE_FUNC" Invalid Istep. major:0x%08x" + " minor:0x%08x", req.major, req.minor); + // @TODO via RTC 132295. + // Need to change code asper better error handling. + respHdr.setStatus( SBE_PRI_INVALID_DATA, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + break; + } + + fapiRc = sbeExecuteIstep( req.major, req.minor ); + if( fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" sbeExecuteIstep() Failed. major:0x%08x" + " minor:0x%08x", req.major, req.minor); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + ffdc.setRc(fapiRc); + break; + } + + }while(0); + + //loop 2 + do + { + // FIFO error + if ( rc ) + { + break; + } + + rc = sbeDsSendRespHdr(respHdr, ffdc); + }while(0); + + if( rc ) + { + SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc); + } + SBE_EXIT(SBE_FUNC); + return rc; + #undef SBE_FUNC +} + +//---------------------------------------------------------------------------- +// @note This is the responsibilty of caller to verify major/minor +// number before calling this function + +// @TODO via RTC 129077. +// This function should check for system checkstop as well. +ReturnCode sbeExecuteIstep (const uint8_t i_major, const uint8_t i_minor) +{ + #define SBE_FUNC "sbeExecuteIstep " + SBE_INFO(SBE_FUNC"Major number:0x%x minor number:0x%x", + i_major, i_minor ); + + ReturnCode rc = FAPI2_RC_SUCCESS; + switch( i_major ) + { + case SBE_ISTEP2: + rc = (g_istep2PtrTbl[i_minor-1].istepWrapper)( + g_istep2PtrTbl[i_minor-1].istepHwp); + break; + + case SBE_ISTEP3: + rc = (g_istep3PtrTbl[i_minor-1].istepWrapper)( + g_istep3PtrTbl[i_minor-1].istepHwp); + break; + + case SBE_ISTEP4: + rc = (g_istep4PtrTbl[i_minor-1].istepWrapper)( + g_istep4PtrTbl[i_minor-1].istepHwp); + break; + + case SBE_ISTEP5: + rc = (g_istep5PtrTbl[i_minor-1].istepWrapper)( + g_istep5PtrTbl[i_minor-1].istepHwp); + break; + + // We should never reach here as before calling this validation has + // been done. + default: + assert(0); + break; + } + + (void)SbeRegAccess::theSbeRegAccess().updateSbeStep(i_major, i_minor); + + if(rc != FAPI2_RC_SUCCESS) + { + // If IPLing State + uint64_t l_state = SbeRegAccess::theSbeRegAccess().getSbeState(); + if(l_state == SBE_STATE_IPLING) + { + (void)SbeRegAccess::theSbeRegAccess(). + stateTransition(SBE_DUMP_FAILURE_EVENT); + } + } + + return rc; + #undef SBE_FUNC +} + +//---------------------------------------------------------------------------- +bool validateIstep (const uint8_t i_major, const uint8_t i_minor) +{ + bool valid = true; + do + { + if( 0 == i_minor ) + { + valid = false; + break; + } + + if((SBE_ROLE_SLAVE == g_sbeRole) && + ((SBE_ISTEP_LAST_SLAVE < i_major) || + ((SBE_ISTEP_LAST_SLAVE == i_major) && + (SLAVE_LAST_MINOR_ISTEP < i_minor) + ))) + { + // Cannot run beyond 3.20 on a slave SBE + valid = false; + break; + } + + switch( i_major ) + { + case SBE_ISTEP2: + // istep 2.1 loads image to PIBMEM + // So SBE control loop can not execute istep 2.1. + if(( i_minor > ISTEP2_MAX_SUBSTEPS ) || ( i_minor == 1) ) + { + valid = false; + } + break; + + case SBE_ISTEP3: + if( i_minor > ISTEP3_MAX_SUBSTEPS ) { valid = false; } ; + break; + + case SBE_ISTEP4: + if( i_minor > ISTEP4_MAX_SUBSTEPS ) + { + valid = false; + } + break; + + case SBE_ISTEP5: + if( i_minor > ISTEP5_MAX_SUBSTEPS ) + { + valid = false; + } + break; + + default: + valid= false; + break; + } + } while(0); + + return valid; +} + +//---------------------------------------------------------------------------- + +ReturnCode istepAttrSetup( sbeIstepHwp_t i_hwp) +{ + SBE_ENTER("istepAttrSetup"); + Target proc = plat_getChipTarget(); + ReturnCode rc = FAPI2_RC_SUCCESS; + do + { + assert( NULL != i_hwp.procHwp ); + rc = i_hwp.procHwp(proc); + if( rc != FAPI2_RC_SUCCESS ) + { + break; + } + // Apply the gard records + rc = plat_ApplyGards(); + }while(0); + SBE_EXIT("istepAttrSetup"); + return rc; +} + +//---------------------------------------------------------------------------- + +ReturnCode istepWithProc( sbeIstepHwp_t i_hwp) +{ + Target proc = plat_getChipTarget(); + assert( NULL != i_hwp.procHwp ); + return i_hwp.procHwp(proc); +} + +//---------------------------------------------------------------------------- + +ReturnCode istepSelectEx( sbeIstepHwp_t i_hwp) +{ + Target proc = plat_getChipTarget(); + // TODO via RTC 135345 + // Once multicast targets are supported, we may need to pass + // p9selectex::ALL as input. + return p9_sbe_select_ex_hwp(proc, p9selectex::SINGLE); +} + +//---------------------------------------------------------------------------- + + +ReturnCode istepWithEq( sbeIstepHwp_t i_hwp) +{ + // TODO via RTC 135345 + // Curently we are passing Hard code eq target. Finally it is + // going to be a multicast target. Once multicast support is + // present, use the right target. + fapi2::Target eqTgt; + // Put this in scope so that vector can be freed up before calling hwp. + { + Target proc = plat_getChipTarget(); + auto eqList = proc.getChildren(); + // As it is workaround lets assume there will always be atleast one + // functional eq. No need to validate. + eqTgt = eqList[0]; + } + + assert( NULL != i_hwp.eqHwp ); + return i_hwp.eqHwp( eqTgt ); +} + +//---------------------------------------------------------------------------- + +ReturnCode istepWithCore( sbeIstepHwp_t i_hwp) +{ + // TODO via RTC 135345 + // Curently we are passing Hard code core target. Finally it is + // going to be a multicast target. Once multicast support is + // present, use the right target. + fapi2::Target coreTgt; + // Put this in scope so that vector can be freed up before calling hwp. + { + Target proc = plat_getChipTarget(); + auto coreList = proc.getChildren(); + // As it is workaround lets assume there will always be atleast one + // functional ec. No need to validate. + coreTgt = coreList[0]; + } + assert( NULL != i_hwp.coreHwp ); + return i_hwp.coreHwp( coreTgt ); +} + +//---------------------------------------------------------------------------- + +ReturnCode istepWithEqConditional( sbeIstepHwp_t i_hwp) +{ + SBE_ENTER("istepWithEqCondtional"); + fapi2::Target sysTgt; + ReturnCode rc = FAPI2_RC_SUCCESS; + do + { + uint8_t iplPhase = ENUM_ATTR_SYSTEM_IPL_PHASE_HB_IPL; + FAPI_ATTR_GET(ATTR_SYSTEM_IPL_PHASE, sysTgt, iplPhase); + if( ENUM_ATTR_SYSTEM_IPL_PHASE_CACHE_CONTAINED == iplPhase ) + { + break; + } + rc = istepWithEq(i_hwp); + }while(0); + SBE_EXIT("istepWithEqCondtional"); + return rc; +} + +//---------------------------------------------------------------------------- + +ReturnCode istepWithCoreConditional( sbeIstepHwp_t i_hwp) +{ + SBE_ENTER("istepWithCoreCondtional"); + fapi2::Target sysTgt; + ReturnCode rc = FAPI2_RC_SUCCESS; + do + { + uint8_t iplPhase = ENUM_ATTR_SYSTEM_IPL_PHASE_HB_IPL; + FAPI_ATTR_GET(ATTR_SYSTEM_IPL_PHASE, sysTgt, iplPhase); + if( ENUM_ATTR_SYSTEM_IPL_PHASE_CACHE_CONTAINED == iplPhase ) + { + break; + } + rc = istepWithCore(i_hwp); + }while(0); + SBE_EXIT("istepWithCoreCondtional"); + return rc; +} + +//---------------------------------------------------------------------------- + +ReturnCode istepLoadBootLoader( sbeIstepHwp_t i_hwp) +{ + // Get master Ex + uint8_t exId = 0; + Target proc = plat_getChipTarget(); + FAPI_ATTR_GET(fapi2::ATTR_MASTER_EX,proc,exId); + fapi2::Target + exTgt(plat_getTargetHandleByInstance(exId)); + // Get hbbl section + P9XipHeader *hdr = getXipHdr(); + P9XipSection *hbblSection = &(hdr->iv_section[P9_XIP_SECTION_SBE_HBBL]); + + ReturnCode rc = p9_sbe_load_bootloader( proc, exTgt, hbblSection->iv_size, + getSectionAddr(hbblSection) ); + return rc; +} + +//---------------------------------------------------------------------------- + +ReturnCode istepStartInstruction( sbeIstepHwp_t i_hwp) +{ + ReturnCode rc = FAPI2_RC_SUCCESS; + rc = istepWithCore(i_hwp); + if(rc == FAPI2_RC_SUCCESS) + { + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_RUNTIME_EVENT); + } + return rc; +} + +//---------------------------------------------------------------------------- +ReturnCode istepCheckSbeMaster( sbeIstepHwp_t i_hwp) +{ + ReturnCode rc = FAPI2_RC_SUCCESS; + g_sbeRole = SbeRegAccess::theSbeRegAccess().isSbeSlave() ? + SBE_ROLE_SLAVE : SBE_ROLE_MASTER; + SBE_INFO("stepCheckSbeMaster g_sbeRole [%x]", g_sbeRole); + if(SBE_ROLE_SLAVE == g_sbeRole) + { + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_RUNTIME_EVENT); + } + return rc; +} + +//---------------------------------------------------------------------------- +ReturnCode istepNoOp( sbeIstepHwp_t i_hwp) +{ + SBE_INFO("istepNoOp"); + return FAPI2_RC_SUCCESS ; +} + +// Only allowed in PLCK Mode, since FFDC State mode is set only in PLCK +//---------------------------------------------------------------------------- +uint32_t sbeContinueBoot (uint8_t *i_pArg) +{ + #define SBE_FUNC "sbeContinueBoot " + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t len = 0; + sbeRespGenHdr_t respHdr; + respHdr.init(); + + do + { + // Dequeue the EOT entry as no more data is expected. + rc = sbeUpFifoDeq_mult (len, NULL); + if(rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // let command processor routine handle the RC + break; + } + + uint32_t distance = 1; + len = sizeof(respHdr)/sizeof(uint32_t); + rc = sbeDownFifoEnq_mult ( len, ( uint32_t *) &respHdr); + if (rc) + { + break; + } + distance += len; + + len = sizeof(distance)/sizeof(uint32_t); + rc = sbeDownFifoEnq_mult ( len, &distance); + if (rc) + { + break; + } + rc = sbeDownFifoSignalEot(); + if (rc) + { + break; + } + + // Expecting this to be in PLCK Mode and not in Istep mode + if(SbeRegAccess::theSbeRegAccess().isDestBitRuntime()) + { + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_CONTINUE_BOOT_RUNTIME_EVENT); + // Nothing to do here. + } + else + { + SBE_INFO(SBE_FUNC"Continuous IPL Mode set... IPLing"); + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_CONTINUE_BOOT_PLCK_EVENT); + sbeDoContinuousIpl(); + } + }while(0); + + SBE_DEBUG(SBE_FUNC "RC = 0x%08X", rc); + return rc; + #undef SBE_FUNC +} + +//---------------------------------------------------------------------------- +void sbeDoContinuousIpl() +{ + #define SBE_FUNC "sbeDoContinuousIpl " + SBE_ENTER(SBE_FUNC); + ReturnCode l_rc = FAPI2_RC_SUCCESS; + do + { + // An array that holds the max number of minor steps per major step + const uint8_t l_minorSteps[] = + { + ISTEP2_MAX_SUBSTEPS, + ISTEP3_MAX_SUBSTEPS, + ISTEP4_MAX_SUBSTEPS, + ISTEP5_MAX_SUBSTEPS + }; + + // Where does each minor istep start from? + const uint8_t l_minorStartStep[] = + { + ISTEP2_MINOR_START, + ISTEP_MINOR_START, + ISTEP_MINOR_START, + ISTEP_MINOR_START + }; + + // Set SBE state as IPLing + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_PLCK_EVENT); + bool l_done = false; + // Run isteps + for(uint8_t l_major = SBE_ISTEP_FIRST; + (l_major <= SBE_ISTEP_LAST_MASTER) && + (false == l_done); + ++l_major) + { + for(uint8_t l_minor = l_minorStartStep[l_major - SBE_ISTEP_FIRST]; + l_minor <= l_minorSteps[l_major - SBE_ISTEP_FIRST]; + ++l_minor) + { + l_rc = sbeExecuteIstep(l_major, l_minor); + if(l_rc != FAPI2_RC_SUCCESS) + { + SBE_ERROR(SBE_FUNC"Failed istep execution in plck mode: " + "Major: %d, Minor: %d", l_major, l_minor); + l_done = true; + break; + } + // Check if we are at step 3.20 on the slave SBE + if(((SBE_ISTEP_LAST_SLAVE == l_major) && + (SLAVE_LAST_MINOR_ISTEP == l_minor)) && + (SBE_ROLE_SLAVE == g_sbeRole)) + { + l_done = true; + break; + } + } + } + } while(false); + // Store l_rc in a global variable that will be a part of the SBE FFDC + g_iplFailRc = l_rc; + SBE_EXIT(SBE_FUNC); + #undef SBE_FUNC +} + +// TODO - RTC 133367 +//---------------------------------------------------------------------------- +uint32_t sbeEnterMpipl(uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeEnterMpipl " + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t len = 0; + sbeRespGenHdr_t l_respHdr; + l_respHdr.init(); + + do + { + // Dequeue the EOT entry as no more data is expected. + l_rc = sbeUpFifoDeq_mult (len, NULL); + if ( l_rc != SBE_SEC_OPERATION_SUCCESSFUL ) + { + // Let command processor routine to handle the RC + break; + } + + sbeResponseFfdc_t l_ffdc; + l_rc = sbeDsSendRespHdr( l_respHdr, l_ffdc); + + // set state to MPIPL Wait + (void)SbeRegAccess::theSbeRegAccess(). + stateTransition(SBE_ENTER_MPIPL_EVENT); + + //TODO RTC-123696 MPIPL Related procedure/steps + }while(0); + return l_rc; + #undef SBE_FUNC +} + +// TODO - RTC 133367 +//---------------------------------------------------------------------------- +uint32_t sbeContinueMpipl(uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeContinueMpipl " + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t len = 0; + sbeRespGenHdr_t l_respHdr; + l_respHdr.init(); + + do + { + // Dequeue the EOT entry as no more data is expected. + l_rc = sbeUpFifoDeq_mult (len, NULL); + if ( l_rc != SBE_SEC_OPERATION_SUCCESSFUL ) + { + // Let command processor routine to handle the RC + break; + } + + sbeResponseFfdc_t l_ffdc; + l_rc = sbeDsSendRespHdr( l_respHdr, l_ffdc); + + //TODO RTC-134278 Continue MPIPL Related procedure/steps + + // TODO - Once continue steps are over, it will trigger the + // istep5.2 and transition to runtime will happen + + }while(0); + + return l_rc; + #undef SBE_FUNC +} + + diff --git a/src/sbefw/sbecmdiplcontrol.H b/src/sbefw/sbecmdiplcontrol.H new file mode 100644 index 00000000..e06757c5 --- /dev/null +++ b/src/sbefw/sbecmdiplcontrol.H @@ -0,0 +1,117 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdiplcontrol.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbecmdiplcontrol.H + * + * @brief This file contains the SBE command details + * + */ + +#ifndef __SBEFW_SBECMDIPLCONTROL_H +#define __SBEFW_SBECMDIPLCONTROL_H + +#include + +namespace fapi2 +{ + class ReturnCode; +} + +/** + * @brief execute istep chipop (0xA101) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeHandleIstep(uint8_t *i_pArg); + + +/** + * @brief Handles Sbe continue boot after collect ffdc chip-op (0xA102) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeContinueBoot(uint8_t *i_pArg); + + +/** + * @brief Executes IPL steps in continuous mode. + * + * @par On the master SBE, this will run + * all steps from 2.2 to 5.2. On the slave SBE, it runs all steps from 2.2 + * to 3.18. + * In case an error is encountered, the execution is aborted. + */ +void sbeDoContinuousIpl(); + +/** + * @brief Handles Sbe Enter Mpipl chip-op (0xA901) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeEnterMpipl(uint8_t *i_pArg); + +/** + * @brief Handles Sbe Continue Mpipl chip-op (0xA902) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeContinueMpipl(uint8_t *i_pArg); + +/** + * @brief Handles Sbe Get FFDC chip-op (0xA801) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetSbeFfdc(uint8_t *i_pArg); + +/** + * @brief Handles Sbe Get FFDC chip-op (0xA803) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetFreqSupported(uint8_t *i_pArg); + +/** + * @brief Handles Sbe Abort chip-op (0xA804) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeAbort(uint8_t *i_pArg); + + +#endif // __SBEFW_SBECMDIPLCONTROL_H diff --git a/src/sbefw/sbecmdmemaccess.C b/src/sbefw/sbecmdmemaccess.C new file mode 100644 index 00000000..942bb72d --- /dev/null +++ b/src/sbefw/sbecmdmemaccess.C @@ -0,0 +1,778 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdmemaccess.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbecmdmemaccess.C + * + * @brief This file contains the SBE Memory Access chipOps + * + */ + +#include "sbecmdmemaccess.H" +#include "sbefifo.H" +#include "sbe_sp_intf.H" +#include "sbetrace.H" +#include "sbeFifoMsgUtils.H" +#include "sbeutil.H" + +#include "fapi2.H" + +#include "p9_pba_setup.H" +#include "p9_adu_setup.H" +#include "p9_pba_access.H" +#include "p9_adu_access.H" + + +using namespace fapi2; + +// Buffer requirement for ADU and PBA on the stack +static const uint32_t MAX_ADU_BUFFER = 40; +static const uint32_t MAX_PBA_BUFFER = 32; +// PBA / ADU Granule size as per the HWP Requirement +static const uint32_t PBA_GRAN_SIZE_BYTES = 128; +static const uint32_t ADU_GRAN_SIZE_BYTES = 8; + +// Multiplier factor with respect to the FIFO length +static const uint32_t ADU_SIZE_MULTIPLIER_FOR_LEN_ALIGNMENT = 2; +static const uint32_t PBA_SIZE_MULTIPLIER_FOR_LEN_ALIGNMENT = 32; + +//Default EX Target ChipletId to be used in PBA by default +static const uint32_t PBA_DEFAULT_EX_CHIPLET_ID = 7; + +/** + * @brief static definition of parameters passed in adu chip-ops + */ +static const uint32_t SBE_ADU_LOCK_TRIES = 3; + +// Transaction size (choice is 1, 2, 4, or 8) +// 0b00: TSIZE_1 +// 0b01: TSIZE_2 +// 0b10: TSIZE_4 +// 0b11: TSIZE_8 +static const uint32_t SBE_ADU_TRANSACTION_SIZE = 3; +static const bool SBE_ADU_LEAVE_DIRTY_BOOL = false; +static const bool SBE_ADU_LOCK_PICK_BOOL = false; + +/** + * @brief Mask used to build the Flag struct for ADU chip-op + **/ +static const uint32_t ADU_LOCK_TRIES_SHIFT = 16; +static const uint32_t ADU_TRANSACTION_SIZE_SHIFT = 20; +static const uint32_t ADU_ECC_OVERRIDE_BIT_SHIFT = 22; +static const uint32_t ADU_ECC_REQUIRED_BIT_SHIFT = 23; +static const uint32_t ADU_ITAG_REQUIRED_BIT_SHIFT = 24; +static const uint32_t ADU_FAST_MODE_SHIFT = 25; +static const uint32_t ADU_LEAVE_DIRTY_SHIFT = 26; +static const uint32_t ADU_LOCK_PICK_SHIFT = 27; +static const uint32_t ADU_AUTO_INCR_SHIFT = 28; +static const uint32_t CACHE_INHIBIT_MODE_SHIFT = 29; + +// Fast Mode bit shift for PBA +static const uint32_t PBA_FAST_MODE_SHIFT = 31; + +/////////////////////////////////////////////////////////////////////// +// @brief align4ByteWordLength - Internal Method to this file +// Align the length passed and return number of words +// +// @param [in] i_len, length pass from user in Bytes +// +// @return Number of words (number of 4byte length) +/////////////////////////////////////////////////////////////////////// +inline uint32_t align4ByteWordLength(uint32_t i_len) +{ + if(i_len % 4 != 0) + { + i_len = i_len + (4 - (i_len % 4)); + } + return(i_len/4); +} + +/////////////////////////////////////////////////////////////////////// +// @brief calInterAduLenForUpFifo - Internal Method to this file +// Calculate Intermediate Adu Data length for Upstream Fifo +// +// @param [in] i_mod, Modulus number from user, (from numGranules % 4) +// could be any values from 1,2,3 +// @param [in] i_itag, Itag flag +// @param [in] i_ecc, Ecc flag +// +// @return length in bytes for intermediate ADU length +/////////////////////////////////////////////////////////////////////// +inline uint32_t calInterAduLenForUpFifo(uint8_t i_mod, bool i_itag, bool i_ecc) +{ + //Default init length with either Ecc or Itag + uint32_t l_len = + ((ADU_GRAN_SIZE_BYTES + 1) * (1 + i_mod)); + // If ECC and iTag bit is also part of the buffer + if(i_itag && i_ecc) + { + l_len = l_len + (1 + i_mod); + } + return (l_len); +} + +/////////////////////////////////////////////////////////////////////// +// @brief sbeAduLenInUpStreamFifo - Internal Method to this file +// Calculate the Final Size which is write/read to/from HWP +// +// @param [in] i_numGranules, Number of granules read/write +// @param [in] i_itag, Itag flag +// @param [in] i_ecc, Ecc flag +// +// @return Length in bytes for ADU to be put in Upstream FIFO +/////////////////////////////////////////////////////////////////////// +inline uint32_t sbeAduLenInUpStreamFifo(uint32_t i_numGranules, + bool i_itag, + bool i_ecc) +{ + uint32_t l_respLen = i_numGranules * ADU_GRAN_SIZE_BYTES; + if(i_itag) + { + // Add one byte for Itag for Each Granule Completed + l_respLen = l_respLen + i_numGranules; + } + if(i_ecc) + { + // Add one byte for Ecc for Each Granule Completed + l_respLen = l_respLen + i_numGranules; + } + return l_respLen; +} + +/////////////////////////////////////////////////////////////////////// +// @brief flushUpstreamFifo - Internal Method to this file, to flush +// out the upstream fifo +// +// @param [in] i_fapiRc, Fapi RC +// +// @return RC from the underlying FIFO utility +/////////////////////////////////////////////////////////////////////// +inline uint32_t flushUpstreamFifo (const uint32_t &i_fapiRc) +{ + uint32_t l_len2dequeue = 0; + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + if ( i_fapiRc != FAPI2_RC_SUCCESS ) + { + l_rc = sbeUpFifoDeq_mult(l_len2dequeue, NULL, + true, true); + } + // For other success paths, just attempt to offload + // the next entry, which is supposed to be the EOT entry + else + { + l_rc = sbeUpFifoDeq_mult(l_len2dequeue, NULL, true); + } + return l_rc; +} + + +/////////////////////////////////////////////////////////////////////// +// @brief constructAduFlag - Internal Method to this file, to construct +// ADU flag as the HWP expects +// +// @param [in] i_hdr, Message Request Header +// @param [in] i_isFlagRead, Read/Write Flag +// +// @return Constructed ADU Flag +/////////////////////////////////////////////////////////////////////// +uint32_t constructAduFlag(const sbeMemAccessReqMsgHdr_t & i_hdr, + const bool i_isFlagRead) +{ + #define SBE_FUNC " constructAduFlag" + + // Fast Mode / Ecc mode / Cache Inhibit Mode / Auto Increment + // required in ADU operations. + bool l_isFastMode = i_hdr.isFastModeSet(); + bool l_isCacheInhibitMode = i_hdr.isCacheInhibitModeFlagSet(); + bool l_isItagBit = i_hdr.isItagFlagSet(); + bool l_isAutoIncr = i_hdr.isAutoIncrModeSet(); + bool l_isEccRequiredMode = false; + bool l_isEccOverrideMode = false; + + if(!i_isFlagRead) // ECC override in write mode + { + l_isEccOverrideMode = i_hdr.isEccOverrideFlagSet(); + if(l_isEccOverrideMode) + { + l_isEccRequiredMode = true; + } + } + else // ECC required in read mode + { + l_isEccRequiredMode = i_hdr.isEccFlagSet(); + } + + // Construct the flag required for adu setup + uint32_t l_aduSetupFlag = + ( (l_isCacheInhibitMode << CACHE_INHIBIT_MODE_SHIFT) | + // 3-bit of Cache mode placed in 31-30-29 bits + (l_isAutoIncr << ADU_AUTO_INCR_SHIFT) | + // 1-bit Auto increment placed at 28th bit + (SBE_ADU_LOCK_PICK_BOOL << ADU_LOCK_PICK_SHIFT) | + // 1-bit pick lock placed at 27th bit + (SBE_ADU_LEAVE_DIRTY_BOOL << ADU_LEAVE_DIRTY_SHIFT) | + // 1-bit leave dirty placed at 26th bit + (l_isFastMode << ADU_FAST_MODE_SHIFT) | + // 1-bit Fast mode placed at 25th bit + (l_isItagBit << ADU_ITAG_REQUIRED_BIT_SHIFT) | + // 1-bit itag placed at 24th bit + (l_isEccRequiredMode << ADU_ECC_REQUIRED_BIT_SHIFT) | + // 1-bit ecc required at 23rd bit + (l_isEccOverrideMode << ADU_ECC_OVERRIDE_BIT_SHIFT) | + // 1-bit ecc override at 22nd bit + (SBE_ADU_TRANSACTION_SIZE << ADU_TRANSACTION_SIZE_SHIFT) | + // 2-bit Transcation size at 21-20th bits + (SBE_ADU_LOCK_TRIES << ADU_LOCK_TRIES_SHIFT) ); + // 4-bit Lock Tries at 19-18-17-16 bits + + SBE_INFO(SBE_FUNC "Cache[%d] Itag[%d] AutoIncr[%d] FastMode[%d] ", + l_isCacheInhibitMode,l_isItagBit,l_isAutoIncr,l_isFastMode); + SBE_INFO(SBE_FUNC "EccRequiredMode[%d] EccOverrideMode[%d] EccOverrideByte" + "[0x%02X] AduSetupFlag[0x%04X]",l_isEccRequiredMode,l_isEccOverrideMode, + i_hdr.eccByte, l_aduSetupFlag); + + return (l_aduSetupFlag); + #undef SBE_FUNC +} + +/////////////////////////////////////////////////////////////////////// +// @brief processPbaRequest - Internal Method to this file, +// To process the PBA Access request +// +// @param [in] i_hdr, Message Request Header +// @param [in] i_isFlagRead, Read/Write Flag +// +// @return RC from the method +/////////////////////////////////////////////////////////////////////// +uint32_t processPbaRequest(const sbeMemAccessReqMsgHdr_t &i_hdr, + const bool i_isFlagRead) +{ + #define SBE_FUNC " processPbaRequest " + SBE_ENTER(SBE_FUNC); + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + ReturnCode l_fapiRc = FAPI2_RC_SUCCESS; + sbeRespGenHdr_t l_respHdr; + l_respHdr.init(); + sbeResponseFfdc_t l_ffdc; + + // Default for PBA + uint32_t l_sizeMultiplier = PBA_SIZE_MULTIPLIER_FOR_LEN_ALIGNMENT; + uint32_t l_granuleSize = PBA_GRAN_SIZE_BYTES; + uint64_t l_addr = i_hdr.getAddr(); + + // Proc Chip Target + Target l_proc = plat_getChipTarget(); + // Default EX Target Init..Not changing it for the time being + Target l_ex((uint64_t)PBA_DEFAULT_EX_CHIPLET_ID); + + // Determine the access flags + // Fast mode flag + bool l_isFastMode = i_hdr.isFastModeSet(); + //LCO Mode for PBA-Put + bool l_isLcoMode = i_hdr.isPbaLcoModeSet(); + if(l_isLcoMode) + { + //Derive the EX target from the input Core Chiplet Id + //Core0/1 -> EX0, Core2/3 -> EX1, Core4/5 -> EX2, Core6/7 -> EX3 + //..so on + l_ex = plat_getTargetHandleByChipletNumber + (i_hdr.coreChipletId); + } + // By default, ex_chipletId printed below won't be used unless accompanied + // by LCO_mode. + SBE_INFO(SBE_FUNC "FAST_Mode[%d] LCO_Mode[%d] EX_ChipletId[%d]", + l_isFastMode, l_isLcoMode, (i_hdr.coreChipletId)/2); + + // The max granule size for which the ADU/PBA interface if configured + uint32_t l_numGranules = 0; + // Keeps track of number of granules sent to HWP + uint64_t l_granulesCompleted = 0; + + // Input Data length in alignment with PBA (128 Bytes) + uint64_t l_lenCacheAligned = i_hdr.getDataLenCacheAlign(); + SBE_DEBUG(SBE_FUNC "Data Aligned Len / Number of data granules = %d", + l_lenCacheAligned); + + while (l_granulesCompleted < l_lenCacheAligned) + { + // Call the PBA setup HWP + l_fapiRc = p9_pba_setup( + l_proc, + l_ex, + l_addr, + i_isFlagRead, + ((l_isFastMode) ? (1< l_proc = plat_getChipTarget(); + + // The max granule size for which the ADU/PBA interface if configured + uint32_t l_numGranules = 0; + // Keeps track of number of granules sent to HWP + uint64_t l_granulesCompleted = 0; + + // Input Data length in alignment with PBA (128 Bytes) + uint64_t l_lenCacheAligned = i_hdr.getDataLenCacheAlign(); + SBE_DEBUG(SBE_FUNC "Data Aligned Len / Number of data granules = %d", + l_lenCacheAligned); + + while (l_granulesCompleted < l_lenCacheAligned) + { + // Call the ADU setup HWP + l_fapiRc = p9_adu_setup (l_proc, + l_addr, + i_isFlagRead, + l_aduSetupFlags, + l_numGranules); + // if p9_adu_setup returns error + if( (l_fapiRc != FAPI2_RC_SUCCESS) ) + { + SBE_ERROR(SBE_FUNC" p9_adu_setup Failed"); + // Respond with HWP FFDC + l_respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION ); + l_ffdc.setRc(l_fapiRc); + break; + } + // Assumption is Hwp won't return zero for Num Granules + assert(0 != l_numGranules); + + SBE_INFO(SBE_FUNC "Hwp returned l_numGranules=[0x%08X]",l_numGranules); + uint64_t l_numAcc = 0; + + if (l_numGranules < (l_lenCacheAligned - l_granulesCompleted)) + { + l_numAcc = l_numGranules; + } + else + { + l_numAcc = l_lenCacheAligned - l_granulesCompleted; + } + + // 8Byte granule for ADU access + uint32_t l_dataFifo[MAX_ADU_BUFFER] = {0}; + + uint64_t l_numCurrAcc = 0; + while (l_numCurrAcc < l_numAcc) + { + bool l_lastGran = (l_numCurrAcc == (l_numAcc-1)) ? true : false; + bool l_firstGran = (l_numCurrAcc == 0) ? true : false; + + // With ECC or ITAG the output length of a granule will become + // 9 bytes instead of 8, To align it we will merge 4 output granule + // before putting it in the Downstream FIFO i.e. 9*4 = 36Bytes + // which is 4Bytes aligned size. + // With Both ECC and ITag, the o/p length of a granule will become + // 10Bytes instead of 8, To align it we will merge 4 output granule + // before putting it in the Downstream FIFO i.e. 10*4 = 40bytes + // So in ADU Read case we will use the same buffer with 10Bytes + // offset to fill the 40bytes. + + // Both Ecc and ITag Present = 40Bytes is the alignment length + /* D[00] D[01] D[02] D[03] D[04] D[05] D[06] D[07] -> 8 Data Bytes + * D[08-Itag] D[09-Ecc] D[0a] D[0b] D[0c] D[0d] D[0e] D[0f] -> 6D B + * D[10] D[11] D [12-Itag] D[13-Ecc] D[14] D[15] D[16] D[17] + * D[18] D[19] D[1a] D[1b] D[1c-Itag] D[1d-Ecc] D[1e] D[1f] + * D[20] D[21] D[22] D[23] D[24] D[25] D[26-Itag] D[27-Ecc] + */ + // Only Ecc Present = 36 Bytes is the alignment length + /* D[00] D[01] D[02] D[03] D[04] D[05] D[06] D[07] -> 8 Data Bytes + * D[08-Ecc] D[09] D[0a] D[0b] D[0c] D[0d] D[0e] D[0f] -> 7D B + * D[10] D[11-Ecc] D [12] D[13] D[14] D[15] D[16] D[17] + * D[18] D[19] D[1a-Ecc] D[1b] D[1c] D[1d] D[1e] D[1f] + * D[20] D[21] D[22] D[23-Ecc] + */ + // Only ITag Present = 36 Bytes is the alignment length + /* D[00] D[01] D[02] D[03] D[04] D[05] D[06] D[07] -> 8 Data Bytes + * D[08-Itag] D[09] D[0a] D[0b] D[0c] D[0d] D[0e] D[0f] -> 7D B + * D[10] D[11-Itag] D [12] D[13] D[14] D[15] D[16] D[17] + * D[18] D[19] D[1a-Itag] D[1b] D[1c] D[1d] D[1e] D[1f] + * D[20] D[21] D[22] D[23-Itag] + */ + uint8_t l_bufIdx = 0; + + // If this is putmem request, read input data from the upstream FIFO + if (!i_isFlagRead) + { + // l_sizeMultiplier * 4B Upstream FIFO = Granule size 128B + uint32_t l_len2dequeue = l_sizeMultiplier; + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, + (uint32_t *)&l_dataFifo, + false); + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc); + + // Insert the ECC if ECC Mode is set + if(l_isEccMode) + { + uint8_t l_eccPos = 8; + if(l_isItagMode) + { + l_eccPos = 9; + } + ((uint8_t*)&l_dataFifo)[l_eccPos] = i_hdr.eccByte; + } + } + else + { + //Adu Read Mode - with either ECC or ITag or Both + // Calculate the MODULUS + uint8_t l_mod = (l_numCurrAcc % 4); + if( (l_mod) && ((l_isEccMode) || (l_isItagMode)) ) + { + // Default Init it for 1byte extra + l_bufIdx = (ADU_GRAN_SIZE_BYTES * l_mod) + l_mod; + if((l_isEccMode) && (l_isItagMode)) + { + l_bufIdx = l_bufIdx + l_mod; + } + } + } + + // Call ADU access HWP for ADU write/read request + l_fapiRc = p9_adu_access ( + l_proc, + l_addr, + i_isFlagRead, + l_aduSetupFlags, + l_firstGran, + l_lastGran, + &(((uint8_t *)&(l_dataFifo))[l_bufIdx])); + // if p9_adu_access returns error + if( l_fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" p9_adu_access Failed"); + // Respond with HWP FFDC + l_respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION ); + l_ffdc.setRc(l_fapiRc); + break; + } + + // If this is a getmem request, + // need to push the data into the downstream FIFO + if (i_isFlagRead) + { + // Number of 4Bytes to put, to align with Granule Size + uint32_t l_len = l_sizeMultiplier; // l_len*4 = Granule Size + + //Enter the below 'if' if ADU Read Mode with Either Ecc or ITag + //or both set. During non-aligned Transaction (but not the last) + //then set the len as zero so as to skip the unalign byte send, + //during next transaction when the data is aligned it will take + //care of sending all granules. + //If the below condition is not met then for ADU Read Mode will + //happen to write on DownStream FIFO for each granule. + + //Calculate the MODULUS + uint8_t l_mod = (l_numCurrAcc % 4); + if((l_isEccMode) || (l_isItagMode)) + { + if( (l_mod == 3) || (l_lastGran) ) + { + l_len = calInterAduLenForUpFifo(l_mod,l_isItagMode, + l_isEccMode); + l_len = align4ByteWordLength(l_len); + } + else + { + // If it is not the last granule or on the 4th entry + // into the data buffer, need not send it to Upstream + // Fifo + l_len = 0; + } + } + if(l_len) + { + l_rc = sbeDownFifoEnq_mult (l_len, (uint32_t *)&l_dataFifo); + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc); + } + } + l_granulesCompleted++; + l_numCurrAcc++; + } // End inner while loop + + if ( (l_fapiRc != FAPI2_RC_SUCCESS) || + (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) ) + { + break; + } + + l_addr += l_granuleSize * l_granulesCompleted; + } // End..while (l_granulesCompleted < l_lenCacheAligned); + + // Now build and enqueue response into downstream FIFO + do + { + // If there was a FIFO error, will skip sending the response, + // instead give the control back to the command processor thread + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc); + // If there was a HWP failure for putmem request, + // need to Flush out upstream FIFO, until EOT arrives + if (!i_isFlagRead) + { + l_rc = flushUpstreamFifo(l_fapiRc); + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc); + } + + // first enqueue the length of data actually written + uint32_t l_len = 1; + uint32_t l_respLen = sbeAduLenInUpStreamFifo( + l_granulesCompleted, + l_isItagMode, + l_isEccMode); + + SBE_INFO(SBE_FUNC "Total length Pushed for ChipOp [%d]", l_respLen); + l_rc = sbeDownFifoEnq_mult ( l_len, &l_respLen ); + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc); + + l_rc = sbeDsSendRespHdr( l_respHdr, l_ffdc); + } while(false); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + +/////////////////////////////////////////////////////////////////////// +// @brief sbeMemAccess_Wrap Memory Access Wrapper function +// +// @param [in] i_isFlagRead Flag to indicate the memory Access Type +// true : GetMem ChipOp +// false : PutMem ChipOp +// +// @return RC from the method +/////////////////////////////////////////////////////////////////////// +uint32_t sbeMemAccess_Wrap(const bool i_isFlagRead) +{ + #define SBE_FUNC " sbeMemAccess_Wrap " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + // Create an instance of Memory Access ChipOp structure + sbeMemAccessReqMsgHdr_t l_req = {0}; + + // Offload the common header from the Upstream FIFO + uint32_t l_len2dequeue = sizeof(l_req) / sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult(l_len2dequeue, (uint32_t *)&l_req, i_isFlagRead); + + if(!l_rc) + { + // Calculate the PBA/ADU address from the given input + SBE_INFO(SBE_FUNC "Address Upper[0x%08X] Lower[0x%08X] Flags[0x%08X] " + "Length[0x%08X]", ((l_req.getAddr()>>32) & 0xFFFFFFFF), + (l_req.getAddr() & 0xFFFFFFFF), l_req.flags, l_req.len); + + // PBA + bool l_isPBA = l_req.isPbaFlagSet(); + if(l_isPBA) + { + l_rc = processPbaRequest(l_req, i_isFlagRead); + if(l_rc) + { + SBE_ERROR(SBE_FUNC "processPbaRequest failed"); + } + } + // ADU + else + { + l_rc = processAduRequest(l_req, i_isFlagRead); + if(l_rc) + { + SBE_ERROR(SBE_FUNC "processAduRequest failed"); + } + } + } + // If there was a FIFO error, will skip sending the response, + // instead give the control back to the command processor thread + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbePutMem (uint8_t *i_pArg) +{ + return sbeMemAccess_Wrap (false); +} + +///////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeGetMem (uint8_t *i_pArg) +{ + return sbeMemAccess_Wrap (true); +} + diff --git a/src/sbefw/sbecmdmemaccess.H b/src/sbefw/sbecmdmemaccess.H new file mode 100644 index 00000000..6a2449fc --- /dev/null +++ b/src/sbefw/sbecmdmemaccess.H @@ -0,0 +1,54 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdmemaccess.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbecmdmemaccess.H + * + * @brief This file contains the Interfaces for the Memory Access chip-ops + * + */ + +#ifndef __SBEFW_SBECMDMEMACCESS_H +#define __SBEFW_SBECMDMEMACCESS_H + +#include + +/** + * @brief sbeGetMem : Implements SBE Get Memory ChipOp + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetMem (uint8_t *i_pArg); + +/** + * @brief sbePutMem : Implements SBE Put Memory ChipOp + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbePutMem (uint8_t *i_pArg); + +#endif /* __SBEFW_SBECMDMEMACCESS_H */ diff --git a/src/sbefw/sbecmdparser.C b/src/sbefw/sbecmdparser.C new file mode 100644 index 00000000..c22e67c7 --- /dev/null +++ b/src/sbefw/sbecmdparser.C @@ -0,0 +1,483 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdparser.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbecmdparser.C + * + * @brief This file contains the SBE FIFO Commands + * + */ + +#include "sbecmdparser.H" +#include "sbecmdscomaccess.H" +#include "sbecmdiplcontrol.H" +#include "sbecmdgeneric.H" +#include "sbecmdmemaccess.H" +#include "sbecmdregaccess.H" +#include "sbecmdcntrldmt.H" +#include "sbecmdringaccess.H" +#include "sbecmdsram.H" +#include "sbecmdcntlinst.H" +#include "sbecmdringaccess.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "sbeHostMsg.H" +#include "sbe_host_intf.H" +#include "sbestates.H" +#include "sberegaccess.H" + +// Declaration +static const uint16_t HARDWARE_FENCED_STATE = + SBE_FENCE_AT_CONTINUOUS_IPL|SBE_FENCE_AT_QUIESCE| + SBE_FENCE_AT_DMT; + +static const uint16_t PUT_HARDWARE_FENCED_STATE = + HARDWARE_FENCED_STATE|SBE_FENCE_AT_MPIPL; + +//////////////////////////////////////////////////////////////// +// @brief g_sbeScomCmdArray +//////////////////////////////////////////////////////////////// +static sbeCmdStruct_t g_sbeScomCmdArray [] = +{ + {sbeGetScom, + SBE_CMD_GETSCOM, + HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, + {sbePutScom, + SBE_CMD_PUTSCOM, + PUT_HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, + {sbeModifyScom, + SBE_CMD_MODIFYSCOM, + PUT_HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, + {sbePutScomUnderMask, + SBE_CMD_PUTSCOM_MASK, + PUT_HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, + {sbeMultiScom, + SBE_CMD_MULTISCOM, + PUT_HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, +}; + +//////////////////////////////////////////////////////////////// +// @brief g_sbeIplControlCmdArray +// +//////////////////////////////////////////////////////////////// +static sbeCmdStruct_t g_sbeIplControlCmdArray [] = +{ + {sbeHandleIstep, + SBE_CMD_EXECUTE_ISTEP, + PUT_HARDWARE_FENCED_STATE|SBE_FENCE_AT_RUNTIME| + SBE_FENCE_AT_DUMPING, + // This is allowed in FFDC Collect state + // TODO - Issue 157287 - Allow MPIIPL in Isteps state + }, + + {sbeContinueBoot, + SBE_CMD_CONTINUE_BOOT, + PUT_HARDWARE_FENCED_STATE|SBE_FENCE_AT_RUNTIME| + SBE_FENCE_AT_DUMPING|SBE_FENCE_AT_ISTEP, + // This is allowed only in FFDC Collect State in PLCK mode + }, +}; + +//////////////////////////////////////////////////////////////// +// @brief g_sbeGenericCmdArray +// +//////////////////////////////////////////////////////////////// +static sbeCmdStruct_t g_sbeGenericCmdArray [] = +{ + {sbeGetCapabilities, + SBE_CMD_GET_SBE_CAPABILITIES, + SBE_STATE_FFDC_COLLECT, + // Fence in FFDC Collect State, since it might over-write traces + }, +}; + +////////////////////////////////////////////////////////////// +// @brief g_sbeMemoryAccessCmdArray +// +////////////////////////////////////////////////////////////// +static sbeCmdStruct_t g_sbeMemoryAccessCmdArray [] = +{ + {sbeGetMem, + SBE_CMD_GETMEM, + HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, + + {sbePutMem, + SBE_CMD_PUTMEM, + PUT_HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, + + {sbeGetOccSram, + SBE_CMD_GETSRAM_OCC, + HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, + + {sbePutOccSram, + SBE_CMD_PUTSRAM_OCC, + PUT_HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, +}; + +////////////////////////////////////////////////////////////// +// @brief g_sbeInstructionCntlCmdArray +// +////////////////////////////////////////////////////////////// +static sbeCmdStruct_t g_sbeInstructionCntlCmdArray[] = +{ + {sbeCntlInst, + SBE_CMD_CONTROL_INSTRUCTIONS, + PUT_HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, +}; + +////////////////////////////////////////////////////////////// +// @brief g_sbeRegAccessCmdArray +// +////////////////////////////////////////////////////////////// +static sbeCmdStruct_t g_sbeRegAccessCmdArray [] = +{ + {sbeGetReg, + SBE_CMD_GETREG, + PUT_HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, + + {sbePutReg, + SBE_CMD_PUTREG, + PUT_HARDWARE_FENCED_STATE|SBE_STATE_FFDC_COLLECT, + }, +}; + +////////////////////////////////////////////////////////////// +// @brief g_sbeMpiplCmdArray +// +////////////////////////////////////////////////////////////// +static sbeCmdStruct_t g_sbeMpiplCmdArray[] = +{ + {sbeEnterMpipl, + SBE_CMD_MPIPL_ENTER, + PUT_HARDWARE_FENCED_STATE|SBE_FENCE_AT_ISTEP| + SBE_FENCE_AT_DUMPING|SBE_FENCE_AT_ABORT, + // Allow Fspless system to enter MPIPL + // Honour MPIPL at FFDC Collect state + // Issue 157287 + }, + + {sbeContinueMpipl, + SBE_CMD_MPIPL_CONTINUE, + HARDWARE_FENCED_STATE|SBE_FENCE_AT_ISTEP| + SBE_FENCE_AT_RUNTIME|SBE_FENCE_AT_DUMPING| + SBE_FENCE_AT_ABORT|SBE_FENCE_AT_FFDC_COLLECT, + // Only allowed State is MPIPL + }, +}; + +////////////////////////////////////////////////////////////// +// @brief g_sbeRingAccessCmdArray +// +////////////////////////////////////////////////////////////// +static sbeCmdStruct_t g_sbeRingAccessCmdArray [] = +{ + {sbeGetRing, + SBE_CMD_GETRING, + SBE_FENCE_AT_CONTINUOUS_IPL, + }, +}; + +////////////////////////////////////////////////////////////// +// @brief g_sbeCoreStateControlCmdArray +// +////////////////////////////////////////////////////////////// +static sbeCmdStruct_t g_sbeCoreStateControlCmdArray [] = +{ + {sbeControlDeadmanTimer, + SBE_PSU_CMD_CONTROL_DEADMAN, + SBE_FENCE_AT_CONTINUOUS_IPL|SBE_FENCE_AT_QUIESCE| + SBE_FENCE_AT_MPIPL|SBE_FENCE_AT_ISTEP| + SBE_FENCE_AT_DUMPING|SBE_FENCE_AT_ABORT| + SBE_FENCE_AT_FFDC_COLLECT, + }, +}; + +////////////////////////////////////////////////////////////// +// @brief g_sbePutRingFromImageCmdArray +// +////////////////////////////////////////////////////////////// +static sbeCmdStruct_t g_sbePutRingFromImageCmdArray [] = +{ + {sbePutRingFromImagePSU, + SBE_PSU_MSG_PUT_RING_FROM_IMAGE, + SBE_FENCE_AT_CONTINUOUS_IPL, + }, +}; + + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +uint8_t sbeGetCmdStructAttr (const uint8_t i_cmdClass, + sbeCmdStruct_t **o_ppCmd) +{ + #define SBE_FUNC " sbeGetCmdStructAttr " + uint8_t l_numCmds = 0; + *o_ppCmd = NULL; + + switch(i_cmdClass) + { + // FIFO Commands + case SBE_CMD_CLASS_IPL_CONTROL: + // @TODO via RTC : 128655 + // Use C++ style typecase + l_numCmds = sizeof(g_sbeIplControlCmdArray) / + sizeof(sbeCmdStruct_t); + *o_ppCmd = (sbeCmdStruct_t*)g_sbeIplControlCmdArray; + break; + case SBE_CMD_CLASS_SCOM_ACCESS: + l_numCmds = sizeof(g_sbeScomCmdArray) / + sizeof(sbeCmdStruct_t); + *o_ppCmd = (sbeCmdStruct_t*)g_sbeScomCmdArray; + break; + case SBE_CMD_CLASS_GENERIC_MESSAGE: + l_numCmds = sizeof(g_sbeGenericCmdArray) / + sizeof(sbeCmdStruct_t); + *o_ppCmd = (sbeCmdStruct_t*)g_sbeGenericCmdArray; + break; + + case SBE_CMD_CLASS_MEMORY_ACCESS: + l_numCmds = sizeof(g_sbeMemoryAccessCmdArray) / + sizeof(sbeCmdStruct_t); + *o_ppCmd = (sbeCmdStruct_t*)g_sbeMemoryAccessCmdArray; + break; + + case SBE_CMD_CLASS_INSTRUCTION_CONTROL: + l_numCmds = sizeof(g_sbeInstructionCntlCmdArray) / + sizeof(sbeCmdStruct_t); + *o_ppCmd = (sbeCmdStruct_t*)g_sbeInstructionCntlCmdArray; + break; + + case SBE_CMD_CLASS_REGISTER_ACCESS: + l_numCmds = sizeof(g_sbeRegAccessCmdArray) / + sizeof(sbeCmdStruct_t); + *o_ppCmd = (sbeCmdStruct_t*)g_sbeRegAccessCmdArray; + break; + + case SBE_CMD_CLASS_RING_ACCESS: + l_numCmds = sizeof(g_sbeRingAccessCmdArray) / + sizeof(sbeCmdStruct_t); + *o_ppCmd = (sbeCmdStruct_t*)g_sbeRingAccessCmdArray; + break; + + case SBE_CMD_CLASS_MPIPL_COMMANDS: + l_numCmds = sizeof(g_sbeMpiplCmdArray) / + sizeof(sbeCmdStruct_t); + *o_ppCmd = (sbeCmdStruct_t*)g_sbeMpiplCmdArray; + break; + + // PSU Commands + case SBE_PSU_CMD_CLASS_CORE_STATE: + l_numCmds = sizeof(g_sbeCoreStateControlCmdArray) / + sizeof(sbeCmdStruct_t); + *o_ppCmd = (sbeCmdStruct_t*)g_sbeCoreStateControlCmdArray; + break; + + case SBE_PSU_CMD_CLASS_RING_ACCESS: + l_numCmds = sizeof(g_sbePutRingFromImageCmdArray) / + sizeof(sbeCmdStruct_t); + *o_ppCmd = (sbeCmdStruct_t*)g_sbePutRingFromImageCmdArray; + break; + + // This will grow with each class of chipOp in future + default: + break; + } + return l_numCmds; + #undef SBE_FUNC +} + + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +uint8_t sbeValidateCmdClass (const uint8_t i_cmdClass, + const uint8_t i_cmdOpcode) +{ + #define SBE_FUNC " sbeValidateCmdClass " + uint8_t l_rc = SBE_SEC_COMMAND_NOT_SUPPORTED; + + SBE_INFO(SBE_FUNC"i_cmdClass[0x%02X], " + "i_cmdOpcode[0x%02X]", i_cmdClass, i_cmdOpcode); + + do + { + uint8_t l_numCmds = 0; + sbeCmdStruct_t *l_pCmd = NULL; + + l_numCmds = sbeGetCmdStructAttr (i_cmdClass, &l_pCmd); + if (!l_numCmds) + { + SBE_ERROR(SBE_FUNC"SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED " + "i_cmdClass[0x%02X], i_cmdOpcode[0x%02X]", + i_cmdClass, i_cmdOpcode); + // Command class not supported + l_rc = SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED; + break; + } + + // @TODO via RTC : 128654 + // Analyze on merging the validation functions into one + // and also on using loop vs switch case performance + for (uint8_t l_cnt = 0; l_cnt < l_numCmds; ++l_cnt, ++l_pCmd) + { + if (i_cmdOpcode == l_pCmd->cmd_opcode) + { + // Command found + l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + break; + } + } + } while (false); + + return l_rc; + #undef SBE_FUNC +} + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +bool sbeIsCmdAllowedAtState (const uint8_t i_cmdClass, + const uint8_t i_cmdOpcode) +{ + #define SBE_FUNC " sbeIsCmdAllowedAtState " + uint8_t l_numCmds = 0; + sbeCmdStruct_t *l_pCmd = NULL; + bool l_ret = false; + l_numCmds = sbeGetCmdStructAttr (i_cmdClass, &l_pCmd); + + for (uint8_t l_cnt = 0; l_cnt < l_numCmds; ++l_cnt, ++l_pCmd) + { + if (i_cmdOpcode == l_pCmd->cmd_opcode) + { + // Get the Present State + uint64_t l_state = + SbeRegAccess::theSbeRegAccess().getSbeState(); + SBE_INFO(SBE_FUNC "SBE State [0x%08X] Fence State[0x%04X]", + (uint32_t)(l_state & 0xFFFFFFFF),l_pCmd->cmd_state_fence); + + switch(l_state) + { + case SBE_STATE_QUIESCE: + case SBE_STATE_UNKNOWN: + case SBE_STATE_FAILURE: + // All operations are fenced here, return false + // Reset is the only Option available + break; + + case SBE_STATE_FFDC_COLLECT: + { + l_ret = ((l_pCmd->cmd_state_fence & + SBE_FENCE_AT_FFDC_COLLECT)? false:true); + break; + } + + case SBE_STATE_IPLING: + { + l_ret = ((l_pCmd->cmd_state_fence & + SBE_FENCE_AT_CONTINUOUS_IPL)? false:true); + break; + } + + case SBE_STATE_ISTEP: + { + l_ret = ((l_pCmd->cmd_state_fence & + SBE_FENCE_AT_ISTEP)? false:true); + break; + } + + case SBE_STATE_RUNTIME: + { + l_ret = ((l_pCmd->cmd_state_fence & + SBE_FENCE_AT_RUNTIME)? false:true); + break; + } + + case SBE_STATE_DUMP: + { + l_ret = ((l_pCmd->cmd_state_fence & + SBE_FENCE_AT_DUMPING)? false:true); + break; + } + + case SBE_STATE_MPIPL: + { + l_ret = ((l_pCmd->cmd_state_fence & + SBE_FENCE_AT_MPIPL)? false:true); + break; + } + + case SBE_STATE_DMT: + { + l_ret = ((l_pCmd->cmd_state_fence & + SBE_FENCE_AT_DMT)? false:true); + break; + } + + case SBE_STATE_ABORT: + { + l_ret = ((l_pCmd->cmd_state_fence & + SBE_FENCE_AT_ABORT)? false:true); + break; + } + + default: break; + } + } + } + // For any other state, which is not handled above, return from here + return l_ret; + #undef SBE_FUNC +} + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +sbeCmdFunc_t sbeFindCmdFunc (const uint8_t i_cmdClass, + const uint8_t i_cmdOpcode) + +{ + #define SBE_FUNC " sbeFindCmdFunc " + uint8_t l_numCmds = 0; + sbeCmdStruct_t *l_pCmd = NULL; + + l_numCmds = sbeGetCmdStructAttr (i_cmdClass, &l_pCmd); + + for (uint8_t l_cnt = 0; l_cnt < l_numCmds; ++l_cnt, ++l_pCmd) + { + if (i_cmdOpcode == l_pCmd->cmd_opcode) + { + break; + } + } + + return l_pCmd ? (l_pCmd->cmd_func) : NULL; + #undef SBE_FUNC +} diff --git a/src/sbefw/sbecmdparser.H b/src/sbefw/sbecmdparser.H new file mode 100644 index 00000000..d51995f2 --- /dev/null +++ b/src/sbefw/sbecmdparser.H @@ -0,0 +1,119 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdparser.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbecmdparser.H + * + * @brief This file contains the SBE command details + * + */ + +#ifndef __SBEFW_SBECMDPARSER_H +#define __SBEFW_SBECMDPARSER_H + +#include + + +/** + * @brief SBE Command structure associating an opcode of a command + * to the processing function as well as the allowed states + * + */ +typedef uint32_t (*sbeChipOpFunc_t) (uint8_t *i_pArg); + +typedef struct { + sbeChipOpFunc_t cmd_func; /* Command function pointer */ + uint8_t cmd_opcode; /* Command opcode */ + uint16_t cmd_state_fence; /* Command fencing based on SBE state */ +} sbeCmdStruct_t; + +/** + * @brief SBE Command Fence attributes + * + */ +enum sbe_command_fence_attrs +{ + SBE_NO_FENCE = 0x0000, ///< Allow cmd in all states + SBE_FENCE_AT_ABORT = 0x0001, ///< Fence off at SBE Abort State + SBE_FENCE_AT_FFDC_COLLECT = 0x0002, ///< Fence off at FFDC Collect State + SBE_FENCE_AT_DUMPING = 0x0004, ///< Fence off at DUMPING State + SBE_FENCE_AT_MPIPL = 0x0010, ///< Fence off at MPIPL state + SBE_FENCE_AT_CONTINUOUS_IPL = 0x0040, ///< Fence off at cont IPL + SBE_FENCE_AT_ISTEP = 0x0080, ///< Fence off at istep state + SBE_FENCE_AT_RUNTIME = 0x0100, ///< Fence off at Runtime state + SBE_FENCE_AT_QUIESCE = 0x0200, ///< Fense off at Quiesce state + SBE_FENCE_AT_DMT = 0x0400, ///< Fense off at DMT state +}; + +/** + * @brief sbeValidateCmdClass Validates the command class and opcode + * + * @param[in] i_cmdClass Command class code + * @param[in] i_cmdOpcode Command opcode + * + * @return uint8_t return code + * SBE_SEC_OPERATION_SUCCESSFUL - Command found + * SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED + * SBE_SEC_COMMAND_NOT_SUPPORTED + */ +uint8_t sbeValidateCmdClass (const uint8_t i_cmdClass, + const uint8_t i_cmdOpcode); + +/** + * @brief sbeIsCmdAllowedAtState Validates if the command is allowed + * at the current SBE state + * + * @param[in] i_cmdClass Command class code + * @param[in] i_cmdOpcode Command opcode + * + * @return true command is allowed at the current state + * false command is not allowed at the current state + */ +bool sbeIsCmdAllowedAtState (const uint8_t i_cmdClass, + const uint8_t i_cmdOpcode); + + +/** + * @brief sbeCmdFunc_t Typical signature for any SBE ChipOp back-end function + * + * @param[in] uint8_t *i_pArg Pointer to the argument to be passed to + * the chipOp function + * + * @return uint32_t Return code from the chipOp function + */ +typedef uint32_t ( *sbeCmdFunc_t ) (uint8_t *i_pArg); + + +/** + * @brief sbeFindCmdFunc Finds the function corresponding to the command + * + * @param[in] i_cmdClass Command class code + * @param[in] i_cmdOpcode Command opcode + * + * @return sbeCmdFunc_t A pointer to the corresponding ChipOps function + */ +sbeCmdFunc_t sbeFindCmdFunc (const uint8_t i_cmdClass, + const uint8_t i_cmdOpcode); + + +#endif // __SBEFW_SBECMDPARSER_H diff --git a/src/sbefw/sbecmdprocessor.C b/src/sbefw/sbecmdprocessor.C new file mode 100644 index 00000000..6a945b4a --- /dev/null +++ b/src/sbefw/sbecmdprocessor.C @@ -0,0 +1,376 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdprocessor.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbecmdprocessor.C + * + * @brief This file contains the SBE Command processing Thread Routines + * + */ + + +#include "sbeexeintf.H" +#include "sbefifo.H" +#include "sbecmdparser.H" +#include "sbeirq.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "assert.h" +#include "sbeFifoMsgUtils.H" +#include "sbeerrorcodes.H" +#include "sbeHostUtils.H" +#include "sbeHostMsg.H" +#include "sbecmdiplcontrol.H" +#include "sberegaccess.H" +#include "sbestates.H" +#include "fapi2.H" + + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// +void sbeHandlePsuResponse (const uint32_t i_rc) +{ + #define SBE_FUNC " sbeHandlePsuResponse " + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + do + { + uint8_t l_cnt = 0; + switch (i_rc) + { + case SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED: + case SBE_SEC_COMMAND_NOT_SUPPORTED: + case SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE: + // Caller sent an invalid Command class/opcode + // Set the Ack bit in SBE->PSU DB register + l_rc = sbeAcknowledgeHost(); + if (SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + break; + } + // Set primary and secondary status + g_sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INVALID_COMMAND, i_rc); + + // Now Update SBE->PSU Mbx Reg4 with response + l_cnt = sizeof(g_sbeSbe2PsuRespHdr)/ + sizeof(uint64_t); + l_rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4, + reinterpret_cast( + &g_sbeSbe2PsuRespHdr), l_cnt, true); + break; + + case SBE_SEC_OS_FAILURE: + // Set primary and secondary status + g_sbeSbe2PsuRespHdr.setStatus(SBE_PRI_GENERIC_EXECUTION_FAILURE, + i_rc); + + // Now Update SBE->PSU Mbx Reg4 with response + l_cnt = sizeof(g_sbeSbe2PsuRespHdr)/ + sizeof(uint64_t); + l_rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4, + reinterpret_cast( + &g_sbeSbe2PsuRespHdr), l_cnt, true); + break; + + case SBE_SEC_OPERATION_SUCCESSFUL: + // Services code successfully executed the chipOp. + SBE_INFO(SBE_FUNC"PSU ChipOp Done"); + break; + + default: + // The only possibility (as of now) to reach till this point + // is when there was a mbx register access (scom) failure + // happened. Going to return to the waiting loop. + break; + } + } while(false); + + #undef SBE_FUNC +} + + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// +void sbeHandleFifoResponse (const uint32_t i_rc) +{ + #define SBE_FUNC " sbeHandleFifoResponse " + SBE_ENTER(SBE_FUNC); + + do + { + uint16_t l_primStatus = SBE_PRI_OPERATION_SUCCESSFUL; + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + // Handle FIFO reset case + if (i_rc == SBE_FIFO_RESET_RECEIVED) + { + break; + } + + if ( (i_rc == SBE_SEC_UNEXPECTED_EOT_INSUFFICIENT_DATA) || + (i_rc == SBE_SEC_UNEXPECTED_EOT_EXCESS_DATA) ) + { + l_primStatus = SBE_PRI_INVALID_DATA; + } + + uint32_t l_len2dequeue = 0; + uint32_t l_dist2StatusHdr = 0; + uint32_t l_sbeDownFifoRespBuf[4] = {0}; + uint32_t l_secStatus = i_rc; + + switch (i_rc) + { + case SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED: + case SBE_SEC_COMMAND_NOT_SUPPORTED: + case SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE: + // Caller sent Invalid Command + + case SBE_SEC_OS_FAILURE: + // PK API Failures + + // Flush out the upstream FIFO till EOT arrives + l_len2dequeue = 1; + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, NULL, + true, true); + + if ( (l_rc == SBE_FIFO_RESET_RECEIVED) || + (l_rc == SBE_SEC_FIFO_ACCESS_FAILURE) ) + { + break; + } + + if (l_rc) + { + l_secStatus = l_rc; + } + + // Don't break here to force the flow through + // the next case to enqueue the response into + // the downstream FIFO + + case SBE_SEC_UNEXPECTED_EOT_INSUFFICIENT_DATA: + case SBE_SEC_UNEXPECTED_EOT_EXCESS_DATA: + // EOT arrived prematurely in upstream FIFO + // or there were unexpected data in upstream FIFO + + SBE_ERROR(SBE_FUNC"Operation failure, " + "l_primStatus[0x%08X], " + "l_secStatus[0x%08X]", + l_primStatus, l_secStatus); + + sbeBuildMinRespHdr(&l_sbeDownFifoRespBuf[0], + l_dist2StatusHdr, + l_primStatus, + l_secStatus, + 0); + l_rc = sbeDownFifoEnq_mult (++l_dist2StatusHdr, + &l_sbeDownFifoRespBuf[0]); + if (l_rc) + { + SBE_ERROR(SBE_FUNC"sbeDownFifoEnq_mult failure," + " l_rc[0x0%08X]", l_rc); + // not attempting to signal EOT + break; + } + // Follow through to signal EOT in downstream + + case SBE_SEC_OPERATION_SUCCESSFUL: // Successful execution + // Signal EOT in Downstream FIFO + l_rc = sbeDownFifoSignalEot(); + if (l_rc) + { + SBE_ERROR(SBE_FUNC"sbeDownFifoSignalEot failure," + " l_rc[0x0%08X]", l_rc); + } + SBE_INFO(SBE_FUNC"ChipOp Done"); + break; + + default: + break; + } + } while (false); + + #undef SBE_FUNC +} + + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +void sbeSyncCommandProcessor_routine(void *i_pArg) +{ + #define SBE_FUNC " sbeSyncCommandProcessor_routine " + SBE_ENTER(SBE_FUNC); + + // Check the destination bit at the start + if(SbeRegAccess::theSbeRegAccess().isIstepMode()) + { + // In this state, we need not take care of FFDC State, User may + // or may not fetch FFDC and may not issue sbeContinueboot + SBE_INFO(SBE_FUNC"Continuous IPL mode not set, will wait for " + "commands..."); + (void)SbeRegAccess::theSbeRegAccess(). + updateSbeState(SBE_STATE_ISTEP); + } + // If Istep mode is not set, it makes sense to check if we are directly + // in runtime. + else if(true == SbeRegAccess::theSbeRegAccess().isDestBitRuntime()) + { + SBE_INFO(SBE_FUNC"Destination bit tells us to go to runtime"); + (void)SbeRegAccess::theSbeRegAccess(). + updateSbeState(SBE_STATE_RUNTIME); + } + // Now we can assume that we are in Continuous IPL mode, just check if + // FFDC needs to be collected before continuing with IPL + else if(true == SbeRegAccess::theSbeRegAccess().isCollectFFDCSet()) + { + SBE_INFO(SBE_FUNC"FFDC Collect State - Waiting for FFDC to be picked"); + (void)SbeRegAccess::theSbeRegAccess(). + updateSbeState(SBE_STATE_FFDC_COLLECT); + } + else + { + SBE_INFO(SBE_FUNC"Continuous IPL Mode set... IPLing"); + (void)SbeRegAccess::theSbeRegAccess(). + updateSbeState(SBE_STATE_IPLING); + sbeDoContinuousIpl(); + } + + do + { + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + // Wait for new command processing + int l_rcPk = pk_semaphore_pend ( + &g_sbeSemCmdProcess, PK_WAIT_FOREVER); + + do + { + // Local Variables + uint8_t l_cmdClass = 0; + uint8_t l_cmdOpCode = 0; + + // Reset the value of fapi2::current_err from previous value. + // This is required as none of procedure set this value in success + // case. So if we do not reset previous value, previous failure + // will impact new chipops also. + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // Check on the Rx Thread Interrupt Bits for Interrupt Status + if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, + SBE_INTERFACE_PSU) ) + { + l_rc = g_sbeSbe2PsuRespHdr.secStatus; + l_cmdClass = g_sbePsu2SbeCmdReqHdr.cmdClass; + l_cmdOpCode = g_sbePsu2SbeCmdReqHdr.command; + // Set this here, so that during response handling we know which + // interrupt we are processing, need not check for + // g_sbeIntrSource again + g_sbeIntrSource.setIntrSource(SBE_PROC_ROUTINE, + SBE_INTERFACE_PSU); + } + else if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, + SBE_INTERFACE_FIFO) ) + { + l_rc = g_sbeCmdRespHdr.sec_status; + l_cmdClass = g_sbeFifoCmdHdr.cmdClass; + l_cmdOpCode = g_sbeFifoCmdHdr.command; + // Set this here, so that during response handling we know which + // interrupt we are processing, need not check for + // g_sbeIntrSource again + g_sbeIntrSource.setIntrSource(SBE_PROC_ROUTINE, + SBE_INTERFACE_FIFO); + } + else // SBE_INTERFACE_FIFO_RESET or SBE_INTERFACE_UNKNOWN + { + SBE_ERROR(SBE_FUNC"Unexpected interrupt communicated to the " + "processor thread. Interrupt source: 0x%02X 0x%02X", + g_sbeIntrSource.intrSource, g_sbeIntrSource.rxThrIntrSource); + assert(false); + break; + } + + // PK API failure + if (l_rcPk != PK_OK) + { + SBE_ERROR(SBE_FUNC"pk_semaphore_pend failed, " + "l_rcPk=%d, g_sbeSemCmdRecv.count=%d", + l_rcPk, g_sbeSemCmdRecv.count); + + // If it's a semphore_pend error then update the same to show + // internal failure + l_rc = SBE_SEC_OS_FAILURE; + } + + // Check for error which Receiver thread might have set + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + break; + } + + // Get the command function + sbeCmdFunc_t l_pFuncP = sbeFindCmdFunc (l_cmdClass, l_cmdOpCode); + assert( l_pFuncP ) + + // Call the ChipOp function + l_rc = l_pFuncP ((uint8_t *)i_pArg); + + } while(false); // Inner do..while loop ends here + + SBE_INFO (SBE_FUNC"New cmd arrived, g_sbeSemCmdProcess.count=%d " + "l_rc=[0x%04X]", + g_sbeSemCmdProcess.count, l_rc); + + if ( g_sbeIntrSource.isSet(SBE_PROC_ROUTINE, SBE_INTERFACE_PSU) ) + { + sbeHandlePsuResponse (l_rc); + + // Enable Host interrupt + g_sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER,SBE_INTERFACE_PSU); + pk_irq_enable(SBE_IRQ_HOST_PSU_INTR); + } + else if ( g_sbeIntrSource.isSet(SBE_PROC_ROUTINE, SBE_INTERFACE_FIFO) ) + { + sbeHandleFifoResponse (l_rc); + + // Enable the new data available interrupt + g_sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER,SBE_INTERFACE_FIFO); + pk_irq_enable(SBE_IRQ_SBEFIFO_DATA); + pk_irq_enable(SBE_IRQ_SBEFIFO_RESET); + } + } while(true); // Thread always exists + SBE_EXIT(SBE_FUNC); +} + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +void sbeAsyncCommandProcessor_routine(void *arg) +{ + SBE_INFO("sbeAsyncCommandProcessor Thread started"); + + do + { + // @TODO RTC via : 130392 + // Add infrastructure for host interface + + } while(0); +} diff --git a/src/sbefw/sbecmdreceiver.C b/src/sbefw/sbecmdreceiver.C new file mode 100644 index 00000000..50f24657 --- /dev/null +++ b/src/sbefw/sbecmdreceiver.C @@ -0,0 +1,325 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdreceiver.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbecmdreceiver.C + * + * @brief This file contains the SBE Command Receiver Thread Routine + * + */ + + +#include "sbeexeintf.H" +#include "sbefifo.H" +#include "sbecmdparser.H" +#include "sbeirq.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "sbeFifoMsgUtils.H" +#include "sbeerrorcodes.H" +#include "sbeHostMsg.H" +#include "sbeHostUtils.H" +#include "sberegaccess.H" +#include "sbeutil.H" + +sbeFifoCmdReqBuf_t g_sbeFifoCmdHdr; +sbeCmdRespHdr_t g_sbeCmdRespHdr; +sbePsu2SbeCmdReqHdr_t g_sbePsu2SbeCmdReqHdr; +sbeSbe2PsuRespHdr_t g_sbeSbe2PsuRespHdr; +sbeIntrHandle_t g_sbeIntrSource; + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +void sbeCommandReceiver_routine(void *i_pArg) +{ + #define SBE_FUNC " sbeCommandReceiver_routine " + SBE_ENTER(SBE_FUNC); + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + // Update SBE msgg reg to indicate that control loop + // is ready now to receive data on its interfaces + (void)SbeRegAccess::theSbeRegAccess().setSbeReady(); + + // Set Current State to First State i.e. Unknown + (void)SbeRegAccess::theSbeRegAccess().updateSbeState(SBE_STATE_UNKNOWN); + + do + { + // @TODO via RTC: 128944 + // Read Scratchpad + // Wait for new data in FIFO or FIFO reset interrupt or PSU interrupt + int l_rcPk = pk_semaphore_pend (&g_sbeSemCmdRecv, PK_WAIT_FOREVER); + + do + { + uint8_t l_cmdClass = SBE_CMD_CLASS_UNKNOWN; + uint8_t l_command = 0xFF; + + // pk API failure + if (l_rcPk != PK_OK) + { + break; + } + + SBE_DEBUG(SBE_FUNC"Receiver unblocked"); + + // The responsibility of this thread is limited to reading off + // the FIFO or PSU interfaces to be able to decode the command + // class and the command opcode parameters. + + // Received FIFO Reset interrupt + if ( g_sbeIntrSource.isSet(SBE_INTERRUPT_ROUTINE, + SBE_INTERFACE_FIFO_RESET) ) + { + SBE_ERROR(SBE_FUNC"FIFO reset received"); + l_rc = SBE_FIFO_RESET_RECEIVED; + break; + } + + // Received PSU interrupt + if ( g_sbeIntrSource.isSet(SBE_INTERRUPT_ROUTINE, + SBE_INTERFACE_PSU) ) + { + //Clear the Interrupt Source bit for PSU + g_sbeIntrSource.clearIntrSource(SBE_INTERRUPT_ROUTINE, + SBE_INTERFACE_PSU); + g_sbeIntrSource.setIntrSource(SBE_RX_ROUTINE, + SBE_INTERFACE_PSU); + // First clear PSU->SBE DB bit 0 + l_rc = sbeClearPsu2SbeDbBitX(SBE_PSU2SBE_DOORBELL_CLEAR_BIT0); + if (l_rc) + { + break; + } + + // Initialize the g_sbePsu2SbeCmdReqHdr + g_sbePsu2SbeCmdReqHdr.init(); + // Read the request field from PSU->SBE Mbx Reg0 + uint8_t l_cnt = sizeof(g_sbePsu2SbeCmdReqHdr)/sizeof(uint64_t); + + l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG0, l_cnt, + (uint64_t *)&g_sbePsu2SbeCmdReqHdr); + + g_sbeSbe2PsuRespHdr.init(); + l_cmdClass = g_sbePsu2SbeCmdReqHdr.cmdClass; + l_command = g_sbePsu2SbeCmdReqHdr.command; + } // end if loop for PSU interface chipOp handling + + // Received FIFO New Data interrupt + else if ( g_sbeIntrSource.isSet(SBE_INTERRUPT_ROUTINE, + SBE_INTERFACE_FIFO) ) + { + //Clear the Interrupt Source bit for FIFO + g_sbeIntrSource.clearIntrSource(SBE_INTERRUPT_ROUTINE, + SBE_INTERFACE_FIFO); + g_sbeIntrSource.setIntrSource(SBE_RX_ROUTINE, + SBE_INTERFACE_FIFO); + + // This thread will attempt to unblock the command processor + // thread on the following scenarios: + // - Normal scenarios where SBE would need to respond to FSP + // via downstream FIFO. This includes SUCCESS cases as well + // as the cases for Invalid Data sequence or Command + // validation failure. + // - if there is a need to handle FIFO reset + + // Accordingly, this will update g_sbeCmdRespHdr.prim_status + // and g_sbeCmdRespHdr.sec_status for command processor thread + // to handle them later in the sequence. + + g_sbeFifoCmdHdr.cmdClass = SBE_CMD_CLASS_UNKNOWN; + g_sbeCmdRespHdr.init(); + uint32_t len = sizeof(g_sbeFifoCmdHdr)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult ( len, (uint32_t *)&g_sbeFifoCmdHdr, + false ); + + // If FIFO reset is requested, + if (l_rc == SBE_FIFO_RESET_RECEIVED) + { + SBE_ERROR(SBE_FUNC"FIFO reset received"); + break; + } + + // If we received EOT out-of-sequence + if ( (l_rc == SBE_SEC_UNEXPECTED_EOT_INSUFFICIENT_DATA) || + (l_rc == SBE_SEC_UNEXPECTED_EOT_EXCESS_DATA) ) + { + SBE_ERROR(SBE_FUNC"sbeUpFifoDeq_mult failure, " + " l_rc=[0x%08X]", l_rc); + g_sbeCmdRespHdr.setStatus(SBE_PRI_INVALID_DATA, l_rc); + + // Reassign l_rc to Success to Unblock command processor + // thread and let that take the necessary action. + l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + break; + } + + l_cmdClass = g_sbeFifoCmdHdr.cmdClass; + l_command = g_sbeFifoCmdHdr.command; + } // end else if loop for FIFO interface chipOp handling + + // Any other FIFO access issue + if ( l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + break; + } + + // validate the command class and sub-class opcodes + l_rc = sbeValidateCmdClass (l_cmdClass, l_command) ; + + if (l_rc) + { + // Command Validation failed; + SBE_ERROR(SBE_FUNC"Command validation failed"); + if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, + SBE_INTERFACE_PSU) ) + { + g_sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INVALID_COMMAND,l_rc); + } + else if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, + SBE_INTERFACE_FIFO) ) + { + g_sbeCmdRespHdr.setStatus(SBE_PRI_INVALID_COMMAND, l_rc); + } + + // Reassign l_rc to Success to Unblock command processor + // thread and let that take the necessary action. + l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + break; + } + + // Need to return from receiver thread itself for fenced rejection + // of command, but there might be contention on the response sent + // over FIFO/Mailbox usage. + if(false == sbeIsCmdAllowedAtState(l_cmdClass, l_command)) + { + // This command is not allowed in this state + SBE_ERROR("Chip-Op CmdClass[0x%02X] Cmd[0x%02X] not allowed in " + "State - [0x%04X] ",l_cmdClass,l_command, + SbeRegAccess::theSbeRegAccess().getSbeState()); + + if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, SBE_INTERFACE_PSU) ) + { + g_sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INVALID_COMMAND, + SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE); + } + else if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, + SBE_INTERFACE_FIFO) ) + { + g_sbeCmdRespHdr.setStatus(SBE_PRI_INVALID_COMMAND, + SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE); + } + + l_rc = SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE; + break; + } + + } while (false); // Inner do..while ends + + // If there was a FIFO reset request, + if (l_rc == SBE_FIFO_RESET_RECEIVED) + { + // Perform FIFO Reset + uint32_t l_rc = sbeUpFifoPerformReset(); + if (l_rc) + { + // Perform FIFO Reset failed + SBE_ERROR(SBE_FUNC"Perform FIFO Reset failed, " + "l_rc=[0x%08X]", l_rc); + // Collect FFDC? + } + + if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, SBE_INTERFACE_FIFO) ) + { + g_sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER, + SBE_INTERFACE_FIFO); + } + + if ( g_sbeIntrSource.isSet(SBE_INTERRUPT_ROUTINE, + SBE_INTERFACE_FIFO_RESET) ) + { + g_sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER, + SBE_INTERFACE_FIFO_RESET); + } + + pk_irq_enable(SBE_IRQ_SBEFIFO_DATA); + pk_irq_enable(SBE_IRQ_SBEFIFO_RESET); + continue; + } // FIFO reset handling ends + + // Unblock the command processor thread + // if we could dequeue the header successfully, + if ((l_rcPk == PK_OK) && (l_rc == SBE_SEC_OPERATION_SUCCESSFUL)) + { + l_rcPk = pk_semaphore_post(&g_sbeSemCmdProcess); + } + + // Handle Cmd not in a valid state here + + if ((l_rcPk != PK_OK) || (l_rc != SBE_SEC_OPERATION_SUCCESSFUL)) + { + if(l_rc != SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE) + { + // It's likely a code bug or PK failure, + // or any other PSU/FIFO access (scom) failure. + + // @TODO via RTC : 129166 + // Review if we need to add ASSERT here + + // Add Error trace, collect FFDC and + // continue wait for the next interrupt + SBE_ERROR(SBE_FUNC"Unexpected failure, " + "l_rcPk=[%d], g_sbeSemCmdProcess.count=[%d], l_rc=[%d]", + l_rcPk, g_sbeSemCmdProcess.count, l_rc); + } + if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, + SBE_INTERFACE_PSU) ) + { + if(l_rc == SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE) + { + sbeHandlePsuResponse(l_rc); + } + g_sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER, + SBE_INTERFACE_PSU); + pk_irq_enable(SBE_IRQ_HOST_PSU_INTR); + } + else if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, + SBE_INTERFACE_FIFO) ) + { + if(l_rc == SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE) + { + sbeHandleFifoResponse(l_rc); + } + g_sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER, + SBE_INTERFACE_FIFO); + pk_irq_enable(SBE_IRQ_SBEFIFO_DATA); + } + continue; + } + + SBE_DEBUG(SBE_FUNC"Posted g_sbeSemCmdProcess, " + "g_sbeSemCmdProcess.count=[%d]", g_sbeSemCmdProcess.count); + + } while (true); // thread always exists + #undef SBE_FUNC +} diff --git a/src/sbefw/sbecmdregaccess.C b/src/sbefw/sbecmdregaccess.C new file mode 100644 index 00000000..d4023f73 --- /dev/null +++ b/src/sbefw/sbecmdregaccess.C @@ -0,0 +1,274 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdregaccess.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbecmdregaccess.C + * + * @brief This file contains the SBE Reg Access chipOps + * + */ + +#include "sbecmdregaccess.H" +#include "sbefifo.H" +#include "sbe_sp_intf.H" +#include "sbetrace.H" +#include "sbeFifoMsgUtils.H" +#include "p9_ram_core.H" + +using namespace fapi2; + +Enum_RegType getRegType( const sbeRegAccessMsgHdr_t ®Req) +{ + Enum_RegType type = REG_GPR; + switch( regReq.regType ) + { + case SBE_REG_ACCESS_SPR: + type = REG_SPR; + break; + + case SBE_REG_ACCESS_FPR: + type = REG_FPR; + break; + } + return type; +} + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeGetReg(uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeGetReg " + SBE_ENTER(SBE_FUNC); + + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbeRegAccessMsgHdr_t regReqMsg; + uint32_t reqData[SBE_MAX_REG_ACCESS_REGS]; + sbeRespGenHdr_t respHdr; + respHdr.init(); + sbeResponseFfdc_t ffdc; + ReturnCode fapiRc; + + do + { + // Get the reg access header + uint32_t len = sizeof(sbeRegAccessMsgHdr_t)/sizeof(uint32_t); + rc = sbeUpFifoDeq_mult (len, (uint32_t *)®ReqMsg, false); + + // If FIFO access failure + if (rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // Let command processor routine to handle the RC. + break; + } + if( false == regReqMsg.isValidRequest() ) + { + SBE_ERROR(SBE_FUNC" Invalid request. core: 0x%02x threadNr:0x%x" + " regType:0x%01x numRegs:0x%02x", regReqMsg.coreChiplet, + regReqMsg.threadNr, regReqMsg.regType, regReqMsg.numRegs); + + respHdr.setStatus( SBE_PRI_INVALID_DATA, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + break; + } + + len = regReqMsg.numRegs; + rc = sbeUpFifoDeq_mult (len, reqData, true); + if (rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + break; + } + uint8_t core = regReqMsg.coreChiplet; + RamCore ramCore( plat_getTargetHandleByChipletNumber + (core), + regReqMsg.threadNr ); + + fapiRc = ramCore.ram_setup(); + if( fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" ram_setup failed. threadNr:0x%x" + "chipletId:0x%02x", regReqMsg.threadNr, core); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + ffdc.setRc(fapiRc); + break; + } + + fapi2::buffer data64; + uint64_t respData = 0; + for( uint32_t regIdx = 0; regIdx < regReqMsg.numRegs; regIdx++ ) + { + fapiRc = ramCore.get_reg( getRegType(regReqMsg), reqData[regIdx], + &data64, true ); + if( fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" get_reg failed. threadNr:0x%x" + "chipletId:0x%02x, regNr:%u regType:%u ", + regReqMsg.threadNr, core, reqData[regIdx], + regReqMsg.regType); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + ffdc.setRc(fapiRc); + break; + } + respData = data64; + // Now enqueue into the downstream FIFO + len = sizeof( respData )/sizeof(uint32_t); + rc = sbeDownFifoEnq_mult (len, ( uint32_t *)&respData); + if (rc) + { + break; + } + } + // HWP team does not care about cleanup for failure case. + // So call cleaup only for success case. + if( ffdc.getRc() ) + { + break; + } + fapiRc = ramCore.ram_cleanup(); + if( fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" ram_cleanup failed. threadNr:0x%x" + "chipletId:0x%02x", regReqMsg.threadNr, core); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + ffdc.setRc(fapiRc); + } + }while(false); + + if ( SBE_SEC_OPERATION_SUCCESSFUL == rc ) + { + rc = sbeDsSendRespHdr( respHdr, ffdc); + } + + SBE_EXIT(SBE_FUNC); + return rc; + #undef SBE_FUNC +} +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbePutReg(uint8_t *i_pArg) +{ + #define SBE_FUNC " sbePutReg " + SBE_ENTER(SBE_FUNC); + + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbeRegAccessMsgHdr_t regReqMsg; + sbeRespGenHdr_t respHdr; + respHdr.init(); + sbeResponseFfdc_t ffdc; + ReturnCode fapiRc; + + do + { + // Get the reg access header + uint32_t len = sizeof(sbeRegAccessMsgHdr_t)/sizeof(uint32_t); + rc = sbeUpFifoDeq_mult (len, (uint32_t *)®ReqMsg, false); + + // If FIFO access failure + if (rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // Let command processor routine to handle the RC. + break; + } + if( false == regReqMsg.isValidRequest() ) + { + SBE_ERROR(SBE_FUNC" Invalid request. threadNr:0x%x" + " regType:0x%02x numRegs:0x%02x", regReqMsg.threadNr, + regReqMsg.regType, regReqMsg.numRegs); + respHdr.setStatus( SBE_PRI_INVALID_DATA, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + break; + } + + sbeRegAccessPackage_t regPkg[SBE_MAX_REG_ACCESS_REGS]; + len = (sizeof(sbeRegAccessPackage_t)/sizeof(uint32_t)) * + regReqMsg.numRegs; + rc = sbeUpFifoDeq_mult (len, (uint32_t *) regPkg,true ); + if (rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + break; + } + uint8_t core = regReqMsg.coreChiplet; + RamCore ramCore( plat_getTargetHandleByChipletNumber + (core), + regReqMsg.threadNr ); + + fapiRc = ramCore.ram_setup(); + if( fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" ram_setup failed. threadNr:0x%x" + "chipletId:0x%02x", regReqMsg.threadNr, core); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + ffdc.setRc(fapiRc); + break; + } + + fapi2::buffer data64; + for( uint32_t regIdx = 0; regIdx < regReqMsg.numRegs; regIdx++ ) + { + data64 = regPkg[regIdx].getData(); + fapiRc = ramCore.put_reg( getRegType(regReqMsg), + regPkg[regIdx].regNr, + &data64, true ); + if( fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" get_reg failed. threadNr:0x%x" + "chipletId:0x%02x, regNr:%u regType:%u ", + regReqMsg.threadNr, core, regPkg[regIdx].regNr, + regReqMsg.regType); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + ffdc.setRc(fapiRc); + break; + } + } + // HWP team does not care about cleanup for failure case. + // So call cleaup only for success case. + if( ffdc.getRc() ) + { + break; + } + fapiRc = ramCore.ram_cleanup(); + if( fapiRc ) + { + SBE_ERROR(SBE_FUNC" ram_cleanup failed. threadNr:0x%x" + " chipletId:0x%02x", regReqMsg.threadNr, core); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + ffdc.setRc(fapiRc); + } + + }while(false); + + if ( SBE_SEC_OPERATION_SUCCESSFUL == rc ) + { + rc = sbeDsSendRespHdr( respHdr, ffdc); + } + + SBE_EXIT(SBE_FUNC); + return rc; + #undef SBE_FUNC +} + diff --git a/src/sbefw/sbecmdregaccess.H b/src/sbefw/sbecmdregaccess.H new file mode 100644 index 00000000..01199816 --- /dev/null +++ b/src/sbefw/sbecmdregaccess.H @@ -0,0 +1,56 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdregaccess.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbecmdregaccess.H + * + * @brief This file contains the Interfaces for the SCOM Access chip-ops + * + */ + +#ifndef __SBEFW_SBECMDREGACCESS_H +#define __SBEFW_SBECMDREGACCESS_H + +#include + +/** + * @brief sbeGetRegs : Get the reg data + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetReg(uint8_t *i_pArg); + + +/** + * @brief sbePutRegs : Put the reg data + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbePutReg(uint8_t *i_pArg); + + +#endif /* __SBEFW_SBECMDREGACCESS_H */ diff --git a/src/sbefw/sbecmdringaccess.C b/src/sbefw/sbecmdringaccess.C new file mode 100644 index 00000000..3fdc8f7e --- /dev/null +++ b/src/sbefw/sbecmdringaccess.C @@ -0,0 +1,305 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdringaccess.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 "fapi2.H" +#include "plat_hw_access.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; + +/*@brief - Map sbe ring access modes to fapi ring access modes + * + * @param[in] - i_ringMode - sbe ring access mode + * + * @return - l_fapiRingMode - fapi ring mode + */ +uint16_t sbeToFapiRingMode(uint16_t i_ringMode) +{ + uint16_t l_fapiRingMode = RING_MODE_HEADER_CHECK; + + if(i_ringMode & SBE_RING_MODE_SET_PULSE_NO_OPCG_COND) + { + l_fapiRingMode |= RING_MODE_SET_PULSE_NO_OPCG_COND; + } + if(i_ringMode & SBE_RING_MODE_NO_HEADER_CHECK) + { + l_fapiRingMode |= RING_MODE_NO_HEADER_CHECK; + } + if(i_ringMode & SBE_RING_MODE_SET_PULSE_NSL) + { + l_fapiRingMode |= RING_MODE_SET_PULSE_NSL; + } + if(i_ringMode & SBE_RING_MODE_SET_PULSE_SL) + { + l_fapiRingMode |= RING_MODE_SET_PULSE_SL; + } + if(i_ringMode & SBE_RING_MODE_SET_PULSE_ALL) + { + l_fapiRingMode |= RING_MODE_SET_PULSE_ALL; + } + return l_fapiRingMode; +} + +/*@brief - create fapi target handle for the target type + * + * @param[in] - i_taretType - sbe ring target type + * @param[in] - i_chipletId - chiplet id + * @param[out] - o_tgtHndl - fapi target handle + * + * @return - true - on success + * false - on failure + */ +bool sbeGetFapiTargetHandle(uint16_t i_targetType, + uint16_t i_chipletId, + fapi2::plat_target_handle_t &o_tgtHndl) +{ + bool l_rc = true; + o_tgtHndl = NULL; + switch(i_targetType) + { + case TARGET_EX: + o_tgtHndl = plat_getTargetHandleByChipletNumber + (i_chipletId); + break; + case TARGET_PERV: + o_tgtHndl = plat_getTargetHandleByChipletNumber + (i_chipletId); + break; + case TARGET_PROC_CHIP: + o_tgtHndl = plat_getChipTarget().get(); + break; + default: + l_rc = false; + break; + } + return l_rc; +} + +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 = {0}; + if(!sbeGetFapiTargetHandle(l_cmd.TargetType, l_cmd.ChipletID, + l_tgtHndl)) + { + SBE_ERROR(SBE_FUNC "Invalid target type [0x%04x]", + (uint16_t)l_cmd.TargetType); + g_sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INVALID_DATA, + SBE_SEC_INVALID_TARGET_TYPE_PASSED); + break; + } + fapi2::Target 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(g_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; + uint32_t l_bitSentCnt = 0; + + 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", + l_reqMsg.ringAddr, l_reqMsg.ringMode, 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; + + // Fetch the ring data in bits, each iteration will give you 64bits + for(uint32_t l_cnt=0; l_cnt < l_loopCnt; l_cnt++) + { + if((l_cnt == (l_loopCnt-1)) && (l_mod)) + { + l_bitShift = l_mod; + } + else + { + l_bitShift = GETRING_GRANULE_SIZE_IN_BITS; + } + // Call getRing_granule_data - read the 64 bit data from the HW + l_fapiRc = getRing_granule_data((uint32_t)(l_reqMsg.ringAddr), + (uint64_t*)&l_buf, + l_bitShift); + 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; + } + + // 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; + } + if ( (l_fapiRc == FAPI2_RC_SUCCESS) && + (l_rc == SBE_SEC_OPERATION_SUCCESSFUL) ) + { + // 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 +} + diff --git a/src/sbefw/sbecmdringaccess.H b/src/sbefw/sbecmdringaccess.H new file mode 100644 index 00000000..d2163646 --- /dev/null +++ b/src/sbefw/sbecmdringaccess.H @@ -0,0 +1,63 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdringaccess.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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.H + * + * @brief This file contains the Interfaces for the RING Access chip-ops + * + */ + +#ifndef __SBEFW_SBECMDRINGACCESS_H +#define __SBEFW_SBECMDRINGACCESS_H + +#include + +typedef struct +{ + uint64_t TargetType:16; + uint64_t ChipletID:16; + uint64_t RingID:16; + uint64_t RingMode:16; +} sbePSUPutRingCMD_t; + +/** + * @brief Put Ring From Image Command (0xD301) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return RC from the PSU access utility + */ +uint32_t sbePutRingFromImagePSU(uint8_t *i_pArg); + +/** + * @brief sbeGetRing : Get the ring data + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetRing(uint8_t *i_pArg); + + +#endif /* __SBEFW_SBECMDRINGACCESS_H */ diff --git a/src/sbefw/sbecmdscomaccess.C b/src/sbefw/sbecmdscomaccess.C new file mode 100644 index 00000000..e99ce89f --- /dev/null +++ b/src/sbefw/sbecmdscomaccess.C @@ -0,0 +1,495 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdscomaccess.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbecmdscomaccess.C + * + * @brief This file contains the SBE SCOM Access chipOps + * + */ + +#include "sbecmdscomaccess.H" +#include "sbefifo.H" +#include "sbe_sp_intf.H" +#include "sbetrace.H" +#include "sbescom.H" +#include "sbeutil.H" +#include "sbeFifoMsgUtils.H" + + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeGetScom (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeGetScom " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbeGetScomReqMsg_t l_getScomReqMsg; + + do + { + uint16_t l_primStatus = g_sbeCmdRespHdr.prim_status; + uint16_t l_secStatus = g_sbeCmdRespHdr.sec_status ; + + // Will attempt to dequeue two entries for + // the scom addresses plus the expected + // EOT entry at the end + + uint32_t l_len2dequeue = sizeof(l_getScomReqMsg)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, (uint32_t *)&l_getScomReqMsg); + + // If FIFO access failure + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // Let command processor routine to handle the RC. + break; + } + + uint32_t l_sbeDownFifoRespBuf[6] = {0}; + uint32_t l_pcbpibStatus = SBE_PCB_PIB_ERROR_NONE; + uint32_t l_len2enqueue = 0; + uint32_t l_index = 0; + + uint64_t l_addr = ( (uint64_t)l_getScomReqMsg.hiAddr << 32) | + l_getScomReqMsg.lowAddr; + uint64_t l_scomData = 0; + SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]", + l_getScomReqMsg.hiAddr, l_getScomReqMsg.lowAddr); + l_rc = checkIndirectAndDoScom(true, l_addr, + l_scomData, l_pcbpibStatus); + + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed + { + SBE_ERROR(SBE_FUNC"getscom failed, l_pcbpibStatus[0x%08X], " + "scomAddr[0x%08X%08X]", l_pcbpibStatus, + l_getScomReqMsg.hiAddr, l_getScomReqMsg.lowAddr); + l_primStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE; + l_secStatus = l_rc; + } + else // successful scom + { + SBE_DEBUG(SBE_FUNC"getscom succeeds, l_scomData[0x%016X]", + l_scomData); + + l_sbeDownFifoRespBuf[0] = (uint32_t)(l_scomData>>32); + l_sbeDownFifoRespBuf[1] = (uint32_t)(l_scomData); + + // Push the data into downstream FIFO + l_len2enqueue = 2; + l_rc = sbeDownFifoEnq_mult (l_len2enqueue, + &l_sbeDownFifoRespBuf[0]); + if (l_rc) + { + // will let command processor routine + // handle the failure + break; + } + l_index = 2; + } // end successful scom + + // Build the response header packet + + uint32_t l_curIndex = l_index ; + sbeBuildMinRespHdr(&l_sbeDownFifoRespBuf[0], + l_curIndex, + l_primStatus, + l_secStatus, + l_pcbpibStatus, + l_index); + + // Now enqueue into the downstream FIFO + l_len2enqueue = ++l_curIndex - l_index; + l_rc = sbeDownFifoEnq_mult (l_len2enqueue, + &l_sbeDownFifoRespBuf[l_index]); + if (l_rc) + { + // will let command processor routine + // handle the failure + break; + } + + } while(false); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + +///////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbePutScom (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbePutScom " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbePutScomReqMsg_t l_putScomReqMsg; + + do + { + uint16_t l_primStatus = g_sbeCmdRespHdr.prim_status; + uint16_t l_secStatus = g_sbeCmdRespHdr.sec_status ; + + // Will attempt to dequeue four entries for + // the scom address (two entries) and the + // corresponding data (two entries) plus + // the expected EOT entry at the end + + uint32_t l_len2dequeue = sizeof(l_putScomReqMsg)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, (uint32_t *)&l_putScomReqMsg); + + // If FIFO access failure + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // Let command processor routine to handle the RC. + break; + } + + uint64_t l_scomData = 0; + uint32_t l_sbeDownFifoRespBuf[4] = {0}; + uint32_t l_pcbpibStatus = SBE_PCB_PIB_ERROR_NONE; + uint32_t l_len2enqueue = 0; + // successfully dequeued two entries for + // scom address followed by the EOT entry + + // Data entry 0 : Scom Register Address (0..31) + // Data entry 1 : Scom Register Address (32..63) + // Data entry 2 : Scom Register Data (0..31) + // Data entry 3 : Scom Register Data (32..63) + // For Direct SCOM, will ignore entry 0 + + l_scomData = l_putScomReqMsg.getScomData(); + + uint64_t l_addr = ( (uint64_t) l_putScomReqMsg.hiAddr << 32) | + l_putScomReqMsg.lowAddr; + SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]", + l_putScomReqMsg.hiAddr, l_putScomReqMsg.lowAddr); + l_rc = checkIndirectAndDoScom(false, l_addr, + l_scomData, l_pcbpibStatus); + + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed + { + SBE_ERROR(SBE_FUNC"putscom failed, l_pcbpibStatus[0x%08X]", + l_pcbpibStatus); + SBE_ERROR(SBE_FUNC"putscom failure data, " + "scomAddr[0x%08X%08X], " + "scomData[0x%08X%08X]", + l_putScomReqMsg.hiAddr, + l_putScomReqMsg.lowAddr, + SBE::higher32BWord(l_scomData), + SBE::lower32BWord(l_scomData)); + l_primStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE; + l_secStatus = l_rc; + } + + // Build the response header packet + + uint32_t l_curIndex = 0; + sbeBuildMinRespHdr(&l_sbeDownFifoRespBuf[0], + l_curIndex, + l_primStatus, + l_secStatus, + l_pcbpibStatus); + + // Now enqueue into the downstream FIFO + l_len2enqueue = ++l_curIndex; + l_rc = sbeDownFifoEnq_mult (l_len2enqueue, &l_sbeDownFifoRespBuf[0]); + if (l_rc) + { + // will let command processor routine + // handle the failure + break; + } + + } while(false); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeModifyScom (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeModifyScom " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + sbeModifyScomReqMsg_t l_modifyScomMsg; + + do + { + uint16_t l_primStatus = g_sbeCmdRespHdr.prim_status; + uint16_t l_secStatus = g_sbeCmdRespHdr.sec_status ; + + // Will attempt to dequeue the following entries: + // Entry 1 : Operation Mode + // Entry 2 : Scom Register Address (0..31) + // Entry 3 : Scom Register Address (32..63) + // Entry 4 : Modifying Data (0..31) + // Entry 5 : Modifying Data (32..63) + // Entry 6 : EOT entry at the end + + uint32_t l_len2dequeue = sizeof(l_modifyScomMsg)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, (uint32_t *)&l_modifyScomMsg); + + // If FIFO access failure + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // Let command processor routine to handle the RC. + break; + } + + uint32_t l_sbeDownFifoRespBuf[4] = {0}; + uint32_t l_pcbpibStatus = SBE_PCB_PIB_ERROR_NONE; + uint32_t l_len2enqueue = 0; + + // Modifying Data + uint64_t l_modifyingData = l_modifyScomMsg.getModifyingData(); + + SBE_DEBUG(SBE_FUNC"OpMode[0x%02X], modifyingData[0x%016X]", + l_modifyScomMsg.opMode, + SBE::higher32BWord(l_modifyingData), + SBE::lower32BWord(l_modifyingData)); + + // The following steps need to be done as part of this command : + // 1. Read Register Data (getscom) + // 2. 'AND' the Mask with the data read from register + // 3. 'OR' the modifying data with the result of step 2 + // 4. Write the result of step 3 into the register (putscom) + do + { + // Check for a valid OpMode + if ( (l_modifyScomMsg.opMode != SBE_MODIFY_MODE_OR) && + (l_modifyScomMsg.opMode != SBE_MODIFY_MODE_AND) && + (l_modifyScomMsg.opMode != SBE_MODIFY_MODE_XOR) ) + { + // Invalid Data passed + SBE_ERROR(SBE_FUNC"Invalid OpMode"); + l_primStatus = SBE_PRI_INVALID_DATA; + l_secStatus = SBE_SEC_GENERIC_FAILURE_IN_EXECUTION; + break; + } + + uint64_t l_addr = ( (uint64_t) l_modifyScomMsg.hiAddr << 32) | + l_modifyScomMsg.lowAddr; + uint64_t l_scomData = 0; + SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]", + l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr); + l_rc = checkIndirectAndDoScom(true, l_addr, + l_scomData, l_pcbpibStatus); + + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed + { + SBE_ERROR(SBE_FUNC"getscom failed, l_pcbpibStatus[0x%08X]," + " ScomAddress[0x%08X %08X]", l_pcbpibStatus, + l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr); + l_primStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE; + l_secStatus = l_rc; + break; + } + + if (l_modifyScomMsg.opMode == SBE_MODIFY_MODE_OR) + { + l_modifyingData |= l_scomData; + } + else if (l_modifyScomMsg.opMode == SBE_MODIFY_MODE_AND) + { + l_modifyingData &= l_scomData; + } + else + { + l_modifyingData ^= l_scomData; + } + + // Write the modified data + l_rc = checkIndirectAndDoScom(false, l_addr, + l_modifyingData, l_pcbpibStatus); + + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed + { + SBE_ERROR(SBE_FUNC"putscom failed, l_pcbpibStatus[0x%08X]," + " ScomAddress[0x%08X%08X]", l_pcbpibStatus, + l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr); + SBE_ERROR(SBE_FUNC"modifyingData[0x%08X%08X]", + SBE::higher32BWord(l_modifyingData), + SBE::lower32BWord(l_modifyingData)); + l_primStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE; + l_secStatus = l_rc; + break; + } + } while (false); + + // Build the response header packet + + uint32_t l_curIndex = 0; + sbeBuildMinRespHdr(&l_sbeDownFifoRespBuf[0], + l_curIndex, + l_primStatus, + l_secStatus, + l_pcbpibStatus); + + // Now enqueue into the downstream FIFO + l_len2enqueue = ++l_curIndex; + l_rc = sbeDownFifoEnq_mult (l_len2enqueue, + (uint32_t *)&l_sbeDownFifoRespBuf); + if (l_rc) + { + // will let command processor routine + // handle the failure + break; + } + + } while(false); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + +///////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbePutScomUnderMask (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbePutScomUnderMask " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbePutScomUnderMaskReqMsg_t l_putScomUmaskMsg; + + do + { + uint16_t l_primStatus = g_sbeCmdRespHdr.prim_status; + uint16_t l_secStatus = g_sbeCmdRespHdr.sec_status ; + + // Will attempt to dequeue the following entries: + // Entry 1 : Scom Register Address (0..31) + // Entry 2 : Scom Register Address (32..63) + // Entry 3 : Modifying Data (0..31) + // Entry 4 : Modifying Data (32..63) + // Entry 5 : Mask Data (0..31) + // Entry 6 : Mask Data (32..63) + // Entry 7 : EOT entry at the end + + uint32_t l_len2dequeue = sizeof(l_putScomUmaskMsg)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, + (uint32_t *)&l_putScomUmaskMsg); + + // If FIFO access failure + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // Let command processor routine to handle the RC. + break; + } + + uint32_t l_sbeDownFifoRespBuf[4] = {0}; + uint32_t l_pcbpibStatus = SBE_PCB_PIB_ERROR_NONE; + uint32_t l_len2enqueue = 0; + + SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]," + "modifyingData[0x%08X%08X]", + l_putScomUmaskMsg.hiAddr, + l_putScomUmaskMsg.lowAddr, + l_putScomUmaskMsg.hiInputData, + l_putScomUmaskMsg.lowInputData); + SBE_INFO(SBE_FUNC"maskData[0x%08X%08X]", + l_putScomUmaskMsg.hiMaskData, + l_putScomUmaskMsg.lowMaskData); + + // PutScomUnderMask formula: + // dest_reg = (dest_reg & ~input_mask) | (input_data & input_mask) + + do + { + uint64_t l_scomData = 0; + + uint64_t l_addr = ( (uint64_t) l_putScomUmaskMsg.hiAddr << 32) | + l_putScomUmaskMsg.lowAddr; + l_rc = checkIndirectAndDoScom(true, l_addr, + l_scomData, l_pcbpibStatus); + + if (l_rc == SBE_SEC_OPERATION_SUCCESSFUL) // scom success + { + l_putScomUmaskMsg.getScomData(l_scomData); + + // Write the modified data + l_rc = checkIndirectAndDoScom(false, l_addr, + l_scomData, l_pcbpibStatus); + } + + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed + { + SBE_ERROR(SBE_FUNC"scom failed, l_pcbpibStatus[0x%08X], " + "ScomAddress[0x%08X%08X]", l_pcbpibStatus, + l_putScomUmaskMsg.hiAddr, + l_putScomUmaskMsg.lowAddr); + SBE_ERROR(SBE_FUNC"modifyingData[0x%08X%08X]" + "maskData[0x%08X%08X]", + l_putScomUmaskMsg.hiInputData, + l_putScomUmaskMsg.lowInputData, + l_putScomUmaskMsg.hiMaskData, + l_putScomUmaskMsg.lowMaskData); + + l_primStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE; + l_secStatus = l_rc; + break; + } + } while (false); + + // Build the response header packet + uint32_t l_curIndex = 0; + sbeBuildMinRespHdr(&l_sbeDownFifoRespBuf[0], + l_curIndex, + l_primStatus, + l_secStatus, + l_pcbpibStatus); + + // Now enqueue into the downstream FIFO + l_len2enqueue = ++l_curIndex; + l_rc = sbeDownFifoEnq_mult (l_len2enqueue, &l_sbeDownFifoRespBuf[0]); + if (l_rc) + { + // will let command processor routine + // handle the failure + break; + } + } while(false); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + +///////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeMultiScom (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeMultiScom " + return 0; + #undef SBE_FUNC +} + diff --git a/src/sbefw/sbecmdscomaccess.H b/src/sbefw/sbecmdscomaccess.H new file mode 100644 index 00000000..8a4a4a28 --- /dev/null +++ b/src/sbefw/sbecmdscomaccess.H @@ -0,0 +1,93 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdscomaccess.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbecmdscomaccess.H + * + * @brief This file contains the Interfaces for the SCOM Access chip-ops + * + */ + +#ifndef __SBEFW_SBECMDSCOMACCESS_H +#define __SBEFW_SBECMDSCOMACCESS_H + +#include + +/** + * @brief sbeDownFifoGetStatus : Write data into Downstream FIFO + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetScom (uint8_t *i_pArg); + + +/** + * @brief sbeDownFifoGetStatus : Write data into Downstream FIFO + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbePutScom (uint8_t *i_pArg); + + +/** + * @brief sbeModifyScom : Modify the Scom data + * This chipOp needs to do the following + * 1. Read Register Data (getscom) + * 2. modify the scomData using the given op mode + * 3. Write the modified Data into the Register (putscom) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeModifyScom (uint8_t *i_pArg); + + +/** + * @brief sbePutScomUnderMask : Write data into Downstream FIFO + * The following steps need to be done as part of this command : + * 1. Read Register Data (getscom) + * 2. 'AND' the Mask with the data read from register + * 3. 'OR' the modifying data with the result of step 2 + * 4. Write the result of step 3 into the register (putscom) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbePutScomUnderMask (uint8_t *i_pArg); + +/** + * @brief sbeMultiScom: + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeMultiScom (uint8_t *i_pArg); + +#endif /* __SBEFW_SBECMDSCOMACCESS_H */ diff --git a/src/sbefw/sbecmdsram.C b/src/sbefw/sbecmdsram.C new file mode 100644 index 00000000..ac11ffc6 --- /dev/null +++ b/src/sbefw/sbecmdsram.C @@ -0,0 +1,337 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdsram.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbecmdsram.C + * + * @brief This file contains the SBE Sram Access chipOps + * + */ + +#include "sbecmdsram.H" +#include "sbefifo.H" +#include "sbe_sp_intf.H" +#include "sbetrace.H" +#include "sbeFifoMsgUtils.H" +#include "sberegaccess.H" + +#include "fapi2.H" +#include "p9_pm_ocb_init.H" +#include "p9_pm_ocb_indir_setup_linear.H" +#include "p9_pm_ocb_indir_access.H" +#include "p9_perv_scom_addresses.H" + +using namespace fapi2; + + +/////////////////////////////////////////////////////////////////////// +// @brief sbeOccSramAccess_Wrap Occ Sran Access Wrapper function +// +// @param [in] i_isGetFlag Flag to indicate the sram Access Type +// true : GetOccSram ChipOp +// false : PutOccSram ChipOp +// +// @return RC from the underlying FIFO utility +/////////////////////////////////////////////////////////////////////// +uint32_t sbeOccSramAccess_Wrap(const bool i_isGetFlag) +{ + #define SBE_FUNC " sbeOccSramAccess_Wrap " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + ReturnCode l_fapiRc = FAPI2_RC_SUCCESS; + + sbeRespGenHdrWithLen_t l_respHdr; + l_respHdr.init(); + sbeResponseFfdc_t l_ffdc; + + // Total Returned length from the procedure + uint32_t l_totalReturnLen = 0; + + // Create the req struct for the OCC Sram Chip-op + sbeOccSramAccessReqMsgHdr_t l_req = {0}; + + // Check if True - Get / False - Put + p9ocb::PM_OCB_ACCESS_OP l_ocb_access = + (i_isGetFlag)? p9ocb::OCB_GET : p9ocb::OCB_PUT; + + do + { + // Get the Req Struct Size Data from upstream Fifo + uint32_t l_len2dequeue = sizeof(l_req) / sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, + (uint32_t *)&l_req, + i_isGetFlag); + + // If FIFO failure + if (SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + // Let command processor routine to handle the RC. + break; + } + + SBE_INFO("mode [0x%08X] addr[0x%08X] len[0x%08X]", + l_req.mode, l_req.addr, l_req.len); + + // Get the Proc Chip Target to be passed in to the procedure call + Target l_proc = plat_getChipTarget(); + + // Do linear setup for indirect access HWP for Chan0, Chan2 and Chan3 + // For Circular Mode, Chan1 is assumed to be setup by default + // Linear mode is setup with Linear streaming mode only + + // Sram Access condition to pass valid address during the first access + bool l_validAddrForFirstAccess = true; + + // Channel Selection based on Mode as well as Fsp attchament + p9ocb::PM_OCB_CHAN_NUM l_chan = p9ocb::OCB_CHAN0; + switch(l_req.mode) + { + case NORMAL_MODE: + if(false == SbeRegAccess::theSbeRegAccess().isFspSystem()) + { + l_chan = p9ocb::OCB_CHAN2; + } + break; + + case DEBUG_MODE: + l_chan = p9ocb::OCB_CHAN3; + break; + + case CIRCULAR_MODE: + l_chan = p9ocb::OCB_CHAN1; + l_validAddrForFirstAccess = false; + break; + + default: + SBE_ERROR(SBE_FUNC "Invalid Mode Passed by User"); + l_rc = SBE_SEC_GENERIC_FAILURE_IN_EXECUTION; + l_respHdr.respHdr.setStatus( SBE_PRI_INVALID_DATA, l_rc); + break; + } + if (SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + break; + } + + // Setup Needs to be called in Normal and Debug Mode only + if( (l_req.mode == NORMAL_MODE) || (l_req.mode == DEBUG_MODE) ) + { + l_fapiRc = p9_pm_ocb_indir_setup_linear(l_proc, l_chan, + p9ocb::OCB_TYPE_LINSTR, + l_req.addr); + if(l_fapiRc != FAPI2_RC_SUCCESS) + { + SBE_ERROR(SBE_FUNC "p9_pm_ocb_indir_setup_linear failed, " + "Channel[0x%02X] Addr[0x%08X]", + l_chan, l_req.addr); + + // Respond with HWP FFDC + l_respHdr.respHdr.setStatus(SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + break; + } + } + + //Create a 128 Byte Buffer - 16 64-Bit buffer + // This is our Granule size as well for this HWP + uint32_t l_getBuf[SBE_OCC_SRAM_GRANULE/SBE_32BIT_ALIGN_FACTOR] = {}; + uint32_t l_remainingLen = l_req.len; // Initialize with Total Len + uint32_t l_lenPassedToHwp = 0; + uint32_t l_actLen = 0; // Return Len from Hwp not used + + while(l_remainingLen) + { + if(l_remainingLen <= SBE_OCC_SRAM_GRANULE) + { + l_lenPassedToHwp = l_remainingLen; + } + else + { + l_lenPassedToHwp = SBE_OCC_SRAM_GRANULE; + } + l_remainingLen = l_remainingLen - l_lenPassedToHwp; + + // Fetch buffer from Upstream Fifo for the HWP if it is PutOCC Sram + if(!i_isGetFlag) + { + l_len2dequeue = (l_lenPassedToHwp/SBE_32BIT_ALIGN_FACTOR); + l_rc = sbeUpFifoDeq_mult ( l_len2dequeue, + l_getBuf, + false); + // If there was an underlying FIFO operation failure + if (SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + // Let command processor routine to handle the RC. + break; + } + } + + // Don't need to put any check for Linear/Circular - It's the same + // API for access, For circular valid address flag is false, Hwp + // doesn't need the address field from us. + l_fapiRc = p9_pm_ocb_indir_access( + l_proc, + l_chan, + l_ocb_access, // Get/Put + (l_lenPassedToHwp/SBE_64BIT_ALIGN_FACTOR), // 64-bit aligned + l_validAddrForFirstAccess, // If requested addr is valid + l_req.addr, // Requested Addr being passed + l_actLen, // O/p from hwp not used + (uint64_t *)l_getBuf); // O/p buffer + if(l_fapiRc != FAPI2_RC_SUCCESS) + { + SBE_ERROR(SBE_FUNC "p9_pm_ocb_indir_access failed, " + "Channel[0x%02X] Addr[0x%08X] 64Bit Aligned Len[0x%08X]", + l_chan, l_req.addr, (l_lenPassedToHwp/SBE_64BIT_ALIGN_FACTOR)); + + // Respond with HWP FFDC + l_respHdr.respHdr.setStatus(SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + break; + } + + l_totalReturnLen = l_totalReturnLen + l_lenPassedToHwp; + // Change this to false, so that Indirect Access Hwp doesn't + // reset the Address to starting point. + l_validAddrForFirstAccess = false; + + if(i_isGetFlag) // Get Occ Sram + { + l_len2dequeue = (l_lenPassedToHwp/SBE_32BIT_ALIGN_FACTOR); + // Push this into the downstream FIFO + l_rc = sbeDownFifoEnq_mult (l_len2dequeue, l_getBuf); + + // If FIFO failure + if (SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + // Let command processor routine to handle the RC. + break; + } + } + } // End of while Put/Get from Hwp + + // 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 ) + { + break; + } + + do + { + l_len2dequeue = 0; + if (!i_isGetFlag) + { + // If there was a HWP failure for put sram occ request, + // need to Flush out upstream FIFO, until EOT arrives + if ( l_fapiRc != FAPI2_RC_SUCCESS ) + { + l_rc = sbeUpFifoDeq_mult(l_len2dequeue, NULL, + true, true); + if ( SBE_SEC_OPERATION_SUCCESSFUL != l_rc ) + { + break; + } + } + // For other success paths, just attempt to offload + // the next entry, which is supposed to be the EOT entry + else + { + l_rc = sbeUpFifoDeq_mult(l_len2dequeue, NULL, true); + if ( SBE_SEC_OPERATION_SUCCESSFUL != l_rc ) + { + break; + } + } + } + + // Distance to Header is minus the length field in the response + // buffer. So when we do sizeof(l_respHdr) It will add an extra byte + // for the length. So it compensates for the length, if we start the + // distance from hdr as zero. + uint32_t l_dist2Hdr = 0; + + // Now enqueue the minimum response header + // first enqueue the length of data actually written + l_respHdr.setLength(l_totalReturnLen); + uint32_t l_len = sizeof(l_respHdr) / sizeof(uint32_t); + l_rc = sbeDownFifoEnq_mult(l_len, (uint32_t *)(&l_respHdr)); + + if ( SBE_SEC_OPERATION_SUCCESSFUL != l_rc ) + { + break; + } + + l_dist2Hdr += l_len; + + // Enqueue FFDC data if there is one + if( l_ffdc.getRc() ) + { + l_len = sizeof(l_ffdc) / sizeof(uint32_t); + l_rc = sbeDownFifoEnq_mult (l_len, (uint32_t *)(&l_ffdc)); + if ( SBE_SEC_OPERATION_SUCCESSFUL != l_rc ) + { + break; + } + + l_dist2Hdr += l_len; + } + + l_len = sizeof(l_dist2Hdr) / sizeof(uint32_t); + l_rc = sbeDownFifoEnq_mult ( l_len, &l_dist2Hdr); + + if ( SBE_SEC_OPERATION_SUCCESSFUL != l_rc ) + { + break; + } + }while(0); + }while(0); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbePutOccSram (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbePutOccSram " + return sbeOccSramAccess_Wrap (false); + #undef SBE_FUNC +} + +///////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeGetOccSram (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeGetOccSram " + return sbeOccSramAccess_Wrap (true); + #undef SBE_FUNC +} + diff --git a/src/sbefw/sbecmdsram.H b/src/sbefw/sbecmdsram.H new file mode 100644 index 00000000..1c86aa2b --- /dev/null +++ b/src/sbefw/sbecmdsram.H @@ -0,0 +1,64 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdsram.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbecmdsram.H + * + * @brief This file contains the Interfaces for the Sram Access chip-ops + * + */ + +#ifndef __SBEFW_SBECMDSRAM_H +#define __SBEFW_SBECMDSRAM_H + +#include + +static const uint8_t SBE_32BIT_ALIGN_FACTOR = 4; +static const uint8_t SBE_64BIT_ALIGN_FACTOR = 8; + +static const uint64_t SBE_FWCTRLFLG3_FSP_ATTACHED = 0X1000000000000000; + +/* + * @brief Granule size in Bytes for 'Get from Hwp'/'Put to Hwp' + */ +static const uint32_t SBE_OCC_SRAM_GRANULE = 128; + +/** + * @brief sbeGetOccSram : Implements SBE Get Occ Sram ChipOp + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetOccSram (uint8_t *i_pArg); + +/** + * @brief sbePutOccSram : Implements SBE Put Occ Sram ChipOp + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbePutOccSram (uint8_t *i_pArg); + +#endif /* __SBEFW_SBECMDSRAM_H */ diff --git a/src/sbefw/sbeerrorcodes.H b/src/sbefw/sbeerrorcodes.H new file mode 100644 index 00000000..2e37bb2b --- /dev/null +++ b/src/sbefw/sbeerrorcodes.H @@ -0,0 +1,49 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeerrorcodes.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbeerrorcodes.H + * + * @brief This file contains the SBE internal error status codes + * + */ + +#ifndef __SBEFW_SBEERRORCODES_H +#define __SBEFW_SBEERRORCODES_H + +#include + + +/** + * @brief enums SBE internal error codes + * +*/ +enum sbeInternalResponseCodes +{ + SBE_FIFO_RESET_RECEIVED = 0xFA00, + SBE_FIFO_RESET_HANDLING_FAILED = 0xFB00, + SBE_FUNC_NOT_SUPPORTED = 0xFC00, +}; + + +#endif // __SBEFW_SBEERRORCODES_H \ No newline at end of file diff --git a/src/sbefw/sbeevents.H b/src/sbefw/sbeevents.H new file mode 100644 index 00000000..6506a050 --- /dev/null +++ b/src/sbefw/sbeevents.H @@ -0,0 +1,96 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeevents.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbeevents.H + * + * @brief This file contains interfaces pertaining to the events for state + * transition trigger. + * + */ + +#ifndef __SBEFW_SBEEVENTS_H +#define __SBEFW_SBEEVENTS_H + +/** + * @brief An enumeration of all SBE state transition events + * + */ +enum sbeEvent +{ + SBE_CONTINUE_BOOT_PLCK_EVENT = 0x0, // From FFDC State + SBE_CONTINUE_BOOT_RUNTIME_EVENT = 0x1, // From FFDC State + SBE_RUNTIME_EVENT = 0x2, // From FFDC/Unknown/ISTEP/IPLING State + SBE_ISTEP_EVENT = 0x3, // From FFDC/Unknown State + SBE_PLCK_EVENT = 0x4, // From FFDC/Unknown state + SBE_DUMP_FAILURE_EVENT = 0x5, // From IPLING/RUNTIME/MPIPL/DMT/Unknown State + SBE_ENTER_MPIPL_EVENT = 0x6, // From Runtime State + SBE_CONTINUE_MPIPL_EVENT = 0x7, // From MPIPL Wait State + SBE_ABORT_EVENT = 0x8, // From Any state + SBE_DMT_ENTER_EVENT = 0x9, // From Runtime State + SBE_DMT_COMP_EVENT = 0xA, // From DMT State + SBE_FAILURE_EVENT = 0xB, // From Any State + SBE_FFDC_COLLECT_EVENT = 0xC, // From Unknown State +}; + +// Maximum number of Events per State +enum maxEventPerState +{ + SBE_STATE_UNKNOWN_MAX_EVENT = 5, + SBE_STATE_FFDC_COLLECT_MAX_EVENT = 4, + SBE_STATE_IPLING_MAX_EVENT = 4, + SBE_STATE_ISTEP_MAX_EVENT = 3, + SBE_STATE_RUNTIME_MAX_EVENT = 4, + SBE_STATE_MPIPL_MAX_EVENT = 2, + SBE_STATE_DMT_MAX_EVENT = 1, + SBE_STATE_DUMP_MAX_EVENT = 0, + SBE_STATE_FAILURE_MAX_EVENT = 0, + SBE_STATE_QUIESCE_MAX_EVENT = 0, + SBE_STATE_ABORT_MAX_EVENT = 0, + + // Total number of State Transition Events, Addition of all the above + SBE_MAX_TRANSITIONS = 23, +}; + + +// Entry Point to stateTransitionStr_t Map Structure, This adds up all the state +// transition of the previous state, If any more transition is added, this will +// add up to all subsequent entries. This is closely mapped with the sbestates.H +// as well. +enum entryToStateMap +{ + SBE_STATE_UNKNOWN_ENTRY_TO_MAP = 0, + SBE_STATE_FFDC_COLLECT_ENTRY_TO_MAP = SBE_STATE_UNKNOWN_ENTRY_TO_MAP + SBE_STATE_UNKNOWN_MAX_EVENT, // 5 + SBE_STATE_IPLING_ENTRY_TO_MAP = SBE_STATE_FFDC_COLLECT_ENTRY_TO_MAP + SBE_STATE_FFDC_COLLECT_MAX_EVENT, //9 + SBE_STATE_ISTEP_ENTRY_TO_MAP = SBE_STATE_IPLING_ENTRY_TO_MAP + SBE_STATE_IPLING_MAX_EVENT, //13 + SBE_STATE_RUNTIME_ENTRY_TO_MAP = SBE_STATE_ISTEP_ENTRY_TO_MAP + SBE_STATE_ISTEP_MAX_EVENT, //16 + SBE_STATE_MPIPL_ENTRY_TO_MAP = SBE_STATE_RUNTIME_ENTRY_TO_MAP + SBE_STATE_RUNTIME_MAX_EVENT, //20 + SBE_STATE_DMT_ENTRY_TO_MAP = SBE_STATE_MPIPL_ENTRY_TO_MAP + SBE_STATE_MPIPL_MAX_EVENT, //22 + SBE_STATE_DUMP_ENTRY_TO_MAP = SBE_STATE_DMT_ENTRY_TO_MAP + SBE_STATE_DMT_MAX_EVENT, //23 + SBE_STATE_FAILURE_ENTRY_TO_MAP = SBE_STATE_DUMP_ENTRY_TO_MAP + SBE_STATE_DUMP_MAX_EVENT, //23 + SBE_STATE_QUIESCE_ENTRY_TO_MAP = SBE_STATE_FAILURE_ENTRY_TO_MAP + SBE_STATE_FAILURE_MAX_EVENT, //23 + SBE_STATE_ABORT_ENTRY_TO_MAP = SBE_STATE_QUIESCE_ENTRY_TO_MAP + SBE_STATE_QUIESCE_MAX_EVENT, //23 +}; + +#endif //__SBEFW_SBEEVENTS_H + diff --git a/src/sbefw/sbeexeintf.H b/src/sbefw/sbeexeintf.H new file mode 100644 index 00000000..8a8aff66 --- /dev/null +++ b/src/sbefw/sbeexeintf.H @@ -0,0 +1,256 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeexeintf.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbeexeintf.H + * + * @brief This file contains the SBE control loop firmware details like + * - Thread priority enums + * - Thread stack size and space enums + * - Thread sub-rountine declarations + * - IRQ setup and ISR declarations + * - Other Common declaration among all the threads + */ + +#ifndef __SBEFW_SBE_H +#define __SBEFW_SBE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pk.h" + +#ifdef __cplusplus +} +#endif + +/** + * @brief enums for priorities for thread creation + * + */ +typedef enum +{ + THREAD_PRIORITY_MAX_0, + THREAD_PRIORITY_1, + THREAD_PRIORITY_2, + THREAD_PRIORITY_3, + THREAD_PRIORITY_4, + THREAD_PRIORITY_5, + THREAD_PRIORITY_6, + THREAD_PRIORITY_7, + THREAD_PRIORITY_8, + THREAD_PRIORITY_MIN_30 = 30, +} sbeThreadPriorities ; + +/** + * @brief enums for thread stack sizes + * - Non-Critical Stack used by non-critical interrupt handlers + * - Critical Stack used for critical interrupts + * - Stacks for each thread + * + * @TODO via RTC : 128657 + * - Measure the actual thread stack utilization + * - This will be a continuous activity + */ +enum sbeThreadStackSize +{ + SBE_NONCRITICAL_STACK_SIZE = 256, + SBE_THREAD_ASYNC_CMD_PROC_STACK_SIZE = 256, + SBE_THREAD_CMD_RECV_STACK_SIZE = 512, + SBE_THREAD_SYNC_CMD_PROC_STACK_SIZE = 2048, +}; + +/** + * @brief Global semaphore : g_sbeSemCmdRecv + * + * This is used to synchronize between the ISR and + * the command receiver thread. + * + */ +extern PkSemaphore g_sbeSemCmdRecv; + +/** + * @brief Global semaphore : g_sbeSemCmdProcess + * + * This is used to synchronize between command receiver thread + * and synchronous command processor thread. + * + */ +extern PkSemaphore g_sbeSemCmdProcess; + + +/** + * @brief SBE Interface source + * + */ +typedef enum +{ + SBE_INTERFACE_UNKNOWN = 0x00, + SBE_INTERFACE_FIFO = 0x01, + SBE_INTERFACE_PSU = 0x02, + SBE_INTERFACE_FIFO_RESET = 0x04, +} sbeInterfaceSrc_t; + +/* + * @brief Enum for Handler, handling the interrupt and setting/clearing the + * interrupt variable + */ +typedef enum +{ + SBE_ALL_HANDLER = 0x0, + SBE_INTERRUPT_ROUTINE = 0x1, + SBE_RX_ROUTINE = 0x2, + SBE_PROC_ROUTINE = 0x3, +} sbeHandler_t; + +/** + * @brief structure for SBE external Interrupt handling + * + */ +typedef struct +{ + uint8_t intrSource; + uint8_t rxThrIntrSource; + uint8_t procThrIntrSource; + + void setIntrSource(const sbeHandler_t i_handler, + const sbeInterfaceSrc_t i_val) + { + switch(i_handler) + { + case SBE_INTERRUPT_ROUTINE: intrSource |= i_val; break; + case SBE_RX_ROUTINE: rxThrIntrSource |= i_val; break; + case SBE_PROC_ROUTINE: procThrIntrSource |= i_val; break; + case SBE_ALL_HANDLER: break; + } + } + + void clearIntrSource(const sbeHandler_t i_handler, + const sbeInterfaceSrc_t i_val) + { + switch(i_handler) + { + case SBE_INTERRUPT_ROUTINE: intrSource &= ~i_val; break; + case SBE_RX_ROUTINE: rxThrIntrSource &= ~i_val; break; + case SBE_PROC_ROUTINE: procThrIntrSource &= ~i_val; break; + case SBE_ALL_HANDLER: + { + intrSource &= ~i_val; + rxThrIntrSource &= ~i_val; + procThrIntrSource &= ~i_val; + break; + } + } + } + + bool isSet (const sbeHandler_t i_handler, const sbeInterfaceSrc_t i_val) + { + bool l_ret = false; + switch(i_handler) + { + case SBE_INTERRUPT_ROUTINE: l_ret = (intrSource & i_val); break; + case SBE_RX_ROUTINE: l_ret = (rxThrIntrSource & i_val); break; + case SBE_PROC_ROUTINE: l_ret = (procThrIntrSource & i_val); break; + case SBE_ALL_HANDLER: break; + } + return l_ret; + } +} sbeIntrHandle_t; +extern sbeIntrHandle_t g_sbeIntrSource ; + + +/** + * @TODO via RTC : 128658 + * Mutex protect the critical data + * e.g., add Mutex g_sbeMutCmdReqBuf etc. + */ + +/** + * @brief sbeCommandReceiver_routine + * The major responsibilities of this thread are : + * - Determine the reason for the interrupt + * - FIFO New data + * - FIFO reset + * - Host services + * - Dequeue the mandatory 2 entry header from upstream FIFO + * - Command input data validation + * - SBE State and pre-requirements validation + * - FFDC collection and FIFO flush upon validation failure + * - Unblock SBE command processor thread + * - Perform FIFO reset upon request from SP + * + * @param[in] i_pArg - Any buffer needed to be passed to the thread routine + */ +void sbeCommandReceiver_routine(void *i_pArg); + +/** + * @brief sbeSyncCommandProcessor_routine + * The major responsibilities of this thread are : + * - Dequeue data payload from upstream FIFO + * - Un-marshalling of the command request data + * - Blacklist validation + * - FFDC collection upon validation failure + * - Invoke the corresponding Hardware access utility + * or the HWP corresponding to the chipOp request + * - FFDC collection and FIFO flush upon hardware access / HWP failure + * - Build the response buffer with the data and the header + * - Enqueue the response into the Downstream FIFO + * - Un-mask the new data available interrupt + * + * @param[in] i_pArg - Any buffer needed to be passed to the thread routine + */ +void sbeSyncCommandProcessor_routine(void *i_pArg); + +/** + * @brief sbeAsyncCommandProcessor_routine + * @TODO RTC via : 130392 + * Add infrastructure for host interface + * + * @param[in] i_pArg - Any buffer needed to be passed to the thread routine + */ +void sbeAsyncCommandProcessor_routine(void *i_pArg); + + +/* @brief ISR for all SBE External Interrupts + * - FIFO : New data available + * - FIFO : Reset Request + * - PSU : New data available + * + * @param[in/out] i_pArg - Any buffer needed to be passed to the handler + * @param[in] i_irq - IRQ number as defined in the SBE PPE spec + */ +void sbe_interrupt_handler(void* i_pArg, PkIrqId i_irq); + + +/* brief : Register SBE interrupt handlers and enable the IRQs + * + * @return int PK_OK - Success (IRQ Setup was successful) + * PK_INVALID_ARGUMENT_IRQ_HANDLER - Invalid argument passed + * (Code bug) + * + */ +int sbeIRQSetup (void); + + +#endif /* __SBEFW_SBE_H */ diff --git a/src/sbefw/sbefifo.H b/src/sbefw/sbefifo.H new file mode 100644 index 00000000..47ce5beb --- /dev/null +++ b/src/sbefw/sbefifo.H @@ -0,0 +1,227 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbefifo.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbefifo.H + * + * @brief This file contains basic SBE FIFO hardware specific + * definitions and operations. + * + */ + +#ifndef __SBEFW_SBEFIFO_H +#define __SBEFW_SBEFIFO_H + +#include "sbeexeintf.H" +#include "sbetrace.H" +#include "ppe42_scom.h" +#include "sbe_sp_intf.H" +#include "sbeSpMsg.H" + +/** + * @brief SBE FIFO Access addresses + * + */ +const uint32_t SBE_FIFO_BASE = 0x000B0000; + +const uint32_t SBE_UPSTREAM_FIFO_DEQ_ADD = SBE_FIFO_BASE + 0x0000; +const uint32_t SBE_UPSTREAM_FIFO_STATUS = SBE_FIFO_BASE + 0x0001; +const uint32_t SBE_UPSTREAM_FIFO_SIGNAL_EOT = SBE_FIFO_BASE + 0x0002; +const uint32_t SBE_UPSTREAM_FIFO_REQ_RESET = SBE_FIFO_BASE + 0x0003; +const uint32_t SBE_UPSTREAM_FIFO_PERFORM_RESET = SBE_FIFO_BASE + 0x0004; +const uint32_t SBE_UPSTREAM_FIFO_ACK_EOT = SBE_FIFO_BASE + 0x0005; + +const uint32_t SBE_DOWNSTREAM_FIFO_ENQ_ADD = SBE_FIFO_BASE + 0x0010; +const uint32_t SBE_DOWNSTREAM_FIFO_STATUS = SBE_FIFO_BASE + 0x0011; +const uint32_t SBE_DOWNSTREAM_FIFO_SIGNAL_EOT = SBE_FIFO_BASE + 0x0012; +const uint32_t SBE_DOWNSTREAM_FIFO_REQ_RESET = SBE_FIFO_BASE + 0x0013; +const uint32_t SBE_DOWNSTREAM_FIFO_PERFORM_RESET = SBE_FIFO_BASE + 0x0014; +const uint32_t SBE_DOWNSTREAM_FIFO_ACK_EOT = SBE_FIFO_BASE + 0x0015; + +/** + * @brief SBE Upstream FIFO Status bits + * + */ + +typedef struct +{ + uint32_t valid_flag:1; // Bit 0 + uint32_t eot_flag:1; // Bit 1 + uint32_t parity_err:1; // Bit 2 + uint32_t reserved3_5:3; // Bit 3:5 + uint32_t req_upfifo_reset:1; // Bit 6 + uint32_t req_downfifo_reset:1; // Bit 7 + uint32_t signaling_eot:1; // Bit 8 + uint32_t reserved9:1; // Bit 9 + uint32_t fifo_full:1; // Bit 10 + uint32_t fifo_empty:1; // Bit 11 + uint32_t fifo_entry_count:4; // Bit 12:15 + uint32_t fifo_valid_flags:8; // Bit 16:23 + uint32_t fifo_eot_flags:8; // Bit 24:31 + +} sbe_upfifo_status_t ; + +/** + * @brief 64-bit DW structure for Upstream FIFO Dequeue + * or Downstream FIFO Enqueue + * For Upstream FIFO, + * Bit 0 - 31 : Data, Bit 32 - 63 : Status + * For Downstream FIFO, + * Bit 0 - 31 : Data, Bit 32 - 63 : Unused + * + */ +typedef struct +{ + uint32_t fifo_data; + + // The following status field is applicable only for + // upstream FIFO access and will remain reserved for + // downstream FIFO access + sbe_upfifo_status_t statusOrReserved; +} sbeFifoEntry_t ; + + +/** + * @brief 64-bit DW structure for Upstream FIFO Status Reg Read + * Bit 0 - 31 : Status Data, Bit 32 - 63 : Unused + * + */ +typedef struct +{ + sbe_upfifo_status_t upfifo_status; + uint32_t reserved; +} sbeUpFifoStatusReg_t ; + + +/** + * @brief SBE Downstream FIFO Status bits + * + */ +typedef struct +{ + uint32_t reserved0_1:2; // Bit 0:1 + uint32_t parity_err:1; // Bit 2 + uint32_t reserved3_5:3; // Bit 3:5 + uint32_t req_downfifo_reset:1; // Bit 6 + uint32_t req_upfifo_reset:1; // Bit 7 + uint32_t signaling_eot:1; // Bit 8 + uint32_t reserved9:1; // Bit 9 + uint32_t fifo_full:1; // Bit 10 + uint32_t fifo_empty:1; // Bit 11 + uint32_t fifo_entry_count:4; // Bit 12:15 + uint32_t fifo_valid_flags:8; // Bit 16:23 + uint32_t fifo_eot_flags:8; // Bit 24:31 + +} sbe_downfifo_status_t ; + +/** + * @brief 64-bit DW structure for Downstream FIFO Status Reg Read + * Bit 0 - 31 : Status Data, Bit 32 - 63 : Unused + * + */ +typedef struct +{ + sbe_downfifo_status_t downfifo_status; + uint32_t reserved; +} sbeDownFifoStatusReg_t; + +/*****************************************************************/ +/** Upstream FIFO access utilities **/ +/*****************************************************************/ + +/** + * @brief sbeUpFifoDeq : Read entry and status from Upstream FIFO + * + * @param[out] 64-Bit Data read from Upstream FIFO + * + * @return Rc from the underlying scom utility + * + */ +extern inline uint32_t sbeUpFifoDeq (uint64_t *o_data) +{ + /* For SBE FIFO (PIB) access, chiplet ID should be passed as 0 */ + return getscom_abs(SBE_UPSTREAM_FIFO_DEQ_ADD, o_data); +} + + +/** + * @brief sbeUpFifoPerformReset : Perform Upstream FIFO reset request + * + * @return Rc from the underlying scom utility + * + */ +extern inline uint32_t sbeUpFifoPerformReset (void) +{ + SBE_INFO("sbeUpFifoPerformReset"); + return putscom_abs(SBE_UPSTREAM_FIFO_PERFORM_RESET, ((uint64_t)0x1)<<32); +} + + +/** + * @brief sbeUpFifoAckEot : Acknowledge EOT in Upstream FIFO + * + * @return Rc from the underlying scom utility + * + */ +extern inline uint32_t sbeUpFifoAckEot (void) +{ + SBE_INFO("sbeUpFifoAckEot"); + return putscom_abs(SBE_UPSTREAM_FIFO_ACK_EOT, ((uint64_t)0x1)<<32); +} + + +/*****************************************************************/ +/** Downstream FIFO access utilities **/ +/*****************************************************************/ + +/** + * @brief sbeDownFifoEnq : Write data into Downstream FIFO + * + * @param[in] 64-Bit Data write into Downstream FIFO + * Bit 0-31 : Data + * Bit 32-63 : Unused + * + * @return Rc from the underlying scom utility + */ +extern inline uint32_t sbeDownFifoEnq (const uint64_t i_data) +{ + SBE_DEBUG(">sbeDownFifoEnq"); + return putscom_abs(SBE_DOWNSTREAM_FIFO_ENQ_ADD, i_data); +} + + +/** + * @brief sbeDownFifoGetStatus : Read status from downstream FIFO + * + * @param[out] 64-Bit Read status from downstream FIFO + * Bit 0-31 : Data + * Bit 32-63 : Unused + * + * @return Rc from the underlying scom utility + */ +extern inline uint32_t sbeDownFifoGetStatus (uint64_t *o_data) +{ + return getscom_abs(SBE_DOWNSTREAM_FIFO_STATUS, o_data); +} + +#endif // __SBEFW_SBEFIFO_H diff --git a/src/sbefw/sbefwfiles.mk b/src/sbefw/sbefwfiles.mk new file mode 100644 index 00000000..24f9318e --- /dev/null +++ b/src/sbefw/sbefwfiles.mk @@ -0,0 +1,48 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/sbefw/sbefwfiles.mk $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# 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 +SBEFW-CPP-SOURCES = sbemain.C +SBEFW-CPP-SOURCES += sbeirq.C +SBEFW-CPP-SOURCES += sbecmdreceiver.C +SBEFW-CPP-SOURCES += sbecmdprocessor.C +SBEFW-CPP-SOURCES += sbecmdparser.C +SBEFW-CPP-SOURCES += sbecmdscomaccess.C +SBEFW-CPP-SOURCES += sbecmdiplcontrol.C +SBEFW-CPP-SOURCES += pool.C +SBEFW-CPP-SOURCES += sbecmdgeneric.C +SBEFW-CPP-SOURCES += sbeFifoMsgUtils.C +SBEFW-CPP-SOURCES += sbecmdmemaccess.C +SBEFW-CPP-SOURCES += sbeHostUtils.C +SBEFW-CPP-SOURCES += sbecmdcntrldmt.C +SBEFW-CPP-SOURCES += sbecmdsram.C +SBEFW-CPP-SOURCES += sberegaccess.C +SBEFW-CPP-SOURCES += sbecmdcntlinst.C +SBEFW-CPP-SOURCES += sbecmdregaccess.C +SBEFW-CPP-SOURCES += sbeFFDC.C +SBEFW-CPP-SOURCES += sbecmdringaccess.C +SBEFW-CPP-SOURCES += sbescom.C + +SBEFW-C-SOURCES = +SBEFW-S-SOURCES = + +SBEFW_OBJECTS = $(SBEFW-C-SOURCES:.c=.o) $(SBEFW-CPP-SOURCES:.C=.o) $(SBEFW-S-SOURCES:.S=.o) diff --git a/src/sbefw/sbeirq.C b/src/sbefw/sbeirq.C new file mode 100644 index 00000000..bf445245 --- /dev/null +++ b/src/sbefw/sbeirq.C @@ -0,0 +1,195 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeirq.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbeirq.C + * + * @brief This sets up and registers SBE ISRs + * + */ + +#include "sbeexeintf.H" +#include "sbeirq.H" +#include "sbetrace.H" +#include "assert.h" + +extern sbeIntrHandle_t g_sbeIntrSource ; + +//////////////////////////////////////////////////////////////// +// @brief: SBE control loop ISR: +// - FIFO new data available +// - FIFO reset request +// - PSU new data available +// +// @param[in] i_pArg - Unused +// @param[in] i_irq - IRQ number as defined in sbeirq.h +// +//////////////////////////////////////////////////////////////// +void sbe_interrupt_handler (void *i_pArg, PkIrqId i_irq) +{ + #define SBE_FUNC " sbe_interrupt_handler " + SBE_ENTER(SBE_FUNC"i_irq=[0x%02X]",i_irq); + + int l_rc = 0; + + switch (i_irq) + { + case SBE_IRQ_HOST_PSU_INTR: + g_sbeIntrSource.setIntrSource(SBE_INTERRUPT_ROUTINE, + SBE_INTERFACE_PSU); + break; + + case SBE_IRQ_SBEFIFO_DATA: + g_sbeIntrSource.setIntrSource(SBE_INTERRUPT_ROUTINE, + SBE_INTERFACE_FIFO); + pk_irq_disable(SBE_IRQ_SBEFIFO_RESET); + break; + + case SBE_IRQ_SBEFIFO_RESET: + g_sbeIntrSource.setIntrSource(SBE_INTERRUPT_ROUTINE, + SBE_INTERFACE_FIFO_RESET); + pk_irq_disable(SBE_IRQ_SBEFIFO_DATA); + break; + + default: + SBE_ERROR(SBE_FUNC"Unknown IRQ, assert"); + assert(0); + break; + } + // Mask the interrupt + pk_irq_disable(i_irq); + + // Unblock the command receiver thread + l_rc = pk_semaphore_post(&g_sbeSemCmdRecv); + if (l_rc) + { + // If we received an error while posting the semaphore, + // unmask the interrupt back and assert + SBE_ERROR(SBE_FUNC"pk_semaphore_post failed, rc=[%d]", l_rc); + pk_irq_enable(i_irq); + assert(!l_rc); + } + #undef SBE_FUNC +} + +//////////////////////////////////////////////////////////////// +// See sbeexeintf.h for more details +//////////////////////////////////////////////////////////////// +int sbeIRQSetup (void) +{ + #define SBE_FUNC " sbeIRQSetup " + int l_rc = 0; + PkIrqId l_irq; + + // Disable the relevant IRQs while we set them up + pk_irq_disable(SBE_IRQ_HOST_PSU_INTR); + pk_irq_disable(SBE_IRQ_SBEFIFO_DATA); + pk_irq_disable(SBE_IRQ_SBEFIFO_RESET); + + do + { + // Register the IRQ handler with PK + + // PSU New data available interrupt + l_irq = SBE_IRQ_HOST_PSU_INTR; + l_rc = pk_irq_handler_set(l_irq, sbe_interrupt_handler, NULL); + if(l_rc) + { + break; + } + + // FIFO New data available interrupt + l_irq = SBE_IRQ_SBEFIFO_DATA; + l_rc = pk_irq_handler_set(l_irq, sbe_interrupt_handler, NULL); + if(l_rc) + { + break; + } + + // FIFO Reset request + l_irq = SBE_IRQ_SBEFIFO_RESET; + l_rc = pk_irq_handler_set(l_irq, sbe_interrupt_handler, NULL); + if(l_rc) + { + break; + } + + // Enable the IRQ + pk_irq_enable(SBE_IRQ_SBEFIFO_RESET); + pk_irq_enable(SBE_IRQ_SBEFIFO_DATA); + pk_irq_enable(SBE_IRQ_HOST_PSU_INTR); + } while(false); + + if (l_rc) + { + SBE_ERROR (SBE_FUNC"pk_irq_handler_set failed, IRQ=[0x%02X], " + "rc=[%d]", l_irq, l_rc); + } + + return l_rc; + #undef SBE_FUNC +} + +//////////////////////////////////////////////////////////////// +// SBE handler for the PPE machine check interrupt +//////////////////////////////////////////////////////////////// +// TODO: via RTC 155896 - Change the way bad scoms are handled. +// Once HW375602 is fixed, there will be no need for this +// interrupt handler. +extern "C" void __sbe_machine_check_handler() +{ + asm( + "# Save r4 to stack, since it is going to be used by\n" + "# this handler\n" + "stwu %r1, -8(%r1)\n" + "stw %r4, 0(%r1)\n" + "# Check the MCS bits (29:31) in the ISR to determine the cause for the machine check\n" + "# For a data machine check, the MCS should be 0x001 to 0x011\n" + "mfisr %r4\n" + "andi. %r4, %r4, 0x0007\n" + "bwz %r4, __hang_forever\n" + "cmpwibgt %r4, 0x0003, __hang_forever\n" + "# The EDR contains the address that caused the machine check\n" + "mfedr %r4\n" + "srawi %r4, %r4, 16\n" + "# If the address is in the range 0x00000000 - 0x7f000000, we treat it as a\n" + "# failed scom and jump to __scom_error\n" + "cmplwi %r4, 0x8000\n" + "blt __scom_error\n" + "# Else, just hang here forever\n" + "__hang_forever:\n" + "b .\n" + "__scom_error:\n" + "# The srr0 contains the address of the instruction that caused the machine\n" + "# check (since the the interrupt is raised *before* the instruction\n" + "# completed execution). Since we want the code to continue with the next\n" + "# instruction, we increment srr0 by 4, restore r4, and rfi to branch to srr0\n" + "mfsrr0 %r4\n" + "addi %r4, %r4, 4\n" + "mtsrr0 %r4\n" + "lwz %r4, 0(%r1)\n" + "addi %r1, %r1, 8\n" + "rfi\n" + ); +} + diff --git a/src/sbefw/sbeirq.H b/src/sbefw/sbeirq.H new file mode 100644 index 00000000..8102ce81 --- /dev/null +++ b/src/sbefw/sbeirq.H @@ -0,0 +1,109 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeirq.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbeirq.H + * + * @brief This file contains the SBE PPE Interrupt Request numbers + */ + +#ifndef _SBE_IRQ_H +#define _SBE_IRQ_H + +/** + * @brief SBE PPE IRQ numbers + * + */ + +#define SBE_IRQ_START0 0 /* SBE Start Vector 0 */ +#define SBE_IRQ_START1 1 /* SBE Start Vector 1 */ +#define SBE_IRQ_INTR0 2 /* SBE Interrupt S0 */ +#define SBE_IRQ_INTR1 3 /* SBE Interrupt S1 */ +#define SBE_IRQ_DRTM_REQ 4 /* DRTM late launch request */ +#define SBE_IRQ_SBEFIFO_RESET 5 /* FIFO - Reset request from SE */ +#define SBE_IRQ_SBEFIFO_DATA 6 /* FIFO - Incoming Data Available */ +#define SBE_IRQ_HOST_PSU_INTR 7 /* PSU - Incoming Data Available */ + + +#define SBE_IRQ_RESERVED_8 8 +#define SBE_IRQ_RESERVED_9 9 + +#define SBE_IRQ_RESERVED_10 10 +#define SBE_IRQ_RESERVED_11 11 +#define SBE_IRQ_RESERVED_12 12 +#define SBE_IRQ_RESERVED_13 13 +#define SBE_IRQ_RESERVED_14 14 +#define SBE_IRQ_RESERVED_15 15 +#define SBE_IRQ_RESERVED_16 16 +#define SBE_IRQ_RESERVED_17 17 +#define SBE_IRQ_RESERVED_18 18 +#define SBE_IRQ_RESERVED_19 19 +#define SBE_IRQ_RESERVED_20 20 +#define SBE_IRQ_RESERVED_21 21 +#define SBE_IRQ_RESERVED_22 22 +#define SBE_IRQ_RESERVED_23 23 +#define SBE_IRQ_RESERVED_24 24 +#define SBE_IRQ_RESERVED_25 25 +#define SBE_IRQ_RESERVED_26 26 +#define SBE_IRQ_RESERVED_27 27 +#define SBE_IRQ_RESERVED_28 28 +#define SBE_IRQ_RESERVED_29 29 +#define SBE_IRQ_RESERVED_30 30 +#define SBE_IRQ_RESERVED_31 31 +#define SBE_IRQ_RESERVED_32 32 +#define SBE_IRQ_RESERVED_33 33 +#define SBE_IRQ_RESERVED_34 34 +#define SBE_IRQ_RESERVED_35 35 +#define SBE_IRQ_RESERVED_36 36 +#define SBE_IRQ_RESERVED_37 37 +#define SBE_IRQ_RESERVED_38 38 +#define SBE_IRQ_RESERVED_39 39 +#define SBE_IRQ_RESERVED_40 40 +#define SBE_IRQ_RESERVED_41 41 +#define SBE_IRQ_RESERVED_42 42 +#define SBE_IRQ_RESERVED_43 43 +#define SBE_IRQ_RESERVED_44 44 +#define SBE_IRQ_RESERVED_45 45 +#define SBE_IRQ_RESERVED_46 46 +#define SBE_IRQ_RESERVED_47 47 +#define SBE_IRQ_RESERVED_48 48 +#define SBE_IRQ_RESERVED_49 49 +#define SBE_IRQ_RESERVED_50 50 +#define SBE_IRQ_RESERVED_51 51 +#define SBE_IRQ_RESERVED_52 52 +#define SBE_IRQ_RESERVED_53 53 +#define SBE_IRQ_RESERVED_54 54 +#define SBE_IRQ_RESERVED_55 55 +#define SBE_IRQ_RESERVED_56 56 +#define SBE_IRQ_RESERVED_57 57 +#define SBE_IRQ_RESERVED_58 58 +#define SBE_IRQ_RESERVED_59 59 +#define SBE_IRQ_RESERVED_60 60 +#define SBE_IRQ_RESERVED_61 61 +#define SBE_IRQ_RESERVED_62 62 +#define SBE_IRQ_RESERVED_63 63 + +#define SBE_MACHINE_CHECK_HANDLER \ + b __sbe_machine_check_handler + +#endif //_SBE_IRQ_H diff --git a/src/sbefw/sbemain.C b/src/sbefw/sbemain.C new file mode 100644 index 00000000..06488c14 --- /dev/null +++ b/src/sbefw/sbemain.C @@ -0,0 +1,352 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbemain.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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/sbemain.C + * + * @brief This file does the following + * - SBE Application Main entry point + * - PK initialization + * - Thread initialization + * - Semaphore initialization + * - IRQ setup + * - Scheduling of the threads and + * - Starting of the control loop code flow + * + */ + + +#include "sbeexeintf.H" +#include "sbetrace.H" +#include "sberegaccess.H" +#include "sbestates.H" +#include "fapi2.H" // For target init + +//////////////////////////////////////////////////////////////// +// @brief Global semaphores +//////////////////////////////////////////////////////////////// +PkSemaphore g_sbeSemCmdRecv; +PkSemaphore g_sbeSemCmdProcess; + +// Max defines for Semaphores +static uint32_t MAX_SEMAPHORE_COUNT = 3; + +//////////////////////////////////////////////////////////////// +// @brief Stacks for Non-critical Interrupts and Threads +//////////////////////////////////////////////////////////////// +uint8_t g_sbe_Kernel_NCInt_stack[SBE_NONCRITICAL_STACK_SIZE]; +uint8_t g_sbeCommandReceiver_stack[SBE_THREAD_CMD_RECV_STACK_SIZE]; +uint8_t g_sbeSyncCommandProcessor_stack[SBE_THREAD_SYNC_CMD_PROC_STACK_SIZE]; +uint8_t g_sbeAsyncCommandProcessor_stack[SBE_THREAD_ASYNC_CMD_PROC_STACK_SIZE]; + +//////////////////////////////////////////////////////////////// +// @brief PkThread structure for SBE Command Receiver thread +//////////////////////////////////////////////////////////////// +PkThread g_sbeCommandReceiver_thread; + +//////////////////////////////////////////////////////////////// +// @brief PkThread structure for SBE Synchronous ChipOps +// processing thread +//////////////////////////////////////////////////////////////// +PkThread g_sbeSyncCommandProcessor_thread; + +//////////////////////////////////////////////////////////////// +//// @brief PkThread structure for SBE Asynchronous ChipOps +//// processing thread +//////////////////////////////////////////////////////////////// +PkThread g_sbeAsyncCommandProcessor_thread; + +extern "C" +{ +// These variables are declared in linker script to keep track of +// global constructor pointer functions and sbss section. +extern void (*ctor_start_address)() __attribute__ ((section (".rodata"))); +extern void (*ctor_end_address)() __attribute__ ((section (".rodata"))); +extern uint64_t _sbss_start __attribute__ ((section (".sbss"))); +extern uint64_t _sbss_end __attribute__ ((section (".sbss"))); +// This function will be used to do any C++ handling required before doing +// any main job. Call to this function should get generated by +// compiler. +// TODO via RTC 152070 +// We are also initialising sbss section to zero this function. +// Though it does not do any harm as of now, it is better if we use loader +// or linker script to zero init sbss section. This way we will be future +// garded if pk boot uses some static/global data initialised to +// false in future. +void __eabi() +{ + // Initialise sbss section + uint64_t *startAddr = &_sbss_start; + while ( startAddr != &_sbss_end ) + { + *startAddr = 0; + startAddr++; + } + + // Call global constructors + void(**ctors)() = &ctor_start_address; + while( ctors != &ctor_end_address) + { + (*ctors)(); + ctors++; + } +} +} // end extern "C" + +//////////////////////////////////////////////////////////////// +// @brief sbeInitSems - Create the necessary semaphores +// +// @return PK_OK - Success +// PK_INVALID_SEMAPHORE_AT_CREATE - Invalid PkSemaphore +// PK_INVALID_ARGUMENT_SEMAPHORE - max_count is non-zero +// and less than the initial_count +//////////////////////////////////////////////////////////////// +uint32_t sbeInitSems(void) +{ + SBE_ENTER("sbeInitSems"); + int l_rc = PK_OK; + + do + { + l_rc = pk_semaphore_create(&g_sbeSemCmdRecv, 0, MAX_SEMAPHORE_COUNT); + if (l_rc) + { + break; + } + l_rc = pk_semaphore_create(&g_sbeSemCmdProcess, 0, MAX_SEMAPHORE_COUNT); + if (l_rc) + { + break; + } + } while (false); + + if (l_rc) + { + SBE_ERROR ("pk_semaphore_create, rc=[%d]", l_rc); + } + return l_rc; +} + +//////////////////////////////////////////////////////////////// +// @brief createAndResumeThreadHelper +// - Create and resume the given thread +// +// @param[in/out] io_thread A pointer to an PkThread structure to initialize +// @param[in] i_thread_routine The subroutine that implements the thread +// @param[in/out] io_arg Private data to be passed as the argument to the +// thread routine when it begins execution +// @param[in] i_stack The stack space of the thread +// @param[in] i_stack_size The size of the stack in bytes +// @param[in] i_priority The initial priority of the thread +// +// @return PK_OK Successfully created and resumed the thread +// +// @return PK_INVALID_THREAD_AT_CREATE io_thread is null +// @return PK_INVALID_ARGUMENT_THREAD1 i_thread_routine is null +// @return PK_INVALID_ARGUMENT_THREAD2 i_priority is invalid +// @return PK_INVALID_ARGUMENT_THREAD3 the stack area wraps around +// the end of memory. +// @return PK_STACK_OVERFLOW The stack area at thread creation +// is smaller than the min safe size +// @return PK_INVALID_THREAD_AT_RESUME1 io_thread is null (unlikely) +// @return PK_INVALID_THREAD_AT_RESUME2 The thread is not active, +// i.e. has completed or been deleted, +// @return PK_PRIORITY_IN_USE_AT_RESUME Another thread is already +// mapped at the priority of the thread +//////////////////////////////////////////////////////////////// +uint32_t createAndResumeThreadHelper(PkThread *io_pThread, + PkThreadRoutine i_thread_routine, + void *io_pArg, + PkAddress i_stack, + size_t i_stack_size, + sbeThreadPriorities i_priority) +{ + int l_rc = PK_OK; + + // Thread creation + l_rc = pk_thread_create(io_pThread, + i_thread_routine, + io_pArg, + i_stack, + i_stack_size, + (PkThreadPriority)i_priority); + if(l_rc == PK_OK) + { + // resume the thread once created + l_rc = pk_thread_resume(io_pThread); + } + + // Check for errors creating or resuming the thread + if(l_rc != PK_OK) + { + SBE_ERROR ("Failure creating/resuming thread, rc=[%d]", l_rc); + } + + return l_rc; +} + +//////////////////////////////////////////////////////////////// +// @brief sbeInitThreads +// Create the resume all the firmware threads +// +// @return See createAndResumeThreadHelper for more details +//////////////////////////////////////////////////////////////// +int sbeInitThreads(void) +{ + // Locals + uint32_t l_rc = PK_OK; + + do + { + // Initialize Command receiver thread + l_rc = createAndResumeThreadHelper(&g_sbeCommandReceiver_thread, + sbeCommandReceiver_routine, + (void *)0, + (PkAddress)g_sbeCommandReceiver_stack, + SBE_THREAD_CMD_RECV_STACK_SIZE, + THREAD_PRIORITY_5); + if (l_rc) + { + break; + } + + // Initialize Synchronous Command Processor thread + l_rc = createAndResumeThreadHelper(&g_sbeSyncCommandProcessor_thread, + sbeSyncCommandProcessor_routine, + (void *)0, + (PkAddress)g_sbeSyncCommandProcessor_stack, + SBE_THREAD_SYNC_CMD_PROC_STACK_SIZE, + THREAD_PRIORITY_7); + if (l_rc) + { + break; + } + + // Initialize Asynchronous Command Processor thread + l_rc = createAndResumeThreadHelper(&g_sbeAsyncCommandProcessor_thread, + sbeAsyncCommandProcessor_routine, + (void *)0, + (PkAddress)g_sbeAsyncCommandProcessor_stack, + SBE_THREAD_ASYNC_CMD_PROC_STACK_SIZE, + THREAD_PRIORITY_6); + if (l_rc) + { + break; + } + } while (false); + + // If there are any errors initializing the threads + if( l_rc ) + { + SBE_ERROR ("Error Initializing a thread, rc=[%d]", l_rc); + } + + return l_rc; +} + +//////////////////////////////////////////////////////////////// +// @brief - main : SBE Application main +//////////////////////////////////////////////////////////////// +uint32_t main(int argc, char **argv) +{ + #define SBE_FUNC "main " + SBE_ENTER(SBE_FUNC); + int l_rc = 0; + + // @TODO via RTC : 128818 + // Explore on reclaiming the stack + // used by this Initialization code + + do + { + // initializes kernel data - + // stack, threads, timebase, timers, etc. + l_rc = pk_initialize((PkAddress)g_sbe_Kernel_NCInt_stack, + SBE_NONCRITICAL_STACK_SIZE, + 0, + 500000000); // @TODO via RTC : 128819 + // Need to obtain at Runtime, a new attribute? + if (l_rc) + { + break; + } + + SBE_INFO("Completed PK init"); + + // Initialize the semaphores + l_rc = sbeInitSems(); + if (l_rc) + { + break; + } + + // Initialize SBE control loop threads + l_rc = sbeInitThreads(); + if (l_rc) + { + break; + } + + // Setup SBE PPE IRQs + l_rc = sbeIRQSetup(); + if (l_rc) + { + break; + } + + // TODO via RTC 126146. + // Check if we should call plat_TargetsInit in some other thread. + // We may want to keep only PK init in main and can move + // plat init to some other thread. Only if this is required by more + // than one thread and there can be some race condition, we will + // keep it here before starting other threads. + fapi2::ReturnCode fapiRc = fapi2::plat_TargetsInit(); + if( fapiRc != fapi2::FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC"plat_TargetsInit failed"); + (void)SbeRegAccess::theSbeRegAccess(). + stateTransition(SBE_FAILURE_EVENT); + // Hard Reset SBE to recover + break; + } + + if(SbeRegAccess::theSbeRegAccess().init()) + { + SBE_ERROR(SBE_FUNC"Failed to initialize SbeRegAccess"); + // init failure could mean the below will fail too, but attempt it + // anyway + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_FAILURE_EVENT); + // Hard Reset SBE to recover + break; + } + + // Start running the highest priority thread. + // This function never returns + pk_start_threads(); + + } while (false); + + SBE_EXIT(SBE_FUNC); + return l_rc; +} diff --git a/src/sbefw/sberegaccess.C b/src/sbefw/sberegaccess.C new file mode 100644 index 00000000..71540e56 --- /dev/null +++ b/src/sbefw/sberegaccess.C @@ -0,0 +1,331 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sberegaccess.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sberegaccess.C + * + * @brief This file contains interfaces to get/set FW flags either in the + * scratch registers and/or the FW attributes. + */ + +#include "sberegaccess.H" +#include "sbetrace.H" +#include "fapi2.H" +#include +#include + +using namespace fapi2; + +// Struct to Map Current State - Event - Final State Transition +typedef struct stateTransitionStr +{ + uint16_t currState:4; + uint16_t event:4; + uint16_t finalState:4; + uint16_t reserved:4; +} stateTransitionStr_t; + +// Start and End point of Event Transition in stateTransMap Table +typedef struct stateEventRangeStr +{ + uint16_t start:8; + uint16_t end:8; +}stateEventRangeStr_t; + +// Entry Point and End point to the StateTransition Map for a State +// It is sequenced as per the sbeState enum, Don't change the sequence +// of states. Events are incremented w.r.t previous event. +static const stateEventRangeStr_t eventRangePerState[SBE_MAX_STATE] = +{ + {SBE_STATE_UNKNOWN_ENTRY_TO_MAP, SBE_STATE_UNKNOWN_MAX_EVENT}, + {SBE_STATE_FFDC_COLLECT_ENTRY_TO_MAP, SBE_STATE_FFDC_COLLECT_MAX_EVENT}, + {SBE_STATE_IPLING_ENTRY_TO_MAP, SBE_STATE_IPLING_MAX_EVENT}, + {SBE_STATE_ISTEP_ENTRY_TO_MAP, SBE_STATE_ISTEP_MAX_EVENT}, + {SBE_STATE_RUNTIME_ENTRY_TO_MAP, SBE_STATE_RUNTIME_MAX_EVENT}, + {SBE_STATE_MPIPL_ENTRY_TO_MAP, SBE_STATE_MPIPL_MAX_EVENT}, + {SBE_STATE_DMT_ENTRY_TO_MAP, SBE_STATE_DMT_MAX_EVENT}, + {SBE_STATE_DUMP_ENTRY_TO_MAP, SBE_STATE_DUMP_MAX_EVENT}, + {SBE_STATE_FAILURE_ENTRY_TO_MAP, SBE_STATE_FAILURE_MAX_EVENT}, + {SBE_STATE_QUIESCE_ENTRY_TO_MAP, SBE_STATE_QUIESCE_MAX_EVENT}, + {SBE_STATE_ABORT_ENTRY_TO_MAP, SBE_STATE_ABORT_MAX_EVENT}, +}; + +// Map to connect the current State with an event along with the final state +// transition. It is sequenced according to the sbeState enums, Don't change the +// sequence of states. +static const stateTransitionStr_t stateTransMap[SBE_MAX_TRANSITIONS] = { + {SBE_STATE_UNKNOWN, SBE_FAILURE_EVENT, SBE_STATE_FAILURE}, + {SBE_STATE_UNKNOWN, SBE_RUNTIME_EVENT, SBE_STATE_RUNTIME}, + {SBE_STATE_UNKNOWN, SBE_ISTEP_EVENT, SBE_STATE_ISTEP}, + {SBE_STATE_UNKNOWN, SBE_PLCK_EVENT, SBE_STATE_IPLING}, + {SBE_STATE_UNKNOWN, SBE_FFDC_COLLECT_EVENT, SBE_STATE_FFDC_COLLECT}, + {SBE_STATE_FFDC_COLLECT, SBE_CONTINUE_BOOT_PLCK_EVENT, SBE_STATE_IPLING}, + {SBE_STATE_FFDC_COLLECT, SBE_CONTINUE_BOOT_RUNTIME_EVENT, SBE_STATE_RUNTIME}, + {SBE_STATE_FFDC_COLLECT, SBE_ISTEP_EVENT, SBE_STATE_ISTEP}, + {SBE_STATE_FFDC_COLLECT, SBE_FAILURE_EVENT, SBE_STATE_DUMP}, + {SBE_STATE_IPLING, SBE_RUNTIME_EVENT, SBE_STATE_RUNTIME}, + {SBE_STATE_IPLING, SBE_DUMP_FAILURE_EVENT, SBE_STATE_DUMP}, + {SBE_STATE_IPLING, SBE_FAILURE_EVENT, SBE_STATE_FAILURE}, + {SBE_STATE_IPLING, SBE_ABORT_EVENT, SBE_STATE_ABORT}, + {SBE_STATE_ISTEP, SBE_RUNTIME_EVENT, SBE_STATE_RUNTIME}, + {SBE_STATE_ISTEP, SBE_ABORT_EVENT, SBE_STATE_ABORT}, + {SBE_STATE_ISTEP, SBE_FAILURE_EVENT, SBE_STATE_FAILURE}, + {SBE_STATE_RUNTIME, SBE_DUMP_FAILURE_EVENT, SBE_STATE_DUMP}, + {SBE_STATE_RUNTIME, SBE_ENTER_MPIPL_EVENT, SBE_STATE_MPIPL}, + {SBE_STATE_RUNTIME, SBE_DMT_ENTER_EVENT, SBE_STATE_DMT}, + {SBE_STATE_RUNTIME, SBE_FAILURE_EVENT, SBE_STATE_FAILURE}, + {SBE_STATE_MPIPL, SBE_CONTINUE_MPIPL_EVENT, SBE_STATE_RUNTIME}, + {SBE_STATE_MPIPL, SBE_DUMP_FAILURE_EVENT, SBE_STATE_DUMP}, + {SBE_STATE_DMT, SBE_DMT_COMP_EVENT, SBE_STATE_RUNTIME}, +}; + +/** + * @brief Initizlize the class + * + * @return An RC indicating success/failure + */ + +void SbeRegAccess::stateTransition(const sbeEvent &i_event) +{ + #define SBE_FUNC "SbeRegAccess::stateTransition " + //Fetch Current State + uint32_t l_state = (uint32_t)getSbeState(); + uint8_t l_startCnt = eventRangePerState[l_state].start; + SBE_INFO(SBE_FUNC "Event Received %d CurrState 0x%08X StartCnt%d EndCnt%d", + i_event, l_state, l_startCnt, eventRangePerState[l_state].end); + // Fetch the final State from the Map + while(l_startCnt < + (eventRangePerState[l_state].end + eventRangePerState[l_state].start)) + { + if(stateTransMap[l_startCnt].event == i_event) + { + SBE_INFO(SBE_FUNC "Updating State as %d", + (sbeState)stateTransMap[l_startCnt].finalState); + updateSbeState((sbeState)stateTransMap[l_startCnt].finalState); + break; + } + else + ++l_startCnt; + } + #undef SBE_FUNC +} + +uint32_t SbeRegAccess::init() +{ + #define SBE_FUNC "SbeRegAccess::SbeRegAccess " + static bool l_initDone = false; + uint32_t l_rc = 0; + uint64_t l_mbx8 = 0; + do + { + if(l_initDone) + { + break; + } + // Read SBE messaging register into iv_messagingReg + l_rc = getscom_abs(PERV_SB_MSG_SCOM, &iv_messagingReg); + if(PCB_ERROR_NONE != l_rc) + { + SBE_ERROR(SBE_FUNC"Failed reading sbe messaging reg., RC: 0x%08X. ", + l_rc); + break; + } + // Read Mailbox register 8 to check if the mailbox registers 3 and 6 are + // valid + l_rc = getscom_abs(PERV_SCRATCH_REGISTER_8_SCOM, &l_mbx8); + if(PCB_ERROR_NONE != l_rc) + { + SBE_ERROR(SBE_FUNC"Failed reading mailbox reg 7, RC: 0x%08X. ", + l_rc); + break; + } + if(l_mbx8 & SBE_MBX8_MBX3_VALID_MASK) + { + // Read MBX3 + l_rc = getscom_abs(PERV_SCRATCH_REGISTER_3_SCOM, &iv_mbx3); + if(PCB_ERROR_NONE != l_rc) + { + SBE_ERROR(SBE_FUNC"Failed reading mailbox reg 3, RC: 0x%08X. ", + l_rc); + break; + } + } + else + { + // Need to read the values off the attributes + uint32_t l_attr = 0; + FAPI_ATTR_GET(ATTR_BOOT_FLAGS, Target(), + l_attr); + iv_mbx3 = ((uint64_t) l_attr ) << 32; + } + if(l_mbx8 & SBE_MBX8_MBX6_VALID_MASK) + { + // Read MBX6 + l_rc = getscom_abs(PERV_SCRATCH_REGISTER_6_SCOM, &iv_mbx6); + if(PCB_ERROR_NONE != l_rc) + { + SBE_ERROR(SBE_FUNC"Failed reading mailbox reg 6, RC: 0x%08X. " + l_rc); + break; + } + } + // If the master/slave bit is 0 (either default or read from mbx6), + // check the C4 board pin to determine role + if(0 == iv_isSlave) + { + uint64_t l_sbeDevIdReg = 0; + // Read device ID register + l_rc = getscom_abs(PERV_DEVICE_ID_REG, &l_sbeDevIdReg); + if(PCB_ERROR_NONE != l_rc) + { + SBE_ERROR(SBE_FUNC"Failed reading device id reg, RC: 0x%08X. " + l_rc); + break; + } + iv_isSlave = l_sbeDevIdReg & SBE_DEV_ID_C4_PIN_MASK; + SBE_INFO(SBE_FUNC"Overriding master/slave with data read from " + "C4 pin: HI: 0x%08X, LO: 0x%08X", + (uint32_t)(l_sbeDevIdReg >> 32), + (uint32_t)(l_sbeDevIdReg & 0xFFFFFFFF)); + } + } while(false); + + SBE_INFO(SBE_FUNC"Read mailbox registers: mbx8: 0x%08X, mbx3: 0x%08X, " + "mbx6: 0x%08X", (uint32_t)(l_mbx8 >> 32), + (uint32_t)(iv_mbx3 >> 32), (uint32_t)(iv_mbx6 >> 32)); + l_initDone = true; + return l_rc; + #undef SBE_FUNC +} + +/** + * @brief Update the SBE states into the SBE messaging register. The + * function does a read-modify-write, so any bits other than the state + * bits are preserved. The current state of the register is set to + * i_state, whereas the old current state is copied to previous state + * + * @param [in] i_state The current SBE state + * + * @return RC indicating success/failure. + * + */ +uint32_t SbeRegAccess::updateSbeState(const sbeState &i_state) +{ + #define SBE_FUNC "SbeRegAccess::updateSbeState " + uint32_t l_rc = 0; + + iv_prevState = iv_currState; + iv_currState = i_state; + l_rc = putscom_abs(PERV_SB_MSG_SCOM, iv_messagingReg); + if(PCB_ERROR_NONE != l_rc) + { + SBE_ERROR(SBE_FUNC"Failed to update state to messaging " + "register. RC: 0x%08X", l_rc); + } + return l_rc; + #undef SBE_FUNC +} + +/** + * @brief Update the SBE IPL steps into the SBE messaging register. The + * function does a read-modify-write, so any bits other than the IPL + * steps are retianed + * + * @param [in] i_major IPL major step number + * @param [in] i_minor IPL minor step number + * + * @return RC indicating success/failure. + * + */ +uint32_t SbeRegAccess::updateSbeStep(const uint8_t i_major, + const uint8_t i_minor) +{ + #define SBE_FUNC "SbeRegAccess::updateSbeStep " + uint32_t l_rc = 0; + + iv_majorStep = i_major; + iv_minorStep = i_minor; + + l_rc = putscom_abs(PERV_SB_MSG_SCOM, iv_messagingReg); + if(l_rc) + { + SBE_ERROR(SBE_FUNC"Failed to update SBE step to messaging " + "register. RC: 0x%08X", l_rc); + } + return l_rc; + #undef SBE_FUNC +} + +/** + * @brief Set the SBE ready bit into the SBE messaging register + * (meaning that SBE control loop is initialized) The function does a + * read-modify-write, so any bits other than the SBE ready bit remain + * unchanged. + * + * @return RC indicating success/failure. + * + */ +uint32_t SbeRegAccess::setSbeReady() +{ + #define SBE_FUNC "SbeRegAccess::setSbeReady " + uint32_t l_rc = 0; + + iv_sbeBooted = true; + l_rc = putscom_abs(PERV_SB_MSG_SCOM, iv_messagingReg); + if(l_rc) + { + SBE_ERROR(SBE_FUNC"Failed to update SBE ready state to " + "messaging register. RC: 0x%08X", l_rc); + } + return l_rc; + #undef SBE_FUNC +} + + +/** + * @brief Set the MPIPL mode bit into the mailbox scratch reg. 3 + * The function does a read-modify-write, so any bits other than the + * SBE ready bit remain unchanged. + * + * @param i_set [in] Whether to set or clear the MPIPL flag + * + * @return RC indicating success/failure. + * + */ +uint32_t SbeRegAccess::setMpIplMode(const bool i_set) +{ + #define SBE_FUNC "SbeRegAccess::setMpIplMode" + uint32_t l_rc = 0; + uint8_t l_set = i_set; + iv_mpiplMode = i_set; + FAPI_ATTR_SET(ATTR_IS_MPIPL, Target(), l_set); + l_rc = putscom_abs(PERV_SCRATCH_REGISTER_3_SCOM, iv_mbx3); + if(l_rc) + { + SBE_ERROR(SBE_FUNC"Failed to set/clear MPIPL flag in " + "mbx reg. 3. RC: 0x%08X", l_rc); + } + return l_rc; + #undef SBE_FUNC +} + diff --git a/src/sbefw/sberegaccess.H b/src/sbefw/sberegaccess.H new file mode 100644 index 00000000..84e2c87e --- /dev/null +++ b/src/sbefw/sberegaccess.H @@ -0,0 +1,266 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sberegaccess.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sberegaccess.H + * + * @brief This file contains interfaces to get/set FW flags either in the + * scratch registers and/or the FW attributes. + */ + +#ifndef __SBEFW_SBEREGACCESS_H +#define __SBEFW_SBEREGACCESS_H + +#include +#include "sbestates.H" +#include "sbeevents.H" + +/** + * @brief Utility singleton that SBEFW can use to read write various scratch + * registers/FW attributes + * TODO: via RTC ??????: Need to change the read of scratch registers to FAPI + * attribute accesses once we have the attributes defined in the HWP code. + */ +class SbeRegAccess +{ + public: + // Disable copy construction and assignment operators + SbeRegAccess(const SbeRegAccess&) = delete; + SbeRegAccess& operator=(const SbeRegAccess&) = delete; + + /** + * @brief Returns the instance of this class + * + * @return A reference to SbeRegAccess + * + */ + static SbeRegAccess& theSbeRegAccess() + { + static SbeRegAccess iv_instance; + return iv_instance; + } + + /** + * @brief Initializes the class for use + * + * @return An RC indicating success/failure + * + */ + uint32_t init(); + + /** + * @brief Update the SBE states into the SBE messaging register. The + * function does a read-modify-write, so any bits other than the state + * bits are preserved. The current state of the register is set to + * i_state, whereas the old current state is copied to previous state + * + * @param [in] i_state The current SBE state + * + * @return RC indicating success/failure. + * + */ + uint32_t updateSbeState(const sbeState &i_state); + + /** + * @brief Update the SBE IPL steps into the SBE messaging register. The + * function does a read-modify-write, so any bits other than the IPL + * steps are retianed + * + * @param [in] i_major IPL major step number + * @param [in] i_minor IPL minor step number + * + * @return RC indicating success/failure. + * + */ + uint32_t updateSbeStep(const uint8_t i_major, const uint8_t i_minor); + + /** + * @brief Set the SBE ready bit into the SBE messaging register + * (meaning that SBE control loop is initialized) The function does a + * read-modify-write, so any bits other than the SBE ready bit remain + * unchanged. + * + * @return RC indicating success/failure. + * + */ + uint32_t setSbeReady(); + + /** + * @brief Set the MPIPL mode bit into the mailbox scratch reg. 3 + * The function does a read-modify-write, so any bits other than the + * SBE ready bit remain unchanged. It also updates the attribute + * ATTR_MPIPL + * + * @param i_set [in] true == set, false == clear + * + * @return RC indicating success/failure. + * + */ + uint32_t setMpIplMode(const bool i_set); + + /** + * @brief Check if we are on an FSP attached + * + * @return true if FSP attached system, false otherwise + * + */ + inline bool isFspSystem() const + { + return iv_fspAttached; + } + + /** + * @brief Check if we are in ISTEP IPL mode + * + * @return true if in istep mode, false otherwise + * + */ + inline bool isIstepMode() const + { + return iv_istepMode; + } + + /** + * @brief Check if SBE should directly go to runtime state + * + * @return true if SBE should go directly to runtime state, + * false otherwise + * + */ + inline bool isDestBitRuntime() const + { + return iv_sbeDestRuntime; + } + + /** + * @brief Check if SBE should collect FFDC + * + * @return true if in istep mode, false otherwise + * + */ + inline bool isCollectFFDCSet() const + { + return iv_collectFFDC; + } + + /** + * @brief Check if SBE should send internal FFDC for any chip op + * failures as a part of the response + * + * @return true if in istep mode, false otherwise + * + */ + inline bool isSendInternalFFDCSet() const + { + return iv_sendFFDC; + } + + /** + * @brief Check if SBE is slave/master + * + * @return true if SBE is slave, false if master + * + */ + inline bool isSbeSlave() const + { + return iv_isSlave; + } + + /** + * @brief Get the SBE current State + * + * @return SBE current State, sbeState enum + * + */ + uint64_t getSbeState() const + { + return iv_currState; + } + + /** + * @brief Update the SBE State as per the transition event + * + * @param [in] i_event Transition Event + */ + void stateTransition(const sbeEvent &i_event); + + private: + + /** + * @brief Constructor + */ + SbeRegAccess() : iv_mbx3(0), iv_mbx6(0), iv_messagingReg(0) + {} + + union + { + struct + { + uint64_t iv_istepMode : 1; + uint64_t iv_sbeDestRuntime : 1; + uint64_t iv_mpiplMode : 1; + uint64_t iv_fspAttached : 1; + uint64_t iv_collectFFDC : 1; + uint64_t iv_sendFFDC : 1; + uint64_t iv_mbx3DontCare : 26; + uint64_t iv_mbx3Unused : 32; + }; + uint64_t iv_mbx3; + }; + + union + { + struct + { + uint64_t iv_mbx6DontCare : 24; + uint64_t iv_isSlave : 1; + uint64_t iv_mbx6DontCare2 : 7; + uint64_t iv_mbx6Unused : 32; + }; + uint64_t iv_mbx6; + }; + + union + { + struct + { + uint64_t iv_sbeBooted : 1; + uint64_t iv_reserved1 : 3; + uint64_t iv_prevState : 4; + uint64_t iv_currState : 4; + uint64_t iv_majorStep : 4; + uint64_t iv_minorStep : 8; + uint64_t iv_reserved2 : 8; + uint64_t iv_unused : 32; + }; + uint64_t iv_messagingReg; + }; + + // Bit masks defining bits in the above registers that the SBE is + // interested in + static const uint64_t SBE_MBX8_MBX3_VALID_MASK = 0x2000000000000000ULL; + static const uint64_t SBE_MBX8_MBX6_VALID_MASK = 0x0400000000000000ULL; + static const uint64_t SBE_DEV_ID_C4_PIN_MASK = 0x0000000000800000ULL; +}; +#endif //__SBEFW_SBEREGACCESS_H + diff --git a/src/sbefw/sbescom.C b/src/sbefw/sbescom.C new file mode 100644 index 00000000..9a2fc38c --- /dev/null +++ b/src/sbefw/sbescom.C @@ -0,0 +1,198 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbescom.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ + +#include +#include "sbe_sp_intf.H" +#include "sbetrace.H" +#include "ppe42_scom.h" + +/** + * @brief Indirect SCOM Status + */ +union IndirectScom_t +{ + uint64_t data64; + struct + { + uint64_t :12; //0:11 + uint64_t addr:20; //12:31 + uint64_t done:1; //32 + uint64_t piberr:3; //33:35 + uint64_t userstat:4; //36:39 + uint64_t :8; //40:47 + uint64_t data:16; //48:63 + }; + +}; + +// Wait time slice to check indirect scom status register +static const uint32_t SBE_INDIRECT_SCOM_WAIT_TIME_NS = 10000; +// Indirect scom timeout +static const uint32_t MAX_INDSCOM_TIMEOUT_NS = 100000; //0.1 ns + +static const uint64_t DIRECT_SCOM_ADDR_MASK = 0x8000000000000000; +static const uint64_t INDIRECT_SCOM_NEW_ADDR_MASK = 0x9000000000000000; + +// Scom types +enum sbeScomType +{ + SBE_SCOM_TYPE_DIRECT = 0, // Direct scom + SBE_SCOM_TYPE_INDIRECT1 = 1, // Indirect scom. Old form + SBE_SCOM_TYPE_INDIRECT_2 = 2, // Indirect scom. New form +}; + +uint32_t checkIndirectAndDoScom( const bool i_isRead, + const uint64_t i_addr, + uint64_t & io_data, + uint32_t & o_pcbPibStatus ) +{ + + #define SBE_FUNC " checkIndirectAndDoScom " + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t elapsedIndScomTimeNs = 0; + uint64_t tempBuffer = io_data; + sbeScomType scomType = SBE_SCOM_TYPE_DIRECT; + do + { + // If the indirect scom bit is 0, then doing a regular scom + if( (i_addr & DIRECT_SCOM_ADDR_MASK) == 0) + { + SBE_INFO(SBE_FUNC "Performing Direct scom"); + if( i_isRead ) + { + o_pcbPibStatus = getscom_abs ( (uint32_t)i_addr, + & io_data); + } + else + { + o_pcbPibStatus = putscom_abs ( (uint32_t)i_addr, + io_data); + } + break; + } + // We are performing an indirect scom. + if( ( i_addr & INDIRECT_SCOM_NEW_ADDR_MASK ) == + INDIRECT_SCOM_NEW_ADDR_MASK ) + { + scomType = SBE_SCOM_TYPE_INDIRECT_2; + if( i_isRead ) + { + // Not allowed write on new format. + SBE_ERROR(SBE_FUNC "Read not allowed in new form"); + l_rc = SBE_SEC_INVALID_ADDRESS_PASSED; + break; + } + // Zero out the indirect address location.. leave the 52bits of data + // Get the 12bit indirect scom address + // OR in the 20bit indirect address + tempBuffer = ( tempBuffer & 0x000FFFFFFFFFFFFF ) | + ( ( i_addr & 0x00000FFF00000000) << 20 ); + } + else + { + scomType = SBE_SCOM_TYPE_INDIRECT1; + // Zero out the indirect address location.. leave the 16bits of data + // Get the 20bit indirect scom address + // OR in the 20bit indirect address + tempBuffer = ( tempBuffer & 0x000000000000FFFF) | + ( i_addr & 0x000FFFFF00000000 ); + } + + SBE_INFO(SBE_FUNC "Performing Indirect scom. Type :%u", scomType); + + // zero out the indirect address from the buffer.. + // bit 0-31 - indirect area.. + // bit 32 - always 0 + // bit 33-47 - bcast/chipletID/port + // bit 48-63 - local addr + uint64_t tempAddr = i_addr & 0x000000007FFFFFFF; + + // If we are doing a read. We need to do a write first.. + if( i_isRead) + { + // turn the read bit on. + tempBuffer = tempBuffer | 0x8000000000000000; + } + else //write + { + // Turn the read bit off. + tempBuffer = tempBuffer & 0x7FFFFFFFFFFFFFFF; + + } // end of write + + // perform write before the read with the new + // IO_buffer with the imbedded indirect scom addr. + o_pcbPibStatus = putscom_abs ( tempAddr, tempBuffer); + + if( ( o_pcbPibStatus ) || ( scomType == SBE_SCOM_TYPE_INDIRECT_2 )) + { + break; + } + + // Need to check loop on read until we see done, error, + // or we timeout + IndirectScom_t scomout; + do + { + // Now perform the op requested using the passed in + // IO_Buffer to pass the read data back to caller. + o_pcbPibStatus = getscom_abs ( tempAddr, &(scomout.data64)); + + if( o_pcbPibStatus ) break; + // if bit 32 is on indicating a complete bit + // or we saw an error, then we're done + if (scomout.piberr) + { + + SBE_ERROR(SBE_FUNC "pib error reading status register"); + o_pcbPibStatus = scomout.piberr; + break; + } + if (scomout.done ) + { + io_data = scomout.data; + break; + } + + pk_sleep(PK_NANOSECONDS(SBE_INDIRECT_SCOM_WAIT_TIME_NS)); + elapsedIndScomTimeNs += SBE_INDIRECT_SCOM_WAIT_TIME_NS; + + }while ( elapsedIndScomTimeNs <= MAX_INDSCOM_TIMEOUT_NS); + + if( o_pcbPibStatus ) break; + if( ! scomout.done) + { + SBE_ERROR(SBE_FUNC "Indirect scom timeout"); + l_rc = SBE_SEC_HW_OP_TIMEOUT; + break; + } + + }while(0); + + if (o_pcbPibStatus ) l_rc = SBE_SEC_PCB_PIB_ERR; + + SBE_DEBUG(SBE_FUNC "o_pcbPibStatus:%u l_rc:0x%08X", o_pcbPibStatus, l_rc); + return l_rc; +} + diff --git a/src/sbefw/sbescom.H b/src/sbefw/sbescom.H new file mode 100644 index 00000000..3809ba10 --- /dev/null +++ b/src/sbefw/sbescom.H @@ -0,0 +1,38 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbescom.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ + +/** + * @brief check if scom address is Indirect scom and perform scom + * + * @param[in] i_isRead True if read operation, false otherwise + * @param[in] i_addr scom addess + * @param[in] io_data data for scom operation. For read, it is output operand. + * @param[in] o_pcbPibStatus pcbpib status + * + * @return seconday error code. + */ +uint32_t checkIndirectAndDoScom( const bool i_isRead, + const uint64_t i_addr, + uint64_t & io_data, + uint32_t & o_pcbPibStatus ); diff --git a/src/sbefw/sbestates.H b/src/sbefw/sbestates.H new file mode 100644 index 00000000..6acaba4d --- /dev/null +++ b/src/sbefw/sbestates.H @@ -0,0 +1,67 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbestates.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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/sbestates.H + * + * @brief This file contains interfaces pertaining to SBE state/role management + * + */ + +#ifndef __SBEFW_SBESTATES_H +#define __SBEFW_SBESTATES_H + +/** + * @brief An enumeration of all SBE states + * + */ +enum sbeState +{ + SBE_STATE_UNKNOWN = 0x0, // Unkown, initial state + SBE_STATE_FFDC_COLLECT = 0x1, // Waiting for FFDC collection after a reset + SBE_STATE_IPLING = 0x2, // IPL'ing - autonomous mode (transient) + SBE_STATE_ISTEP = 0x3, // ISTEP - Running IPL by steps (transient) + SBE_STATE_RUNTIME = 0x4, // SBE Runtime + SBE_STATE_MPIPL = 0x5, // MPIPL + SBE_STATE_DMT = 0x6, // Dead Man Timer State (transient) + SBE_STATE_DUMP = 0x7, // Dumping + SBE_STATE_FAILURE = 0x8, // Internal SBE failure + SBE_STATE_QUIESCE = 0x9, // Final state - needs SBE reset to get out + SBE_STATE_ABORT = 0xA, // SBE was asked to abort - need reset to get out + + // Max States, Always keep it at the last of the enum and sequential + SBE_MAX_STATE = 0xB, + // Don't count this in the state, just to intialize the state variables + SBE_INVALID_STATE = 0xF, +}; + +enum sbeRole +{ + SBE_ROLE_MASTER = 0, + SBE_ROLE_SLAVE = 1 +}; + +extern sbeRole g_sbeRole; + +#endif //__SBEFW_SBESTATES_H + diff --git a/src/sbefw/sbetrace.H b/src/sbefw/sbetrace.H new file mode 100644 index 00000000..1d7df7e4 --- /dev/null +++ b/src/sbefw/sbetrace.H @@ -0,0 +1,75 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbetrace.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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 */ +#ifndef __SBEFW_SBE_TRACE_H +#define __SBEFW_SBE_TRACE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pk_api.h" +#include "trac_interface.h" + +#ifdef __cplusplus +} +#endif + +#define SBE_ENTER_MRK ">>" +#define SBE_EXIT_MRK "<<" +#define SBE_ERR_MRK "E>" +#define SBE_INF_MRK "I>" +#define SBE_DEBUG_MRK "D>" + +#define SBE_ERROR(args...) +#define SBE_INFO(args...) +#define SBE_ENTER(args...) +#define SBE_EXIT(args...) +#define SBE_DEBUG(args...) + +// Levels of logging +// 0 - No tracing +// 1 - Error +// 2 - Error, info +// 3 - Error, info, entry/exit +// 4 - Error, info, entry/exit, debug +#if (SBE_TRACE_LEVEL >= 1) +#undef SBE_ERROR +#define SBE_ERROR(args...) PK_TRACE(SBE_ERR_MRK"" args) +#endif +#if (SBE_TRACE_LEVEL >= 2) +#undef SBE_INFO +#define SBE_INFO(args...) PK_TRACE(SBE_INF_MRK"" args) +#endif +#if (SBE_TRACE_LEVEL >= 3) +#undef SBE_ENTER +#undef SBE_EXIT +#define SBE_ENTER(args...) PK_TRACE(SBE_ENTER_MRK"" args) +#define SBE_EXIT(args...) PK_TRACE(SBE_EXIT_MRK"" args) +#endif +#if (SBE_TRACE_LEVEL >= 4) +#undef SBE_DEBUG +#define SBE_DEBUG(args...) PK_TRACE(SBE_DEBUG_MRK"" args) +#endif +#define SBE_TRACE(args...) PK_TRACE(args) +#endif // __SBEFW_SBE_TRACE_H diff --git a/src/sbefw/sbeutil.H b/src/sbefw/sbeutil.H new file mode 100644 index 00000000..07fc6b7f --- /dev/null +++ b/src/sbefw/sbeutil.H @@ -0,0 +1,81 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbeutil.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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 */ +#ifndef SBE_UTIL_H +#define SBE_UTIL_H +#include "pk.h" +#include "pk_api.h" + +#define MASK_ZERO_L32B_UINT64(x) ((x) & 0xFFFFFFFF00000000) +#define MASK_ZERO_H32B_UINT64(x) ((x) & 0x00000000FFFFFFFF) +#define SHIFT_RIGHT(x, bits) ((x) >> bits) + +// Macros Defined for Internal RC Check, Break if Error +#define CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc) \ +if ((l_rc) != SBE_SEC_OPERATION_SUCCESSFUL) \ +{ \ + break; \ +} \ + +void sbeHandleFifoResponse (const uint32_t i_rc); + +void sbeHandlePsuResponse (const uint32_t i_rc); + +namespace SBE +{ + + // Currently PK does not define start range for app + // specifc panic code as enum. It is implicit understanding + // through code comments. Expectation is 0x1cxx range is for + // non-pk code. + static const uint32_t PK_APP_OFFSET_SBE_START = 0x1c00; + enum + { + // For defining new panic codes refer to pk/ppe42/pk_panic_codes.h + PANIC_ASSERT = PK_APP_OFFSET_SBE_START + }; + + /*@brief - Get higher 32bit number from uint64 + * + * @param[in] - i_lWord - 64bit long word + * + * @return - uint32_t word + */ + inline uint32_t higher32BWord(uint64_t i_lWord) + { + return (uint32_t)(SHIFT_RIGHT(MASK_ZERO_L32B_UINT64(i_lWord), 32)); + } + + /*@brief - Get lower 32bit number from uint64 + * + * @param[in] - i_lWord - 64bit long word + * + * @return - uint32_t word + */ + inline uint32_t lower32BWord(uint64_t i_lWord) + { + return (uint32_t)(MASK_ZERO_H32B_UINT64(i_lWord)); + } + +} // namespace SBE +#endif //SBE_UTIL_H diff --git a/src/sbefw/vector b/src/sbefw/vector new file mode 100644 index 00000000..5929f85f --- /dev/null +++ b/src/sbefw/vector @@ -0,0 +1,397 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/vector $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ + +#ifndef stl_vector +#define stl_vector + +/** + * @file vector + * @brief simple stl vector template class declaration. + */ + +#include + +#if !defined( __STDC_LIMIT_MACROS) +#define __STDC_LIMIT_MACROS +#endif +#include +#include +#include +#include +namespace std +{ + + /** + * @class vector + * subset of stl vector + * @note Does not support allocators, reverse iterators. + */ + template + class vector + { + public: + + typedef T * iterator; + typedef const T * const_iterator; + typedef T & reference; + typedef const T & const_reference; + typedef size_t size_type; + typedef T value_type; + typedef T * pointer; + typedef const T * const_pointer; + + protected: + + pointer iv_start __attribute__ ((aligned (8))); + pointer iv_finish; + SBEVECTORPOOL::vectorMemPool_t *iv_poolPtr; + public: + + /** + * Constructor default + * @post The vector is created with storage of + * G_BLOCKSIZE bytes. + */ + explicit vector(void) + { + iv_poolPtr = SBEVECTORPOOL::allocMem(); + assert ( NULL != iv_poolPtr) + iv_start = ( T* )iv_poolPtr->data; + iv_finish = iv_start; + } + + + /** + * MOVE COPY CTOR create a vector from another vector + * @param[in] x source vector + * @post Vector of x.size() is created from x with same + * memory. + * size() == capacity() == x.size() + * @note move Copy construtor willuse shallow copy. So input + * as well as output vector will point to same data + */ + vector(const vector&& x) + { + iv_start = x.iv_start; + iv_finish = x.iv_finish; + iv_poolPtr = x.iv_poolPtr; + iv_poolPtr->refCount++; + } + + /** + * Reserve space for atleast n elements + * @param[in] n Number of elements + * @note We are having fixed size vectors in ppe. Defining + * this function to avoid compile issues in standard + * library. This function is noop for less than 512 + * bytes requirement. For more than 512 bytes, it will + * assert. + */ + void reserve(size_type n) + { + assert(n < max_size()); + return; + } + /** + * DTOR + * @post Storage released + */ + __attribute__ ((always_inline)) + ~vector() + { + clear(); // call dtors + SBEVECTORPOOL::releaseMem(iv_poolPtr); + } + + /** + * Move Assignment operator. + * @param[in] x A vector. + * @return A vector (for the purpose of multiple assigns). + * @pre None. + * @post *this == x, this->capacity() == x.size(). + * All previously obtained iterators are invalid. + */ + vector& operator=(const vector&& x) + { + // Just check here for pool to make sure + // input vector and current vector are not same; + if( iv_poolPtr != x.iv_poolPtr) + { + clear(); + SBEVECTORPOOL::releaseMem(iv_poolPtr); + iv_start = x.iv_start; + iv_finish = x.iv_finish; + iv_poolPtr = x.iv_poolPtr; + iv_poolPtr->refCount++; + } + return(*this); + } + + // Iterators -------------------- + + /** + * Get iterator to the first vector element + * @return iterator of rist vector element + * @pre None. + * @post None. + */ + __attribute__ ((always_inline)) + iterator begin() + { + return (iv_start); + } + + /** + * Get const_iterator to the first vector element + * @return const_iterator of rist vector element + * @pre None. + * @post None. + */ + __attribute__ ((always_inline)) + const_iterator begin() const + { + return (iv_start); + } + + /** + * Get iterator to the last vector element + 1 + * @return iterator + * @pre None. + * @post None. + */ + __attribute__ ((always_inline)) + iterator end() + { + return (iv_finish); + } + + /** + * Get const_iterator to the last vector element + 1 + * @return const_iterator + * @pre None. + * @post None. + */ + __attribute__ ((always_inline)) + const_iterator end() const + { + return (iv_finish); + } + + // Capacity ----------------------------------------------- + + /** + * Get the number of elements in the container + * @return number of elements in the container + */ + __attribute__ ((always_inline)) + size_type size() const + { + return(iv_finish - iv_start); + } + + /** + * Return the maximum potential size the container could reach. + * @return number of the maximum element count this container + * could reach + */ + __attribute__ ((always_inline)) + size_type max_size() const + { + return SBEVECTORPOOL::G_BLOCKSIZE/(sizeof(T)); + } + + /** + * Query for empty container + * @return bool, true if size()==0 else false. + * @pre none + * @post none + */ + __attribute__ ((always_inline)) + bool empty() const + { + return(size() == 0); + } + + // - Element Access ----------------------------------- + + /** + * Access a mutable reference to an element in the container + * @param An index into the vector + * @return A reference to an element + * @pre 0 <= n < size() + * @post None. + */ + __attribute__ ((always_inline)) + reference operator[](size_type n) + { + assert(n < size()); + return(*(iv_start + n)); + } + + /** + * Access a mutable reference to an element in the container + * @param[in] index An index into the vector + * @return A reference to an element + * @pre 0 <= n < size() + * @post None. + * @note no exception handling + */ + __attribute__ ((always_inline)) + reference at(size_type index) + { + assert(index < size()); + return(*(iv_start + index)); + } + + /** + * Get an immutable reference to an element in the container + * @param[in] index An index into the vector + * @return A const_reference to an object or type T + * @pre 0 <= n < size() + * @post None. + */ + __attribute__ ((always_inline)) + const_reference operator[](size_type index) const + { + assert(index < size()); + return(*(iv_start + index)); + } + + /** + * Get an immutable reference to an element in the container + * @param[in] index An index into the vector + * @return A const_reference to an object or type T + * @pre 0 <= n < size() + * @post None. + * @note no exception handling + */ + __attribute__ ((always_inline)) + const_reference at(size_type index) const + { + assert(index < size()); + return(*(iv_start + index)); + } + + /** + * Get a mutable reference to the first element in the container + * @return reference to first element + * @pre none + * @post None + */ + __attribute__ ((always_inline)) + reference front() + { + return *iv_start; + } + + /** + * Get an Immutable reference to the first element in the + * container + * @return const_reference to first element + * @pre none + * @post None + */ + __attribute__ ((always_inline)) + const_reference front() const + { + return *iv_start; + } + + /** + * Get a mutable reference to the last element in the container + * @return reference to last element + * @pre none + * @post None + */ + __attribute__ ((always_inline)) + reference back() + { + return *(iv_finish-1); + } + + /** + * Get an Immutable reference to the last element in the + * container + * @return reference to last element + * @pre none + * @post None + */ + __attribute__ ((always_inline)) + const_reference back() const + { + return *(iv_finish-1); + } + + /** + * Add element to the back of the container + * @param[in] x reference to object used to create new element + * @pre none + * @post All previously obtained iterators are invalid. + */ + __attribute__ ((always_inline)) + void push_back(const T& x) + { + assert(max_size() > size()); + new (iv_finish++) T(x); + } + + /** + * Clear the vector + * @pre none. + * @post size() = 0, All previously obtained iterators are + * invalid + * @note capacity unchanged + */ + void clear () + { + while(iv_finish != iv_start) + { + --iv_finish; + (iv_finish)->~T(); + } + } + + /* + * Assign new content to the vector object + * @param[in] n number of elements to assign + * @param[in] x reference to element to copy in + */ + void assign ( size_type n, const T& x) + { + assert(n < max_size()); + clear(); + for ( ; n> 0; n--) + push_back( x); + } + + private: + vector(const vector& x); + vector& operator=(const vector& x); +}; + +}; // end namespace std + + +#endif +/* vim: set filetype=cpp : */ -- cgit v1.2.1